// from GSON project, simplified // (Note: There is a ParameterizedTypeImpl in the JDK, but it is not public // and has a different constructor signature) static persistable final class ParameterizedTypeImpl implements ParameterizedType { private /*final*/ Type ownerType; private /*final*/ Type rawType; private /*final*/ Type[] typeArguments; *(Type *ownerType, Type *rawType, Type... *typeArguments) {} public Type[] getActualTypeArguments() { return typeArguments; } public Type getRawType() { return rawType; } public Type getOwnerType() { return ownerType; } @Override public boolean equals(Object other) { if (other cast ParameterizedType) ret eq(ownerType, other.getOwnerType()) && eq(rawType, other.getRawType()) && eq(asList(typeArguments), asList(other.getActualTypeArguments())); false; } @Override public int hashCode() { return Arrays.hashCode(typeArguments) ^ rawType.hashCode() ^ _hashCode(ownerType); } @Override public String toString() { int length = typeArguments.length; if (length == 0) ret typeToString(rawType); new StringBuilder stringBuilder; stringBuilder.append(typeToString(rawType)).append("<").append(typeToString(typeArguments[0])); for (int i = 1; i < length; i++) { stringBuilder.append(", ").append(typeToString(typeArguments[i])); } ret stringBuilder.append(">").toString(); } static S typeToString(Type type) { return type instanceof Class ? ((Class) type).getName() : type.toString(); } }