[LANG-906] new type util features
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1510300 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
eb45c596a8
commit
019256539d
|
@ -18,6 +18,7 @@ package org.apache.commons.lang3.reflect;
|
|||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.GenericDeclaration;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
|
@ -29,7 +30,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.ClassUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.Builder;
|
||||
|
||||
/**
|
||||
* <p> Utility methods focusing on type inspection, particularly with regard to
|
||||
|
@ -40,6 +45,156 @@ import org.apache.commons.lang3.ClassUtils;
|
|||
*/
|
||||
public class TypeUtils {
|
||||
|
||||
/**
|
||||
* {@link WildcardType} builder.
|
||||
*/
|
||||
public static class WildcardTypeBuilder implements Builder<WildcardType> {
|
||||
private WildcardTypeBuilder() {
|
||||
}
|
||||
|
||||
private Type[] upperBounds;
|
||||
private Type[] lowerBounds;
|
||||
|
||||
public WildcardTypeBuilder withUpperBounds(Type... bounds) {
|
||||
this.upperBounds = bounds;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WildcardTypeBuilder withLowerBounds(Type... bounds) {
|
||||
this.lowerBounds = bounds;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WildcardType build() {
|
||||
return new WildcardTypeImpl(upperBounds, lowerBounds);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class GenericArrayTypeImpl implements GenericArrayType {
|
||||
private final Type componentType;
|
||||
|
||||
private GenericArrayTypeImpl(Type componentType) {
|
||||
this.componentType = componentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getGenericComponentType() {
|
||||
return componentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return TypeUtils.toString(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj == this || obj instanceof GenericArrayType && TypeUtils.equals(this, (GenericArrayType) obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 67 << 4;
|
||||
result |= componentType.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ParameterizedTypeImpl implements ParameterizedType {
|
||||
private final Class<?> raw;
|
||||
private final Type useOwner;
|
||||
private final Type[] typeArguments;
|
||||
|
||||
private ParameterizedTypeImpl(Class<?> raw, Type useOwner, Type[] typeArguments) {
|
||||
this.raw = raw;
|
||||
this.useOwner = useOwner;
|
||||
this.typeArguments = typeArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRawType() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOwnerType() {
|
||||
return useOwner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getActualTypeArguments() {
|
||||
return typeArguments.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return TypeUtils.toString(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj == this || obj instanceof ParameterizedType && TypeUtils.equals(this, ((ParameterizedType) obj));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 71 << 4;
|
||||
result |= raw.hashCode();
|
||||
result <<= 4;
|
||||
result |= ObjectUtils.hashCode(useOwner);
|
||||
result <<= 8;
|
||||
result |= Arrays.hashCode(typeArguments);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class WildcardTypeImpl implements WildcardType {
|
||||
private static final Type[] EMPTY_BOUNDS = new Type[0];
|
||||
|
||||
private final Type[] upperBounds;
|
||||
private final Type[] lowerBounds;
|
||||
|
||||
private WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
|
||||
this.upperBounds = ObjectUtils.defaultIfNull(upperBounds, EMPTY_BOUNDS);
|
||||
this.lowerBounds = ObjectUtils.defaultIfNull(lowerBounds, EMPTY_BOUNDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getUpperBounds() {
|
||||
return upperBounds.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getLowerBounds() {
|
||||
return lowerBounds.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return TypeUtils.toString(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj == this || obj instanceof WildcardType && TypeUtils.equals(this, (WildcardType) obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 73 << 8;
|
||||
result |= Arrays.hashCode(upperBounds);
|
||||
result <<= 8;
|
||||
result |= Arrays.hashCode(lowerBounds);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A wildcard instance matching {@code ?}.
|
||||
*/
|
||||
public static final WildcardType WILDCARD_ALL = wildcardType().withUpperBounds(Object.class).build();
|
||||
|
||||
/**
|
||||
* <p> TypeUtils instances should NOT be constructed in standard
|
||||
* programming. Instead, the class should be used as
|
||||
|
@ -1098,4 +1253,365 @@ public class TypeUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a type representing {@code type} with variable assignments "unrolled."
|
||||
*
|
||||
* @param typeArguments as from {@link TypeUtils#getTypeArguments(Type, Class)}
|
||||
* @param type
|
||||
* @return Type
|
||||
*/
|
||||
public static Type unrollVariables(Map<TypeVariable<?>, Type> typeArguments, final Type type) {
|
||||
if (containsTypeVariables(type)) {
|
||||
if (type instanceof TypeVariable<?>) {
|
||||
return unrollVariables(typeArguments, typeArguments.get(type));
|
||||
}
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType p = (ParameterizedType) type;
|
||||
final Map<TypeVariable<?>, Type> parameterizedTypeArguments;
|
||||
if (p.getOwnerType() == null) {
|
||||
parameterizedTypeArguments = typeArguments;
|
||||
} else {
|
||||
parameterizedTypeArguments = new HashMap<TypeVariable<?>, Type>(typeArguments);
|
||||
parameterizedTypeArguments.putAll(TypeUtils.getTypeArguments(p));
|
||||
}
|
||||
final Type[] args = p.getActualTypeArguments();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
final Type unrolled = unrollVariables(parameterizedTypeArguments, args[i]);
|
||||
if (unrolled != null) {
|
||||
args[i] = unrolled;
|
||||
}
|
||||
}
|
||||
return parameterizeWithOwner(p.getOwnerType(), (Class<?>) p.getRawType(), args);
|
||||
}
|
||||
if (type instanceof WildcardType) {
|
||||
final WildcardType wild = (WildcardType) type;
|
||||
return wildcardType().withUpperBounds(unrollBounds(typeArguments, wild.getUpperBounds()))
|
||||
.withLowerBounds(unrollBounds(typeArguments, wild.getLowerBounds())).build();
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static Type[] unrollBounds(final Map<TypeVariable<?>, Type> typeArguments, final Type[] bounds) {
|
||||
Type[] result = bounds;
|
||||
int i = 0;
|
||||
for (; i < result.length; i++) {
|
||||
final Type unrolled = unrollVariables(typeArguments, result[i]);
|
||||
if (unrolled == null) {
|
||||
result = ArrayUtils.remove(result, i--);
|
||||
} else {
|
||||
result[i] = unrolled;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Learn, recursively, whether any of the type parameters associated with {@code type} are bound to variables.
|
||||
*
|
||||
* @param type
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean containsTypeVariables(Type type) {
|
||||
if (type instanceof TypeVariable<?>) {
|
||||
return true;
|
||||
}
|
||||
if (type instanceof Class<?>) {
|
||||
return ((Class<?>) type).getTypeParameters().length > 0;
|
||||
}
|
||||
if (type instanceof ParameterizedType) {
|
||||
for (Type arg : ((ParameterizedType) type).getActualTypeArguments()) {
|
||||
if (containsTypeVariables(arg)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (type instanceof WildcardType) {
|
||||
WildcardType wild = (WildcardType) type;
|
||||
return containsTypeVariables(TypeUtils.getImplicitLowerBounds(wild)[0])
|
||||
|| containsTypeVariables(TypeUtils.getImplicitUpperBounds(wild)[0]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a parameterized type instance.
|
||||
*
|
||||
* @param raw
|
||||
* @param typeArguments
|
||||
* @return {@link ParameterizedType}
|
||||
*/
|
||||
public static final ParameterizedType parameterize(final Class<?> raw, final Type... typeArguments) {
|
||||
return parameterizeWithOwner(null, raw, typeArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a parameterized type instance.
|
||||
*
|
||||
* @param raw
|
||||
* @param typeArgMappings
|
||||
* @return {@link ParameterizedType}
|
||||
*/
|
||||
public static final ParameterizedType parameterize(final Class<?> raw,
|
||||
final Map<TypeVariable<?>, Type> typeArgMappings) {
|
||||
return parameterizeWithOwner(null, raw, extractTypeArgumentsFrom(typeArgMappings, raw.getTypeParameters()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a parameterized type instance.
|
||||
*
|
||||
* @param owner
|
||||
* @param raw
|
||||
* @param typeArguments
|
||||
*
|
||||
* @return {@link ParameterizedType}
|
||||
*/
|
||||
public static final ParameterizedType parameterizeWithOwner(final Type owner, final Class<?> raw,
|
||||
final Type... typeArguments) {
|
||||
Validate.notNull(raw, "raw class");
|
||||
final Type useOwner;
|
||||
if (raw.getEnclosingClass() == null) {
|
||||
Validate.isTrue(owner == null, "no owner allowed for top-level %s", raw);
|
||||
useOwner = null;
|
||||
} else if (owner == null) {
|
||||
useOwner = raw.getEnclosingClass();
|
||||
} else {
|
||||
Validate.isTrue(TypeUtils.isAssignable(owner, raw.getEnclosingClass()),
|
||||
"%s is invalid owner type for parameterized %s", owner, raw);
|
||||
useOwner = owner;
|
||||
}
|
||||
Validate.isTrue(raw.getTypeParameters().length == Validate.noNullElements(typeArguments,
|
||||
"null type argument at index %s").length);
|
||||
|
||||
return new ParameterizedTypeImpl(raw, useOwner, typeArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a parameterized type instance.
|
||||
*
|
||||
* @param owner
|
||||
* @param raw
|
||||
* @param typeArgMappings
|
||||
* @return {@link ParameterizedType}
|
||||
*/
|
||||
public static final ParameterizedType parameterizeWithOwner(final Type owner, final Class<?> raw,
|
||||
final Map<TypeVariable<?>, Type> typeArgMappings) {
|
||||
return parameterizeWithOwner(owner, raw, extractTypeArgumentsFrom(typeArgMappings, raw.getTypeParameters()));
|
||||
}
|
||||
|
||||
private static Type[] extractTypeArgumentsFrom(Map<TypeVariable<?>, Type> mappings, TypeVariable<?>[] variables) {
|
||||
final Type[] result = new Type[variables.length];
|
||||
int index = 0;
|
||||
for (TypeVariable<?> var : variables) {
|
||||
Validate.isTrue(mappings.containsKey(var), "missing argument mapping for %s", toString(var));
|
||||
result[index++] = mappings.get(var);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a {@link WildcardTypeBuilder}.
|
||||
* @return {@link WildcardTypeBuilder}
|
||||
*/
|
||||
public static WildcardTypeBuilder wildcardType() {
|
||||
return new WildcardTypeBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a generic array type instance.
|
||||
*
|
||||
* @param componentType
|
||||
* @return {@link GenericArrayType}
|
||||
*/
|
||||
public static GenericArrayType genericArrayType(final Type componentType) {
|
||||
return new GenericArrayTypeImpl(componentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check equality of types.
|
||||
*
|
||||
* @param t1
|
||||
* @param t2
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean equals(Type t1, Type t2) {
|
||||
if (ObjectUtils.equals(t1, t2)) {
|
||||
return true;
|
||||
}
|
||||
if (t1 instanceof ParameterizedType) {
|
||||
return equals((ParameterizedType) t1, t2);
|
||||
}
|
||||
if (t1 instanceof GenericArrayType) {
|
||||
return equals((GenericArrayType) t1, t2);
|
||||
}
|
||||
if (t1 instanceof WildcardType) {
|
||||
return equals((WildcardType) t1, t2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean equals(ParameterizedType p, Type t) {
|
||||
if (t instanceof ParameterizedType) {
|
||||
final ParameterizedType other = (ParameterizedType) t;
|
||||
if (equals(p.getRawType(), other.getRawType()) && equals(p.getOwnerType(), other.getOwnerType())) {
|
||||
return equals(p.getActualTypeArguments(), other.getActualTypeArguments());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean equals(GenericArrayType a, Type t) {
|
||||
return t instanceof GenericArrayType
|
||||
&& equals(a.getGenericComponentType(), ((GenericArrayType) t).getGenericComponentType());
|
||||
}
|
||||
|
||||
private static boolean equals(WildcardType w, Type t) {
|
||||
if (t instanceof WildcardType) {
|
||||
final WildcardType other = (WildcardType) t;
|
||||
return equals(w.getLowerBounds(), other.getLowerBounds())
|
||||
&& equals(TypeUtils.getImplicitUpperBounds(w), TypeUtils.getImplicitUpperBounds(other));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean equals(Type[] t1, Type[] t2) {
|
||||
if (t1.length == t2.length) {
|
||||
for (int i = 0; i < t1.length; i++) {
|
||||
if (!equals(t1[i], t2[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Present a given type as a Java-esque String.
|
||||
*
|
||||
* @param type
|
||||
* @return String
|
||||
*/
|
||||
public static String toString(Type type) {
|
||||
Validate.notNull(type);
|
||||
if (type instanceof Class<?>) {
|
||||
return classToString((Class<?>) type);
|
||||
}
|
||||
if (type instanceof ParameterizedType) {
|
||||
return parameterizedTypeToString((ParameterizedType) type);
|
||||
}
|
||||
if (type instanceof WildcardType) {
|
||||
return wildcardTypeToString((WildcardType) type);
|
||||
}
|
||||
if (type instanceof TypeVariable<?>) {
|
||||
return typeVariableToString((TypeVariable<?>) type);
|
||||
}
|
||||
if (type instanceof GenericArrayType) {
|
||||
return genericArrayTypeToString((GenericArrayType) type);
|
||||
}
|
||||
throw new IllegalArgumentException(ObjectUtils.identityToString(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a {@link TypeVariable} including its {@link GenericDeclaration}.
|
||||
*
|
||||
* @param var
|
||||
* @return String
|
||||
*/
|
||||
public static String toLongString(TypeVariable<?> var) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final GenericDeclaration d = ((TypeVariable<?>) var).getGenericDeclaration();
|
||||
if (d instanceof Class<?>) {
|
||||
Class<?> c = (Class<?>) d;
|
||||
while (true) {
|
||||
if (c.getEnclosingClass() == null) {
|
||||
buf.insert(0, c.getName());
|
||||
break;
|
||||
}
|
||||
buf.insert(0, c.getSimpleName()).insert(0, '.');
|
||||
c = c.getEnclosingClass();
|
||||
}
|
||||
} else if (d instanceof Type) {// not possible as of now
|
||||
buf.append(toString((Type) d));
|
||||
} else {
|
||||
buf.append(d);
|
||||
}
|
||||
return buf.append(':').append(typeVariableToString(var)).toString();
|
||||
}
|
||||
|
||||
private static String classToString(Class<?> c) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
|
||||
if (c.getEnclosingClass() != null) {
|
||||
buf.append(classToString(c.getEnclosingClass())).append('.').append(c.getSimpleName());
|
||||
} else {
|
||||
buf.append(c.getName());
|
||||
}
|
||||
if (c.getTypeParameters().length > 0) {
|
||||
buf.append('<');
|
||||
appendAllTo(buf, ", ", c.getTypeParameters());
|
||||
buf.append('>');
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static String typeVariableToString(TypeVariable<?> v) {
|
||||
final StringBuilder buf = new StringBuilder(v.getName());
|
||||
final Type[] bounds = v.getBounds();
|
||||
if (bounds.length > 0 && !(bounds.length == 1 && Object.class.equals(bounds[0]))) {
|
||||
buf.append(" extends ");
|
||||
appendAllTo(buf, " & ", v.getBounds());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static String parameterizedTypeToString(ParameterizedType p) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
|
||||
final Type useOwner = p.getOwnerType();
|
||||
final Class<?> raw = (Class<?>) p.getRawType();
|
||||
final Type[] typeArguments = p.getActualTypeArguments();
|
||||
if (useOwner == null) {
|
||||
buf.append(raw.getName());
|
||||
} else {
|
||||
if (useOwner instanceof Class<?>) {
|
||||
buf.append(((Class<?>) useOwner).getName());
|
||||
} else {
|
||||
buf.append(useOwner.toString());
|
||||
}
|
||||
buf.append('.').append(raw.getSimpleName());
|
||||
}
|
||||
|
||||
appendAllTo(buf.append('<'), ", ", typeArguments).append('>');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static String wildcardTypeToString(WildcardType w) {
|
||||
final StringBuilder buf = new StringBuilder().append('?');
|
||||
final Type[] lowerBounds = w.getLowerBounds();
|
||||
final Type[] upperBounds = w.getUpperBounds();
|
||||
if (lowerBounds.length > 0) {
|
||||
appendAllTo(buf.append(" super "), " & ", lowerBounds);
|
||||
} else if (!(upperBounds.length == 1 && Object.class.equals(upperBounds[0]))) {
|
||||
appendAllTo(buf.append(" extends "), " & ", upperBounds);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static String genericArrayTypeToString(GenericArrayType g) {
|
||||
return String.format("%s[]", toString(g.getGenericComponentType()));
|
||||
}
|
||||
|
||||
private static StringBuilder appendAllTo(StringBuilder buf, String sep, Type... types) {
|
||||
Validate.notEmpty(Validate.noNullElements(types));
|
||||
if (types.length > 0) {
|
||||
buf.append(toString(types[0]));
|
||||
for (int i = 1; i < types.length; i++) {
|
||||
buf.append(sep).append(toString(types[i]));
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,19 +17,25 @@
|
|||
package org.apache.commons.lang3.reflect;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.reflect.TypeUtils.WildcardTypeBuilder;
|
||||
import org.apache.commons.lang3.reflect.testbed.Foo;
|
||||
import org.apache.commons.lang3.reflect.testbed.GenericParent;
|
||||
import org.apache.commons.lang3.reflect.testbed.GenericTypeHolder;
|
||||
|
@ -41,7 +47,7 @@ import org.junit.Test;
|
|||
* Test TypeUtils
|
||||
* @version $Id$
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "unused" , "rawtypes", "null"})
|
||||
@SuppressWarnings({ "unchecked", "unused" , "rawtypes" })
|
||||
//raw types, where used, are used purposely
|
||||
public class TypeUtilsTest<B> {
|
||||
|
||||
|
@ -672,6 +678,44 @@ public class TypeUtilsTest<B> {
|
|||
Assert.assertArrayEquals(expectedArray, TypeUtils.normalizeUpperBounds(typeArray));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterize() throws Exception {
|
||||
final ParameterizedType stringComparableType = TypeUtils.parameterize(Comparable.class, String.class);
|
||||
Assert.assertTrue(TypeUtils.equals(getClass().getField("stringComparable").getGenericType(),
|
||||
stringComparableType));
|
||||
Assert.assertEquals("java.lang.Comparable<java.lang.String>", stringComparableType.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterizeWithOwner() throws Exception {
|
||||
final Type owner = TypeUtils.parameterize(TypeUtilsTest.class, String.class);
|
||||
final ParameterizedType dat2Type = TypeUtils.parameterizeWithOwner(owner, That.class, String.class, String.class);
|
||||
Assert.assertTrue(TypeUtils.equals(getClass().getField("dat2").getGenericType(), dat2Type));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWildcardType() throws Exception {
|
||||
final WildcardType simpleWildcard = TypeUtils.wildcardType().withUpperBounds(String.class).build();
|
||||
final Field cClass = AClass.class.getField("cClass");
|
||||
Assert.assertTrue(TypeUtils.equals(((ParameterizedType) cClass.getGenericType()).getActualTypeArguments()[0],
|
||||
simpleWildcard));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericArrayType() throws Exception {
|
||||
final Type expected = getClass().getField("intWildcardComparable").getGenericType();
|
||||
final GenericArrayType actual =
|
||||
TypeUtils.genericArrayType(TypeUtils.parameterize(Comparable.class, TypeUtils.wildcardType()
|
||||
.withUpperBounds(Integer.class).build()));
|
||||
Assert.assertTrue(TypeUtils.equals(expected, actual));
|
||||
Assert.assertEquals("java.lang.Comparable<? extends java.lang.Integer>[]", actual.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToLongString() {
|
||||
Assert.assertEquals(getClass().getName() + ":B", TypeUtils.toLongString(getClass().getTypeParameters()[0]));
|
||||
}
|
||||
|
||||
public Iterable<? extends Map<Integer, ? extends Collection<?>>> iterable;
|
||||
|
||||
public static <G extends Comparable<G>> G stub() {
|
||||
|
|
Loading…
Reference in New Issue