1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.reflect.generics.reflectiveObjects; 27 28 import sun.reflect.generics.tree.FieldTypeSignature; 29 30 import java.lang.reflect.MalformedParameterizedTypeException; 31 import java.lang.reflect.Method; 32 import java.lang.reflect.ParameterizedType; 33 import java.lang.reflect.Type; 34 import java.lang.reflect.TypeVariable; 35 import java.util.Arrays; 36 import java.util.Objects; 37 38 /** Implementing class for ParameterizedType interface. */ 39 40 public class ParameterizedTypeImpl implements ParameterizedType { 41 private Type[] actualTypeArguments; 42 private Class<?> rawType; 43 private Type ownerType; 44 45 private ParameterizedTypeImpl(Class<?> rawType, 46 Type[] actualTypeArguments, 47 Type ownerType) { 48 this.actualTypeArguments = actualTypeArguments; 49 this.rawType = rawType; 50 this.ownerType = (ownerType != null) ? ownerType : rawType.getDeclaringClass(); 51 validateConstructorArguments(); 52 } 53 54 private void validateConstructorArguments() { 55 TypeVariable/*<?>*/[] formals = rawType.getTypeParameters(); 56 // check correct arity of actual type args 57 if (formals.length != actualTypeArguments.length){ 58 throw new MalformedParameterizedTypeException(); 59 } 60 for (int i = 0; i < actualTypeArguments.length; i++) { 61 // check actuals against formals' bounds 62 } 63 } 64 65 /** 66 * Static factory. Given a (generic) class, actual type arguments 67 * and an owner type, creates a parameterized type. 68 * This class can be instantiated with a a raw type that does not 69 * represent a generic type, provided the list of actual type 70 * arguments is empty. 71 * If the ownerType argument is null, the declaring class of the 72 * raw type is used as the owner type. 73 * <p> This method throws a MalformedParameterizedTypeException 74 * under the following circumstances: 75 * If the number of actual type arguments (i.e., the size of the 76 * array <tt>typeArgs</tt>) does not correspond to the number of 77 * formal type arguments. 78 * If any of the actual type arguments is not an instance of the 79 * bounds on the corresponding formal. 80 * @param rawType the Class representing the generic type declaration being 81 * instantiated 82 * @param actualTypeArguments - a (possibly empty) array of types 83 * representing the actual type arguments to the parameterized type 84 * @param ownerType - the enclosing type, if known. 85 * @return An instance of <tt>ParameterizedType</tt> 86 * @throws MalformedParameterizedTypeException - if the instantiation 87 * is invalid 88 */ 89 public static ParameterizedTypeImpl make(Class<?> rawType, 90 Type[] actualTypeArguments, 91 Type ownerType) { 92 return new ParameterizedTypeImpl(rawType, actualTypeArguments, 93 ownerType); 94 } 95 96 97 /** 98 * Returns an array of <tt>Type</tt> objects representing the actual type 99 * arguments to this type. 100 * 101 * <p>Note that in some cases, the returned array be empty. This can occur 102 * if this type represents a non-parameterized type nested within 103 * a parameterized type. 104 * 105 * @return an array of <tt>Type</tt> objects representing the actual type 106 * arguments to this type 107 * @throws <tt>TypeNotPresentException</tt> if any of the 108 * actual type arguments refers to a non-existent type declaration 109 * @throws <tt>MalformedParameterizedTypeException</tt> if any of the 110 * actual type parameters refer to a parameterized type that cannot 111 * be instantiated for any reason 112 * @since 1.5 113 */ 114 public Type[] getActualTypeArguments() { 115 return actualTypeArguments.clone(); 116 } 117 118 /** 119 * Returns the <tt>Type</tt> object representing the class or interface 120 * that declared this type. 121 * 122 * @return the <tt>Type</tt> object representing the class or interface 123 * that declared this type 124 */ 125 public Class<?> getRawType() { 126 return rawType; 127 } 128 129 130 /** 131 * Returns a <tt>Type</tt> object representing the type that this type 132 * is a member of. For example, if this type is <tt>O<T>.I<S></tt>, 133 * return a representation of <tt>O<T></tt>. 134 * 135 * <p>If this type is a top-level type, <tt>null</tt> is returned. 136 * 137 * @return a <tt>Type</tt> object representing the type that 138 * this type is a member of. If this type is a top-level type, 139 * <tt>null</tt> is returned 140 * @throws <tt>TypeNotPresentException</tt> if the owner type 141 * refers to a non-existent type declaration 142 * @throws <tt>MalformedParameterizedTypeException</tt> if the owner type 143 * refers to a parameterized type that cannot be instantiated 144 * for any reason 145 * 146 */ 147 public Type getOwnerType() { 148 return ownerType; 149 } 150 151 /* 152 * From the JavaDoc for java.lang.reflect.ParameterizedType 153 * "Instances of classes that implement this interface must 154 * implement an equals() method that equates any two instances 155 * that share the same generic type declaration and have equal 156 * type parameters." 157 */ 158 @Override 159 public boolean equals(Object o) { 160 if (o instanceof ParameterizedType) { 161 // Check that information is equivalent 162 ParameterizedType that = (ParameterizedType) o; 163 164 if (this == that) 165 return true; 166 167 Type thatOwner = that.getOwnerType(); 168 Type thatRawType = that.getRawType(); 169 170 if (false) { // Debugging 171 boolean ownerEquality = (ownerType == null ? 172 thatOwner == null : 173 ownerType.equals(thatOwner)); 174 boolean rawEquality = (rawType == null ? 175 thatRawType == null : 176 rawType.equals(thatRawType)); 177 178 boolean typeArgEquality = Arrays.equals(actualTypeArguments, // avoid clone 179 that.getActualTypeArguments()); 180 for (Type t : actualTypeArguments) { 181 System.out.printf("\t\t%s%s%n", t, t.getClass()); 182 } 183 184 System.out.printf("\towner %s\traw %s\ttypeArg %s%n", 185 ownerEquality, rawEquality, typeArgEquality); 186 return ownerEquality && rawEquality && typeArgEquality; 187 } 188 189 return 190 Objects.equals(ownerType, thatOwner) && 191 Objects.equals(rawType, thatRawType) && 192 Arrays.equals(actualTypeArguments, // avoid clone 193 that.getActualTypeArguments()); 194 } else 195 return false; 196 } 197 198 @Override 199 public int hashCode() { 200 return 201 Arrays.hashCode(actualTypeArguments) ^ 202 Objects.hashCode(ownerType) ^ 203 Objects.hashCode(rawType); 204 } 205 206 public String toString() { 207 StringBuilder sb = new StringBuilder(); 208 209 if (ownerType != null) { 210 if (ownerType instanceof Class) 211 sb.append(((Class)ownerType).getName()); 212 else 213 sb.append(ownerType.toString()); 214 215 sb.append("."); 216 217 if (ownerType instanceof ParameterizedTypeImpl) { 218 // Find simple name of nested type by removing the 219 // shared prefix with owner. 220 sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$", 221 "")); 222 } else 223 sb.append(rawType.getName()); 224 } else 225 sb.append(rawType.getName()); 226 227 if (actualTypeArguments != null && 228 actualTypeArguments.length > 0) { 229 sb.append("<"); 230 boolean first = true; 231 for(Type t: actualTypeArguments) { 232 if (!first) 233 sb.append(", "); 234 sb.append(t.getTypeName()); 235 first = false; 236 } 237 sb.append(">"); 238 } 239 240 return sb.toString(); 241 } 242 }