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