/** * @return either a class or an interface (parameterized or not), if no bounds declared Object is returned. */ public Type firstBound() { return typeVariable.getBounds()[0]; // }
/** * On a Type Variable (typeVar extends C_0 & I_1 & I_2 & etc), will return an array * containing I_1 and I_2. * * @return other bounds for this type, these bounds can only be only interfaces as the JLS says, * empty array if no other bound declared. */ public Type[] interfaceBounds() { Type[] interfaceBounds = new Type[typeVariable.getBounds().length - 1]; System.arraycopy(typeVariable.getBounds(), 1, interfaceBounds, 0, typeVariable.getBounds().length - 1); return interfaceBounds; }
@Override void visitTypeVariable(TypeVariable<?> t) { result.set(subtypeOfComponentType(t.getBounds())); }
@Override void visitTypeVariable(TypeVariable<?> t) { visit(t.getBounds()); }
@Override TypeVariable<?> captureAsTypeVariable(Type[] upperBounds) { Set<Type> combined = new LinkedHashSet<>(asList(upperBounds)); // Since this is an artifically generated type variable, we don't bother checking // subtyping between declared type bound and actual type bound. So it's possible that we // may generate something like <capture#1-of ? extends Foo&SubFoo>. // Checking subtype between declared and actual type bounds // adds recursive isSubtypeOf() call and feels complicated. // There is no contract one way or another as long as isSubtypeOf() works as expected. combined.addAll(asList(typeParam.getBounds())); if (combined.size() > 1) { // Object is implicit and only useful if it's the only bound. combined.remove(Object.class); } return super.captureAsTypeVariable(combined.toArray(new Type[0])); } };
/** * @param typeParameter The TypeVariable parameter * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable * then retrieve BoundedType of this TypeVariable */ private BoundedType boundsOf(TypeVariable<?> typeParameter) { if (typeParameter.getBounds()[0] instanceof TypeVariable) { return boundsOf((TypeVariable<?>) typeParameter.getBounds()[0]); } return new TypeVarBoundedType(typeParameter); }
private static WildcardType canonicalizeWildcardType( TypeVariable<?> declaration, WildcardType type) { Type[] declared = declaration.getBounds(); List<Type> upperBounds = new ArrayList<>(); for (Type bound : type.getUpperBounds()) { if (!any(declared).isSubtypeOf(bound)) { upperBounds.add(canonicalizeWildcardsInType(bound)); } } return new Types.WildcardTypeImpl(type.getLowerBounds(), upperBounds.toArray(new Type[0])); }
TypeParameterSignature(TypeVariable<?> typeParameter) { name = typeParameter.getName(); bounds = Arrays.asList(typeParameter.getBounds()); }
@Override void visitTypeVariable(TypeVariable<?> t) { visit(t.getBounds()); } }.visit(type);
private static void assertEqualTypeVariable(TypeVariable<?> expected, TypeVariable<?> actual) { assertEquals(expected.toString(), actual.toString()); assertEquals(expected.getName(), actual.getName()); assertEquals(expected.getGenericDeclaration(), actual.getGenericDeclaration()); if (!Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) { assertEquals(actual.toString(), expected.hashCode(), actual.hashCode()); } assertThat(actual.getBounds()) .asList() .containsExactlyElementsIn(asList(expected.getBounds())) .inOrder(); }
public void testWithGenericBoundInTypeVariable() throws Exception { TypeVariable<?> typeVariable = (TypeVariable<?>) new WithGenericBound<String>() {}.getTargetType("withTypeVariable"); assertEquals(String.class, typeVariable.getBounds()[0]); }
public void testWithMutualRecursiveBoundInTypeVariable() throws Exception { ParameterizedType paramType = (ParameterizedType) new WithGenericBound<String>() {}.getTargetType("withMutualRecursiveBound"); TypeVariable<?> k = (TypeVariable<?>) paramType.getActualTypeArguments()[0]; TypeVariable<?> v = (TypeVariable<?>) paramType.getActualTypeArguments()[1]; assertEquals(Types.newParameterizedType(List.class, v), k.getBounds()[0]); assertEquals(Types.newParameterizedType(List.class, k), v.getBounds()[0]); }
private void readTypeVariables() { for (Type type : typeVariable.getBounds()) { registerTypeVariablesOn(type); } registerTypeParametersOn(new TypeVariable[] { typeVariable }); registerTypeVariablesOn(getActualTypeArgumentFor(typeVariable)); }
@Test public void typeVariableType() throws Exception { TypeVariable<?> type = (TypeVariable<?>) SerializableTypeWrapper.forField(Fields.class.getField("typeVariableType")); assertThat(type.toString(), equalTo("T")); assertSerializable(type); assertSerializable(type.getBounds()); }
public void testWildcardCaptured_typeVariableDeclaresTypeBound_wildcardHasExplicitUpperBound() throws Exception { TypeToken<Counter<? extends Number>> type = new TypeToken<Counter<? extends Number>>() {}; TypeToken<?> fieldType = type.resolveType(Counter.class.getDeclaredField("counts").getGenericType()); Type[] typeArgs = ((ParameterizedType) fieldType.getType()).getActualTypeArguments(); assertThat(typeArgs).asList().hasSize(1); TypeVariable<?> captured = (TypeVariable<?>) typeArgs[0]; assertThat(captured.getBounds()).asList().containsExactly(Number.class); assertThat(new TypeToken<List<? extends Number>>() {}.isSupertypeOf(fieldType)).isTrue(); assertThat(new TypeToken<List<? extends Iterable<?>>>() {}.isSupertypeOf(fieldType)).isFalse(); }
public void testWithRecursiveBoundInTypeVariable() throws Exception { TypeVariable<?> typeVariable = (TypeVariable<?>) new WithGenericBound<String>() {}.getTargetType("withRecursiveBound"); assertEquals(Types.newParameterizedType(Enum.class, typeVariable), typeVariable.getBounds()[0]); }
public void testWildcardCaptured_typeVariableDeclaresTypeBound_wildcardHasNoExplicitUpperBound() throws Exception { TypeToken<Counter<?>> type = new TypeToken<Counter<?>>() {}; TypeToken<?> fieldType = type.resolveType(Counter.class.getDeclaredField("counts").getGenericType()); Type[] typeArgs = ((ParameterizedType) fieldType.getType()).getActualTypeArguments(); assertThat(typeArgs).asList().hasSize(1); TypeVariable<?> captured = (TypeVariable<?>) typeArgs[0]; assertThat(captured.getBounds()).asList().containsExactly(Number.class); assertThat(new TypeToken<List<? extends Number>>() {}.isSupertypeOf(fieldType)).isTrue(); assertThat(new TypeToken<List<? extends Iterable<?>>>() {}.isSupertypeOf(fieldType)).isFalse(); }
public void testWildcardCaptured_wildcardWithExplicitBound() throws Exception { TypeToken<Holder<? extends Number>> type = new TypeToken<Holder<? extends Number>>() {}; ImmutableList<Parameter> parameters = type.method(Holder.class.getDeclaredMethod("setList", List.class)).getParameters(); assertThat(parameters).hasSize(1); TypeToken<?> parameterType = parameters.get(0).getType(); Type[] typeArgs = ((ParameterizedType) parameterType.getType()).getActualTypeArguments(); assertThat(typeArgs).asList().hasSize(1); TypeVariable<?> captured = (TypeVariable<?>) typeArgs[0]; assertThat(captured.getBounds()).asList().containsExactly(Number.class); assertThat(new TypeToken<List<? extends Number>>() {}.isSupertypeOf(parameterType)).isTrue(); }
public void testWildcardCaptured_wildcardWithImplicitBound() throws Exception { TypeToken<Holder<?>> type = new TypeToken<Holder<?>>() {}; ImmutableList<Parameter> parameters = type.method(Holder.class.getDeclaredMethod("setList", List.class)).getParameters(); assertThat(parameters).hasSize(1); TypeToken<?> parameterType = parameters.get(0).getType(); Type[] typeArgs = ((ParameterizedType) parameterType.getType()).getActualTypeArguments(); assertThat(typeArgs).asList().hasSize(1); TypeVariable<?> captured = (TypeVariable<?>) typeArgs[0]; assertThat(captured.getBounds()).asList().containsExactly(Object.class); assertThat(new TypeToken<List<?>>() {}.isSupertypeOf(parameterType)).isTrue(); }
public void testWildcardCaptured_typeVariableDeclaresTypeBound_wildcardAddsNewUpperBound() throws Exception { TypeToken<Counter<? extends Iterable<?>>> type = new TypeToken<Counter<? extends Iterable<?>>>() {}; TypeToken<?> fieldType = type.resolveType(Counter.class.getDeclaredField("counts").getGenericType()); Type[] typeArgs = ((ParameterizedType) fieldType.getType()).getActualTypeArguments(); assertThat(typeArgs).asList().hasSize(1); TypeVariable<?> captured = (TypeVariable<?>) typeArgs[0]; assertThat(captured.getBounds()).asList().contains(Number.class); assertThat(captured.getBounds()) .asList() .containsNoneOf(Object.class, new TypeToken<Iterable<Number>>() {}.getType()); assertThat(new TypeToken<List<? extends Number>>() {}.isSupertypeOf(fieldType)).isTrue(); assertThat(new TypeToken<List<? extends Iterable<?>>>() {}.isSupertypeOf(fieldType)).isTrue(); assertThat(new TypeToken<List<? extends Iterable<Number>>>() {}.isSupertypeOf(fieldType)) .isFalse(); }