当泛型被添加到1.5中时,java.lang.reflect添加了一个Type接口和各种子类型来表示类型。Class类被修改以实现Type来适应1.5之前的类型。从1.5开始,Type子类型可用于新的泛型类型。
这一切都很好。有点尴尬,因为Type必须向下转换才能做任何有用的事情,但通过试验、错误、调整和(自动)测试是可行的。只是在实现时会遇到问题...
如何实现equals和hashCode方法呢?ParameterizedType作为Type的子类型,API描述说:
类的实例必须实现一个equals()方法,该方法将等同于共享相同的泛型类型声明并具有相等类型参数的任何两个实例。
(我想这意味着getActualTypeArguments和getRawType,但不包括getOwnerType?)
我们知道根据java.lang.Object的通用契约,也必须实现hashCode方法,但似乎没有规定该方法应该产生什么值。
除了Class有每个值的不同实例之外,Type的其他子类型似乎都没有提到equals或hashCode。
那么我在equals和hashCode中要放什么呢?
(如果你想知道,我正在尝试用实际类型替换类型参数。因此,如果我在运行时知道TypeVariable T是Class String,那么我就想替换Type,那么List就变成List,T[]就变成String[],List[](可能发生!)就变成List[]等)
或者我必须创建自己的并行类型层次结构(没有复制Type的法律原因),有库吗?
编辑:已经有一些人问我为什么需要这个。确实,为什么要查看泛型类型信息呢?
我开始使用非通用的类/接口类型。(如果您想要参数化类型,例如
通过这种方式,我可以使用高质量的静态类型完成所有工作,没有任何
在我的情况下,具体的用法是序列化。但它也适用于反射的任何其他合理用途,例如测试。
下面是我用于替换的代码的当前状态。
这一切都很好。有点尴尬,因为Type必须向下转换才能做任何有用的事情,但通过试验、错误、调整和(自动)测试是可行的。只是在实现时会遇到问题...
如何实现equals和hashCode方法呢?ParameterizedType作为Type的子类型,API描述说:
类的实例必须实现一个equals()方法,该方法将等同于共享相同的泛型类型声明并具有相等类型参数的任何两个实例。
(我想这意味着getActualTypeArguments和getRawType,但不包括getOwnerType?)
我们知道根据java.lang.Object的通用契约,也必须实现hashCode方法,但似乎没有规定该方法应该产生什么值。
除了Class有每个值的不同实例之外,Type的其他子类型似乎都没有提到equals或hashCode。
那么我在equals和hashCode中要放什么呢?
(如果你想知道,我正在尝试用实际类型替换类型参数。因此,如果我在运行时知道TypeVariable T是Class String,那么我就想替换Type,那么List就变成List,T[]就变成String[],List[](可能发生!)就变成List[]等)
或者我必须创建自己的并行类型层次结构(没有复制Type的法律原因),有库吗?
编辑:已经有一些人问我为什么需要这个。确实,为什么要查看泛型类型信息呢?
我开始使用非通用的类/接口类型。(如果您想要参数化类型,例如
List<String>
,则可以始终添加一层间接性与新类。) 然后我遵循字段或方法。它们可能引用参数化类型。只要它们没有使用通配符,当面对类似于 T
的情况时,我仍然可以确定实际的静态类型。通过这种方式,我可以使用高质量的静态类型完成所有工作,没有任何
instanceof
动态类型检查。在我的情况下,具体的用法是序列化。但它也适用于反射的任何其他合理用途,例如测试。
下面是我用于替换的代码的当前状态。
typeMap
是一个 Map<String,Type>
。以“原样”快照的形式存在。没有进行任何整理 (如果您不相信,请抛出 null;)。 Type substitute(Type type) {
if (type instanceof TypeVariable<?>) {
Type actualType = typeMap.get(((TypeVariable<?>)type).getName());
if (actualType instanceof TypeVariable<?>) { throw null; }
if (actualType == null) {
throw new IllegalArgumentException("Type variable not found");
} else if (actualType instanceof TypeVariable<?>) {
throw new IllegalArgumentException("TypeVariable shouldn't substitute for a TypeVariable");
} else {
return actualType;
}
} else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)type;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
int len = actualTypeArguments.length;
Type[] actualActualTypeArguments = new Type[len];
for (int i=0; i<len; ++i) {
actualActualTypeArguments[i] = substitute(actualTypeArguments[i]);
}
// This will always be a Class, wont it? No higher-kinded types here, thank you very much.
Type actualRawType = substitute(parameterizedType.getRawType());
Type actualOwnerType = substitute(parameterizedType.getOwnerType());
return new ParameterizedType() {
public Type[] getActualTypeArguments() {
return actualActualTypeArguments.clone();
}
public Type getRawType() {
return actualRawType;
}
public Type getOwnerType() {
return actualOwnerType;
}
// Interface description requires equals method.
@Override public boolean equals(Object obj) {
if (!(obj instanceof ParameterizedType)) {
return false;
}
ParameterizedType other = (ParameterizedType)obj;
return
Arrays.equals(this.getActualTypeArguments(), other.getActualTypeArguments()) &&
this.getOwnerType().equals(other.getOwnerType()) &&
this.getRawType().equals(other.getRawType());
}
};
} else if (type instanceof GenericArrayType) {
GenericArrayType genericArrayType = (GenericArrayType)type;
Type componentType = genericArrayType.getGenericComponentType();
Type actualComponentType = substitute(componentType);
if (actualComponentType instanceof TypeVariable<?>) { throw null; }
return new GenericArrayType() {
// !! getTypeName? toString? equals? hashCode?
public Type getGenericComponentType() {
return actualComponentType;
}
// Apparently don't have to provide an equals, but we do need to.
@Override public boolean equals(Object obj) {
if (!(obj instanceof GenericArrayType)) {
return false;
}
GenericArrayType other = (GenericArrayType)obj;
return
this.getGenericComponentType().equals(other.getGenericComponentType());
}
};
} else {
return type;
}
}
toString()
的结果。 - Peter Lawrey<U extends Comparable<U>>
。 - fps