    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.bcel.generic;
    020
    021import org.apache.bcel.Const;
    022
    023/**
    024 * Denotes array type, such as int[][]
    025 */
    026public final class ArrayType extends ReferenceType {
    027
    028    private final int dimensions;
    029    private final Type basicType;
    030
    031    /**
    032     * Convenience constructor for array type, for example int[]
    033     *
    034     * @param type array type, for example T_INT
    035     * @param dimensions array dimensions
    036     */
    037    public ArrayType(final byte type, final int dimensions) {
    038        this(BasicType.getType(type), dimensions);
    039    }
    040
    041    /**
    042     * Convenience constructor for reference array type, for example Object[]
    043     *
    044     * @param className complete name of class ({@link String}, for example)
    045     * @param dimensions array dimensions
    046     */
    047    public ArrayType(final String className, final int dimensions) {
    048        this(ObjectType.getInstance(className), dimensions);
    049    }
    050
    051    /**
    052     * Constructor for array of given type
    053     *
    054     * @param type type of array (may be an array itself)
    055     * @param dimensions array dimensions
    056     */
    057    public ArrayType(final Type type, final int dimensions) {
    058        super(Const.T_ARRAY, "<dummy>");
    059        if (dimensions < 1 || dimensions > Const.MAX_BYTE) {
    060            throw new ClassGenException("Invalid number of dimensions: " + dimensions);
    061        }
    062        switch (type.getType()) {
    063        case Const.T_ARRAY:
    064            final ArrayType array = (ArrayType) type;
    065            this.dimensions = dimensions + array.dimensions;
    066            basicType = array.basicType;
    067            break;
    068        case Const.T_VOID:
    069            throw new ClassGenException("Invalid type: void[]");
    070        default: // Basic type or reference
    071            this.dimensions = dimensions;
    072            basicType = type;
    073            break;
    074        }
    075        final StringBuilder buf = new StringBuilder();
    076        for (int i = 0; i < this.dimensions; i++) {
    077            buf.append('[');
    078        }
    079        buf.append(basicType.getSignature());
    080        this.signature = buf.toString();
    081    }
    082
    083    /**
    084     * @return true if both type objects refer to the same array type.
    085     */
    086    @Override
    087    public boolean equals(final Object type) {
    088        if (type instanceof ArrayType) {
    089            final ArrayType array = (ArrayType) type;
    090            return array.dimensions == dimensions && array.basicType.equals(basicType);
    091        }
    092        return false;
    093    }
    094
    095    /**
    096     * @return basic type of array, i.e., for int[][][] the basic type is int
    097     */
    098    public Type getBasicType() {
    099        return basicType;
    100    }
    101
    102    /**
    103     * Gets the name of referenced class.
    104     *
    105     * @return name of referenced class.
    106     * @since 6.7.0
    107     */
    108    @Override
    109    public String getClassName() {
    110        return signature;
    111    }
    112
    113    /**
    114     * @return number of dimensions of array
    115     */
    116    public int getDimensions() {
    117        return dimensions;
    118    }
    119
    120    /**
    121     * @return element type of array, i.e., for int[][][] the element type is int[][]
    122     */
    123    public Type getElementType() {
    124        if (dimensions == 1) {
    125            return basicType;
    126        }
    127        return new ArrayType(basicType, dimensions - 1);
    128    }
    129
    130    /**
    131     * @return a hash code value for the object.
    132     */
    133    @Override
    134    public int hashCode() {
    135        return basicType.hashCode() ^ dimensions;
    136    }
    137}