    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 *
    017 */
    018package org.apache.bcel.generic;
    019
    020import org.apache.bcel.Const;
    021
    022/**
    023 * Denotes array type, such as int[][]
    024 *
    025 * @version $Id: ArrayType.java 1806200 2017-08-25 16:33:06Z ggregory $
    026 */
    027public final class ArrayType extends ReferenceType {
    028
    029    private int dimensions;
    030    private Type basic_type;
    031
    032
    033    /**
    034     * Convenience constructor for array type, e.g. int[]
    035     *
    036     * @param type array type, e.g. T_INT
    037     */
    038    public ArrayType(final byte type, final int dimensions) {
    039        this(BasicType.getType(type), dimensions);
    040    }
    041
    042
    043    /**
    044     * Convenience constructor for reference array type, e.g. Object[]
    045     *
    046     * @param class_name complete name of class (java.lang.String, e.g.)
    047     */
    048    public ArrayType(final String class_name, final int dimensions) {
    049        this(ObjectType.getInstance(class_name), dimensions);
    050    }
    051
    052
    053    /**
    054     * Constructor for array of given type
    055     *
    056     * @param type type of array (may be an array itself)
    057     */
    058    public ArrayType(final Type type, final int dimensions) {
    059        super(Const.T_ARRAY, "<dummy>");
    060        if ((dimensions < 1) || (dimensions > Const.MAX_BYTE)) {
    061            throw new ClassGenException("Invalid number of dimensions: " + dimensions);
    062        }
    063        switch (type.getType()) {
    064            case Const.T_ARRAY:
    065                final ArrayType array = (ArrayType) type;
    066                this.dimensions = dimensions + array.dimensions;
    067                basic_type = array.basic_type;
    068                break;
    069            case Const.T_VOID:
    070                throw new ClassGenException("Invalid type: void[]");
    071            default: // Basic type or reference
    072                this.dimensions = dimensions;
    073                basic_type = type;
    074                break;
    075        }
    076        final StringBuilder buf = new StringBuilder();
    077        for (int i = 0; i < this.dimensions; i++) {
    078            buf.append('[');
    079        }
    080        buf.append(basic_type.getSignature());
    081        super.setSignature(buf.toString());
    082    }
    083
    084
    085    /**
    086     * @return basic type of array, i.e., for int[][][] the basic type is int
    087     */
    088    public Type getBasicType() {
    089        return basic_type;
    090    }
    091
    092
    093    /**
    094     * @return element type of array, i.e., for int[][][] the element type is int[][]
    095     */
    096    public Type getElementType() {
    097        if (dimensions == 1) {
    098            return basic_type;
    099        }
    100        return new ArrayType(basic_type, dimensions - 1);
    101    }
    102
    103
    104    /** @return number of dimensions of array
    105     */
    106    public int getDimensions() {
    107        return dimensions;
    108    }
    109
    110
    111    /** @return a hash code value for the object.
    112     */
    113    @Override
    114    public int hashCode() {
    115        return basic_type.hashCode() ^ dimensions;
    116    }
    117
    118
    119    /** @return true if both type objects refer to the same array type.
    120     */
    121    @Override
    122    public boolean equals( final Object _type ) {
    123        if (_type instanceof ArrayType) {
    124            final ArrayType array = (ArrayType) _type;
    125            return (array.dimensions == dimensions) && array.basic_type.equals(basic_type);
    126        }
    127        return false;
    128    }
    129}