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 * Gets the basic type of array, that is, for int[][][] the basic type is int. 097 * 098 * @return basic type of array, that is, for int[][][] the basic type is int. 099 */ 100 public Type getBasicType() { 101 return basicType; 102 } 103 104 /** 105 * Gets the name of referenced class. 106 * 107 * @return name of referenced class. 108 * @since 6.7.0 109 */ 110 @Override 111 public String getClassName() { 112 return signature; 113 } 114 115 /** 116 * Gets the number of dimensions of array. 117 * 118 * @return number of dimensions of array. 119 */ 120 public int getDimensions() { 121 return dimensions; 122 } 123 124 /** 125 * Gets the element type of array, that is, for int[][][] the element type is int[][]. 126 * 127 * @return element type of array, that is, for int[][][] the element type is int[][]. 128 */ 129 public Type getElementType() { 130 if (dimensions == 1) { 131 return basicType; 132 } 133 return new ArrayType(basicType, dimensions - 1); 134 } 135 136 /** 137 * @return a hash code value for the object. 138 */ 139 @Override 140 public int hashCode() { 141 return basicType.hashCode() ^ dimensions; 142 } 143}