1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 package org.apache.bcel.generic;
19 
20 import org.apache.bcel.Const;
21 
22 /**
23  * Denotes array type, such as int[][]
24  *
25  * @version $Id$
26  */
27 public final class ArrayType extends ReferenceType {
28 
29     private int dimensions;
30     private Type basic_type;
31 
32 
33     /**
34      * Convenience constructor for array type, e.g. int[]
35      *
36      * @param type array type, e.g. T_INT
37      */
ArrayType(final byte type, final int dimensions)38     public ArrayType(final byte type, final int dimensions) {
39         this(BasicType.getType(type), dimensions);
40     }
41 
42 
43     /**
44      * Convenience constructor for reference array type, e.g. Object[]
45      *
46      * @param class_name complete name of class (java.lang.String, e.g.)
47      */
ArrayType(final String class_name, final int dimensions)48     public ArrayType(final String class_name, final int dimensions) {
49         this(ObjectType.getInstance(class_name), dimensions);
50     }
51 
52 
53     /**
54      * Constructor for array of given type
55      *
56      * @param type type of array (may be an array itself)
57      */
ArrayType(final Type type, final int dimensions)58     public ArrayType(final Type type, final int dimensions) {
59         super(Const.T_ARRAY, "<dummy>");
60         if ((dimensions < 1) || (dimensions > Const.MAX_BYTE)) {
61             throw new ClassGenException("Invalid number of dimensions: " + dimensions);
62         }
63         switch (type.getType()) {
64             case Const.T_ARRAY:
65                 final ArrayType array = (ArrayType) type;
66                 this.dimensions = dimensions + array.dimensions;
67                 basic_type = array.basic_type;
68                 break;
69             case Const.T_VOID:
70                 throw new ClassGenException("Invalid type: void[]");
71             default: // Basic type or reference
72                 this.dimensions = dimensions;
73                 basic_type = type;
74                 break;
75         }
76         final StringBuilder buf = new StringBuilder();
77         for (int i = 0; i < this.dimensions; i++) {
78             buf.append('[');
79         }
80         buf.append(basic_type.getSignature());
81         super.setSignature(buf.toString());
82     }
83 
84 
85     /**
86      * @return basic type of array, i.e., for int[][][] the basic type is int
87      */
getBasicType()88     public Type getBasicType() {
89         return basic_type;
90     }
91 
92 
93     /**
94      * @return element type of array, i.e., for int[][][] the element type is int[][]
95      */
getElementType()96     public Type getElementType() {
97         if (dimensions == 1) {
98             return basic_type;
99         }
100         return new ArrayType(basic_type, dimensions - 1);
101     }
102 
103 
104     /** @return number of dimensions of array
105      */
getDimensions()106     public int getDimensions() {
107         return dimensions;
108     }
109 
110 
111     /** @return a hash code value for the object.
112      */
113     @Override
hashCode()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
equals( final Object _type )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 }
130