0

正如您将在下面看到的。我正在编写一个名为 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;
    }
}
4

3 回答 3

6

简而言之,您不能,因为在运行时该类型已被擦除

但是,您可以这样做(简称为相关代码):

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>对象通常称为“类型令牌”。

于 2012-08-15T09:37:22.907 回答
1

你可以写一个方法

public Class<? extends T> getType() {
    return value == null ? null : value.getClass();
}

这将返回 的运行时类型value,并在编译时尽可能多地提供有关返回的类的信息:它将TT.

如果你想总是 return Class<T>,那么你必须提供类作为运行时参数,就像@Bohemian描述的那样。由于类型擦除,泛型类的类型参数在运行时不可用。

于 2012-08-15T09:39:50.860 回答
1

由于类型擦除,您不可能采用这种方式。一个后果是,用于实例化类型参数的类型不能在运行时直接确定。

这里有几个选择:

1) 使用 getClass() 获取属性值的类型。

    public Class getType() {
        return value.getClass();
    }

2) 显式传递ClassT 的实际类型的对象作为构造函数参数。请注意,泛型类型意味着您不会意外传递错误的Class对象

    private T value = null;
    private Class<T> type;

    public Property(Class<T> type) { this.type = type; }

    public Class<T> getType() { this.type; }

还有另一种方法(从设计的角度来看可能在这里行不通),您可以在其中具体化 Property 类;例如

    public class IntegerProperty extends Property<Integer> {
        public Class getType() {
            returns Integer.class;
        }
    }

有一些巧妙的变体,其中泛型类的子类位于匿名类中,和/或您通过getClass().getTypeParameters(). 但请注意,该getTypeParameters()方法在您为类型参数扩展了具有特定类型的泛型类时才有效。

于 2012-08-15T09:41:47.727 回答