找出T.class而不传递Class <t>参数</t>

时间:2013-07-24 18:11:47

标签: java generics

我正在开发一个类似于JTable的setDefaultRenderer方法的类。我想要Class - 特定的格式化程序,它将对象转换为适合显示的字符串。

public interface Formatter<T> {
    String format(T value);
}

private Map<Class<?>, Formatter<?>> formatters;

public <T> void addFormatter(Formatter<T> formatter) {
    formatters.put(T.class, formatter);
}

这就是我现在的代码,但Java不接受T.class

error: cannot select from a type variable
        formatters.put(T.class, formatter);
                        ^
1 error

有没有办法在不传递单独的Class<T>参数的情况下编写此内容?我试图避免这种情况。这似乎是多余的。

6 个答案:

答案 0 :(得分:5)

不,由于Java中的通用type erasure,这是不可能的。有关泛型类的所有信息都在运行时丢失,唯一的解决方案是明确地将类作为参数传递。

答案 1 :(得分:1)

由于type-erasure T.class在运行时不可用,因此您必须传入一个单独的参数。通常,泛型类型信息在运行时不可用(除非您使用的是无界通配符)。

答案 2 :(得分:1)

Java语言不可能。所有泛型类型都在编译时确定,因此您无法在执行时访问类值。因此,您还需要传递Class<T>参数才能访问它。

public Class MyGenericClassContainer<T>{

    public T instance;

    public Class<T> clazz;

    public MyGenericClassContainer(Class<T> clazz){
        intance = clazz.newInstance();
    }

}

答案 3 :(得分:1)

一般来说,这是不可能的。但是,在您的情况下,让Formatter实施Class<T> getFormatterTargetClass()方法可能是合理的,然后您可以在代码中使用T.class代替{{1}}。

答案 4 :(得分:1)

不是解决方案,而是黑客攻击。

你可以做到。但通过肮脏的技巧和反思。以下面的代码为例。礼貌here

class ParameterizedTest<T> {

/**
 * @return the type parameter to our generic base class
 */
@SuppressWarnings("unchecked")
protected final Class<T> determineTypeParameter() {
    Class<?> specificClass = this.getClass();
    Type genericSuperclass = specificClass.getGenericSuperclass();
    while (!(genericSuperclass instanceof ParameterizedType) && specificClass != ParameterizedTest.class) {
        specificClass = specificClass.getSuperclass();
        genericSuperclass = specificClass.getGenericSuperclass();
    }
    final ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;

    final Type firstTypeParameter = parameterizedType.getActualTypeArguments()[0];
    return (Class<T>) firstTypeParameter;
}



}

//change the type of PrameterizedTest<Integer> to Parameterized<String> or something to    display different output
public class Test extends ParameterizedTest<Integer>{
 public static void main(String... args){
    Test test = new Test();
    System.out.println(test.determineTypeParameter());
}
}

在运行时,您将获得Type参数。因此,在您的课程中,您必须定义一个Class对象,如上所述获取该类。然后使用Class.newInstance获得一个新对象。但是你必须手动处理类型转换等等。

  

问题是:这一切都值得吗?

根据我的说法,通过使用泛型类型中的边界并连接到绑定类型,可以避免大部分内容。所以你应该寻找替代解决方案

答案 5 :(得分:1)

一个有益的练习就是问自己,“如果没有仿制药,我该怎么做?”答案也是你问题的答案。

通过删除泛型并在正确的位置插入强制转换,可以将具有泛型的程序写入没有泛型的等效程序,而无需更改代码中的任何其他内容。这种转换称为“类型擦除”。这意味着如果没有泛型就无法写出某些内容,那么它也不能用泛型来编写。

如果没有泛型,您的代码如下所示:

public interface Formatter {
    String format(Object value);
}

private Map formatters;

public void addFormatter(Formatter formatter) {
    formatters.put(?, formatter);
}

所以,我问你,你会怎么做?