Java 计算T.class而不通过一个类<;T>;参数
我正在开发一个类,它的功能类似于JTable的方法。我希望有Java 计算T.class而不通过一个类<;T>;参数,java,generics,Java,Generics,我正在开发一个类,它的功能类似于JTable的方法。我希望有类特定的格式化程序,将对象转换为适合显示的字符串 public interface Formatter<T> { String format(T value); } private Map<Class<?>, Formatter<?>> formatters; public <T> void addFormatter(Formatter<T> forma
类
特定的格式化程序,将对象转换为适合显示的字符串
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中有泛型。关于泛型类的所有信息在运行时都会丢失,唯一的解决方案是将该类作为参数显式传递。不,这是不可能的,因为Java中有泛型。有关泛型类的所有信息在运行时丢失,唯一的解决方案是将该类作为参数显式传递。由于T.class
在运行时不可用,因此您必须传递单独的参数。一般来说,泛型类型信息在运行时不可用(除非您使用的是无界通配符)。由于T.class
在运行时不可用,因此您必须传入单独的参数。一般来说,泛型类型信息在运行时不可用(除非您使用的是无界通配符)。这在Java语言中是不可能的。所有泛型类型都是在编译时确定的,因此您无法在执行时访问类值。因此,您还需要传递Class
参数才能访问它
public Class MyGenericClassContainer<T>{
public T instance;
public Class<T> clazz;
public MyGenericClassContainer(Class<T> clazz){
intance = clazz.newInstance();
}
}
公共类MyGenericClassContainer{
公共行政实例;
公开课;
公共MyGenericClassContainer(类clazz){
intance=clazz.newInstance();
}
}
这在Java语言中是不可能的。所有泛型类型都是在编译时确定的,因此您无法在执行时访问类值。因此,您还需要传递Class
参数才能访问它
public Class MyGenericClassContainer<T>{
public T instance;
public Class<T> clazz;
public MyGenericClassContainer(Class<T> clazz){
intance = clazz.newInstance();
}
}
公共类MyGenericClassContainer{
公共行政实例;
公开课;
公共MyGenericClassContainer(类clazz){
intance=clazz.newInstance();
}
}
一般来说,这是不可能的。不过,在您的情况下,让Formatter
实现一个类getFormatterTargetClass()
方法可能是合理的,然后您可以使用该方法来代替代码中的T.Class
。通常这是不可能的。不过,在您的情况下,让Formatter
实现一个类getFormatterTargetClass()
方法可能是合理的,然后您可以使用该方法代替代码中的T.Class
。不是一个解决方案,而是一个黑客
你能做到。但是通过肮脏的手段和反省。以下面的代码为例。礼节:
类参数化测试{
/**
*@将类型参数返回到我们的泛型基类
*/
@抑制警告(“未选中”)
受保护的最终类determinetyparameter(){
Class specificClass=this.getClass();
类型genericSuperclass=specificClass.getGenericSuperclass();
而(!(genericSuperclass instanceof ParameterizedType)&&specificClass!=ParameterizedTest.class){
specificClass=specificClass.getSuperclass();
genericSuperclass=specificClass.getGenericSuperclass();
}
最终参数化类型参数化类型=(参数化类型)genericSuperclass;
最终类型firstTypeParameter=ParameteredType.getActualTypeArguments()[0];
返回(类)firstTypeParameter;
}
}
//将PrMeterizedTest的类型更改为Parameterized或其他类型以显示不同的输出
公共类测试扩展了参数化测试{
公共静态void main(字符串…参数){
测试=新测试();
System.out.println(test.determinitypeparameter());
}
}
在运行时中,您将获得Type参数。因此,在类中,您必须定义一个class
对象,该对象获取如上所述的类。然后使用Class.newInstance
获得一个新对象。但是您必须手动处理类型转换等等
问题是:这一切值得吗
我认为没有,因为在泛型类型中使用边界并与绑定类型接口可以避免大多数情况。因此,您应该寻找替代解决方案,而不是解决方案,而是黑客 你能做到。但是通过肮脏的手段和反省。以下面的代码为例。礼节:
类参数化测试{
/**
*@将类型参数返回到我们的泛型基类
*/
@抑制警告(“未选中”)
受保护的最终类determinetyparameter(){
Class specificClass=this.getClass();
类型genericSuperclass=specificClass.getGenericSuperclass();
而(!(genericSuperclass instanceof ParameterizedType)&&specificClass!=ParameterizedTest.class){
specificClass=specificClass.getSuperclass();
genericSuperclass=specificClass.getGenericSuperclass();
}
最终参数化类型参数化类型=(参数化类型)genericSuperclass;
最终类型firstTypeParameter=ParameteredType.getActualTypeArguments()[0];
返回(类)firstTypeParameter;
}
}
//将PrMeterizedTest的类型更改为Parameterized或其他类型以显示不同的输出
公共类测试扩展了参数化测试{
公共静态void main(字符串…参数){
测试=新测试();
System.out.println(test.determinitypeparameter());
}
}
在运行时中,您将获得Type参数。因此,在类中,您必须定义一个class
对象,该对象获取如上所述的类。然后使用Class.newInstance
获得一个新对象。但是您必须手动处理类型转换等等
问题是:这一切值得吗
我认为没有,因为在泛型类型中使用边界并与绑定类型接口可以避免大多数情况。因此,你应该寻找替代的解决方案,一个有启发性的练习是问自己,“我该怎么做?”
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());
}
}
public interface Formatter {
String format(Object value);
}
private Map formatters;
public void addFormatter(Formatter formatter) {
formatters.put(?, formatter);
}