正如您将在下面看到的那样。我正在编写一个名为Property的类,它可以绑定到任何Serializable类型,从类描述中可以看出。
现在,在编译期间,属性中的值自动绑定为T
类型。
我想实现一个Class getType()
方法,该方法应该在运行时返回值的Class
对象,即
Property<String> p = new Property<String>();
Class<String> cl = p.getType();
这里我希望cl是String.class。当然有一种方法是:
return value == null ? null : value.getClass();
问题是它不会反映在返回的类型中并返回原始类型的Class
对象。
理想情况下,我希望它是Class<String>
public class Property<T extends Serializable> implements Serializable {
private T value = null ;
private String name = null ;
private boolean dirty = false ;
private Entity parent = null ;
public Class getType() {
// Here I want to determine the type of T that this object is bound to ?
return class;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isDirty() {
return dirty;
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
public Entity getParent() {
return parent;
}
public void setParent(Entity parent) {
this.parent = parent;
}
}
答案 0 :(得分:6)
简而言之,您不能,因为在运行时类型为erased。
但是,你可以这样做(缩写为相关代码):
public class Property<T extends Serializable> implements Serializable {
private T value = null;
private final Class<T> clazz;
// The constructor requires an instance of the Class<T>
public Property(Class<T> clazz) {
this.clazz = clazz;
}
// Return a typed Class object
public Class<T> getType() {
return clazz; // echo back a typed Class object pass to the constructor
}
传递给构造函数的Class<T>
对象通常称为“类型标记”。
答案 1 :(得分:1)
你可以写一个方法
public Class<? extends T> getType() {
return value == null ? null : value.getClass();
}
这将返回{em>运行时类型value
,并在编译时提供尽可能多的有关返回类的信息:它将是T
或任何子类T
。
如果你想总是返回Class<T>
,那么你必须提供类作为运行时参数,就像@Bohemian describes一样。由于类型擦除,泛型类的类型参数在运行时不可用。
答案 2 :(得分:1)
由于type erasure,你不可能这样做。一个结果是,用于实例化类型参数的类型不能在运行时直接确定。
以下是两种选择:
1)使用getClass()获取属性的值的类型。
public Class getType() {
return value.getClass();
}
2)明确地将实际类型为T的Class
对象作为构造函数参数传递。请注意,泛型键入意味着您不会意外地传递错误的Class
对象
private T value = null;
private Class<T> type;
public Property(Class<T> type) { this.type = type; }
public Class<T> getType() { this.type; }
还有另一种方法(从设计的角度来看,这可能不会起作用),你可以在这里修改Property类; e.g。
public class IntegerProperty extends Property<Integer> {
public Class getType() {
returns Integer.class;
}
}
这里有一些聪明的变体,其中匿名类中泛型类的子类,和/或您通过getClass().getTypeParameters()
访问类型参数。但请注意,如果您为类型参数扩展了具有特定类型的泛型类,则getTypeParameters()
方法仅可用。