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}