13c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/* 23c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Copyright (C) 2014 The Android Open Source Project 33c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 43c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 53c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * you may not use this file except in compliance with the License. 63c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * You may obtain a copy of the License at 73c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 83c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 93c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Unless required by applicable law or agreed to in writing, software 113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * See the License for the specific language governing permissions and 143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * limitations under the License. 153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpackage android.hardware.camera2.utils; 183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.lang.reflect.Array; 203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.lang.reflect.GenericArrayType; 213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.lang.reflect.ParameterizedType; 223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.lang.reflect.Type; 233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.lang.reflect.TypeVariable; 243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.lang.reflect.WildcardType; 253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport static com.android.internal.util.Preconditions.*; 273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/** 293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Super type token; allows capturing generic types at runtime by forcing them to be reified. 303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>Usage example: <pre>{@code 323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * // using anonymous classes (preferred) 333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * TypeReference<Integer> intToken = new TypeReference<Integer>() {{ }}; 343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * // using named classes 363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * class IntTypeReference extends TypeReference<Integer> {...} 373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * TypeReference<Integer> intToken = new IntTypeReference(); 383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * }</p></pre> 393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>Unlike the reference implementation, this bans nested TypeVariables; that is all 413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * dynamic types must equal to the static types.</p> 423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>See <a href="http://gafter.blogspot.com/2007/05/limitation-of-super-type-tokens.html"> 443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * http://gafter.blogspot.com/2007/05/limitation-of-super-type-tokens.html</a> 453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * for more details.</p> 463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpublic abstract class TypeReference<T> { 483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private final Type mType; 492cdfa261f44182292d07b7b3b1e9fce8376e4df5Ruben Brunk private final int mHash; 503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Create a new type reference for {@code T}. 533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @throws IllegalArgumentException if {@code T}'s actual type contains a type variable 553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @see TypeReference 573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin protected TypeReference() { 593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin ParameterizedType thisType = (ParameterizedType)getClass().getGenericSuperclass(); 603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // extract the "T" from TypeReference<T> 623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin mType = thisType.getActualTypeArguments()[0]; 633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /* 653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Prohibit type references with type variables such as 663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * class GenericListToken<T> extends TypeReference<List<T>> 683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Since the "T" there is not known without an instance of T, type equality would 703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * consider *all* Lists equal regardless of T. Allowing this would defeat 713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * some of the type safety of a type reference. 723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (containsTypeVariable(mType)) { 743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new IllegalArgumentException( 753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin "Including a type variable in a type reference is not allowed"); 763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 772cdfa261f44182292d07b7b3b1e9fce8376e4df5Ruben Brunk mHash = mType.hashCode(); 783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Return the dynamic {@link Type} corresponding to the captured type {@code T}. 823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public Type getType() { 843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return mType; 853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private TypeReference(Type type) { 883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin mType = type; 893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (containsTypeVariable(mType)) { 903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new IllegalArgumentException( 913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin "Including a type variable in a type reference is not allowed"); 923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 932cdfa261f44182292d07b7b3b1e9fce8376e4df5Ruben Brunk mHash = mType.hashCode(); 943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static class SpecializedTypeReference<T> extends TypeReference<T> { 973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public SpecializedTypeReference(Class<T> klass) { 983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin super(klass); 993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @SuppressWarnings("rawtypes") 1033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static class SpecializedBaseTypeReference extends TypeReference { 1043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public SpecializedBaseTypeReference(Type type) { 1053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin super(type); 1063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 1103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Create a specialized type reference from a dynamic class instance, 1113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * bypassing the standard compile-time checks. 1123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>As with a regular type reference, the {@code klass} must not contain 1143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * any type variables.</p> 1153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @param klass a non-{@code null} {@link Class} instance 1173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @return a type reference which captures {@code T} at runtime 1193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @throws IllegalArgumentException if {@code T} had any type variables 1213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 1223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public static <T> TypeReference<T> createSpecializedTypeReference(Class<T> klass) { 1233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return new SpecializedTypeReference<T>(klass); 1243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 1273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Create a specialized type reference from a dynamic {@link Type} instance, 1283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * bypassing the standard compile-time checks. 1293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>As with a regular type reference, the {@code type} must not contain 1313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * any type variables.</p> 1323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @param type a non-{@code null} {@link Type} instance 1343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @return a type reference which captures {@code T} at runtime 1363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @throws IllegalArgumentException if {@code type} had any type variables 1383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 1393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public static TypeReference<?> createSpecializedTypeReference(Type type) { 1403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return new SpecializedBaseTypeReference(type); 1413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 1443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Returns the raw type of T. 1453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p><ul> 1473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <li>If T is a Class itself, T itself is returned. 1483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <li>If T is a ParameterizedType, the raw type of the parameterized type is returned. 1493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <li>If T is a GenericArrayType, the returned type is the corresponding array class. 1503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * For example: {@code List<Integer>[]} => {@code List[]}. 1513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <li>If T is a type variable or a wildcard type, the raw type of the first upper bound is 1523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * returned. For example: {@code <X extends Foo>} => {@code Foo}. 1533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * </ul> 1543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @return the raw type of {@code T} 1563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 1573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @SuppressWarnings("unchecked") 1583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public final Class<? super T> getRawType() { 1593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return (Class<? super T>)getRawType(mType); 1603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static final Class<?> getRawType(Type type) { 1633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (type == null) { 1643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new NullPointerException("type must not be null"); 1653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (type instanceof Class<?>) { 1683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return (Class<?>)type; 1693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof ParameterizedType) { 1703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return (Class<?>)(((ParameterizedType)type).getRawType()); 1713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof GenericArrayType) { 1723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return getArrayClass(getRawType(((GenericArrayType)type).getGenericComponentType())); 1733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof WildcardType) { 1743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Should be at most 1 upper bound, but treat it like an array for simplicity 1753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return getRawType(((WildcardType) type).getUpperBounds()); 1763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof TypeVariable) { 1773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError("Type variables are not allowed in type references"); 1783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else { 1793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Impossible 1803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError("Unhandled branch to get raw type for type " + type); 1813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static final Class<?> getRawType(Type[] types) { 1853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (types == null) { 1863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return null; 1873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin for (Type type : types) { 1903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Class<?> klass = getRawType(type); 1913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (klass != null) { 1923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return klass; 1933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return null; 1973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static final Class<?> getArrayClass(Class<?> componentType) { 2003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return Array.newInstance(componentType, 0).getClass(); 2013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 2023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 2043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Get the component type, e.g. {@code T} from {@code T[]}. 2053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 2063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @return component type, or {@code null} if {@code T} is not an array 2073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 2083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public TypeReference<?> getComponentType() { 2093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Type componentType = getComponentType(mType); 2103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return (componentType != null) ? 2123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin createSpecializedTypeReference(componentType) : 2133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin null; 2143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 2153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static Type getComponentType(Type type) { 2173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin checkNotNull(type, "type must not be null"); 2183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (type instanceof Class<?>) { 2203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return ((Class<?>) type).getComponentType(); 2213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof ParameterizedType) { 2223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return null; 2233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof GenericArrayType) { 2243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return ((GenericArrayType)type).getGenericComponentType(); 2253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof WildcardType) { 2263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Should be at most 1 upper bound, but treat it like an array for simplicity 2273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new UnsupportedOperationException("TODO: support wild card components"); 2283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof TypeVariable) { 2293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError("Type variables are not allowed in type references"); 2303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else { 2313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Impossible 2323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError("Unhandled branch to get component type for type " + type); 2333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 2343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 2353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 2373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Compare two objects for equality. 2383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 2393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>A TypeReference is only equal to another TypeReference if their captured type {@code T} 2403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * is also equal.</p> 2413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 2423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 2433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public boolean equals(Object o) { 2443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Note that this comparison could inaccurately return true when comparing types 2453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // with nested type variables; therefore we ban type variables in the constructor. 2463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return o instanceof TypeReference<?> && mType.equals(((TypeReference<?>)o).mType); 2473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 2483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 2503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * {@inheritDoc} 2513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 2523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 2533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public int hashCode() { 2542cdfa261f44182292d07b7b3b1e9fce8376e4df5Ruben Brunk return mHash; 2553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 2563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 2583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Check if the {@code type} contains a {@link TypeVariable} recursively. 2593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 2603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>Intuitively, a type variable is a type in a type expression that refers to a generic 2613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * type which is not known at the definition of the expression (commonly seen when 2623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * type parameters are used, e.g. {@code class Foo<T>}).</p> 2633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 2643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>See <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4"> 2653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4</a> 2663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * for a more formal definition of a type variable</p>. 2673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 2683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @param type a type object ({@code null} is allowed) 2693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @return {@code true} if there were nested type variables; {@code false} otherwise 2703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 2713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public static boolean containsTypeVariable(Type type) { 2723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (type == null) { 2733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Trivially false 2743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return false; 2753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof TypeVariable<?>) { 2763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /* 2773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * T -> trivially true 2783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 2793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return true; 2803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof Class<?>) { 2813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /* 2823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * class Foo -> no type variable 2833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * class Foo<T> - has a type variable 2843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 2853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * This also covers the case of class Foo<T> extends ... / implements ... 2863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * since everything on the right hand side would either include a type variable T 2873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * or have no type variables. 2883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 2893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Class<?> klass = (Class<?>)type; 2903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Empty array => class is not generic 2923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (klass.getTypeParameters().length != 0) { 2933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return true; 2943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else { 2953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Does the outer class(es) contain any type variables? 2963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 2973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /* 2983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * class Outer<T> { 2993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * class Inner { 3003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * T field; 3013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * } 3023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * } 3033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 3043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * In this case 'Inner' has no type parameters itself, but it still has a type 3053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * variable as part of the type definition. 3063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 3073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return containsTypeVariable(klass.getDeclaringClass()); 3083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 3093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof ParameterizedType) { 3103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /* 3113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * This is the "Foo<T1, T2, T3, ... Tn>" in the scope of a 3123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 3133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * // no type variables here, T1-Tn are known at this definition 3143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * class X extends Foo<T1, T2, T3, ... Tn> 3153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 3163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * // T1 is a type variable, T2-Tn are known at this definition 3173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * class X<T1> extends Foo<T1, T2, T3, ... Tn> 3183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 3193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin ParameterizedType p = (ParameterizedType) type; 3203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // This needs to be recursively checked 3223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin for (Type arg : p.getActualTypeArguments()) { 3233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (containsTypeVariable(arg)) { 3243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return true; 3253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 3263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 3273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return false; 3293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof WildcardType) { 3303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin WildcardType wild = (WildcardType) type; 3313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /* 3333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * This is is the "?" inside of a 3343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 3353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Foo<?> --> unbounded; trivially no type variables 3363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Foo<? super T> --> lower bound; does T have a type variable? 3373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Foo<? extends T> --> upper bound; does T have a type variable? 3383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 3393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /* 3413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * According to JLS 4.5.1 3423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * (http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.5.1): 3433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 3443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * - More than 1 lower/upper bound is illegal 3453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * - Both a lower and upper bound is illegal 3463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 3473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * However, we use this 'array OR array' approach for readability 3483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 3493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return containsTypeVariable(wild.getLowerBounds()) || 3503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin containsTypeVariable(wild.getUpperBounds()); 3513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 3523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return false; 3543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 3553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 3573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * {@inheritDoc} 3583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 3593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 3603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public String toString() { 3613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin StringBuilder builder = new StringBuilder(); 3623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin builder.append("TypeReference<"); 3633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin toString(getType(), builder); 3643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin builder.append(">"); 3653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return builder.toString(); 3673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 3683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static void toString(Type type, StringBuilder out) { 3703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (type == null) { 3713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return; 3723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof TypeVariable<?>) { 3733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // T 3743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin out.append(((TypeVariable<?>)type).getName()); 3753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof Class<?>) { 3763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Class<?> klass = (Class<?>)type; 3773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin out.append(klass.getName()); 3793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin toString(klass.getTypeParameters(), out); 3803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof ParameterizedType) { 3813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // "Foo<T1, T2, T3, ... Tn>" 3823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin ParameterizedType p = (ParameterizedType) type; 3833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin out.append(((Class<?>)p.getRawType()).getName()); 3853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin toString(p.getActualTypeArguments(), out); 3863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (type instanceof GenericArrayType) { 3873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin GenericArrayType gat = (GenericArrayType)type; 3883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin toString(gat.getGenericComponentType(), out); 3903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin out.append("[]"); 3913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else { // WildcardType, BoundedType 3923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // TODO: 3933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin out.append(type.toString()); 3943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 3953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 3963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static void toString(Type[] types, StringBuilder out) { 3983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (types == null) { 3993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return; 4003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } else if (types.length == 0) { 4013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return; 4023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 4033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 4043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin out.append("<"); 4053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 4063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin for (int i = 0; i < types.length; ++i) { 4073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin toString(types[i], out); 4083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (i != types.length - 1) { 4093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin out.append(", "); 4103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 4113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 4123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 4133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin out.append(">"); 4143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 4153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 4163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /** 4173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Check if any of the elements in this array contained a type variable. 4183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 4193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>Empty and null arrays trivially have no type variables.</p> 4203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 4213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @param typeArray an array ({@code null} is ok) of types 4223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @return true if any elements contained a type variable; false otherwise 4233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 4243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static boolean containsTypeVariable(Type[] typeArray) { 4253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (typeArray == null) { 4263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return false; 4273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 4283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 4293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin for (Type type : typeArray) { 4303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (containsTypeVariable(type)) { 4313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return true; 4323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 4333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 4343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 4353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return false; 4363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 4373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin} 438