有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java有可能获得接口的泛型类型吗?

鉴于接口:

interface GenericInterface<T> {
  Class<T> getGenericType();
}

以及以下实施“框架”:

class GenericInterfaceImpl<T> implements GenericInterface<T> { /* impl */ }

class TypedInterfaceImpl implements GenericInterface<String> { /* impl */ }

以传递以下断言的方式定义getGenericType的实现:

assertEquals(new GenericInterfaceImpl<String>().getGenericType(), String.class, "Type should resolve to String.class");

assertEquals(new TypedInterfaceImpl().getGenericType(), String.class, "Type should resolve to String.class");

我非常清楚有一个很好的实现可以在TypedInterfaceImpl“场景”中解决这个问题。以下代码传递第二种情况的断言:

@Override
@SuppressWarnings("unchecked")
Class<T> getGenericType() {
    Type t = this.getClass().getGenericInterfaces()[0];
    ParameterizedType pt = (ParameterizedType) t;

    return (Class<T>) pt.getActualTypeArguments()[0];
}

但是,如果我处理这个问题的GenericInterfaceImpl版本,我找不到一种方法来获得相同的结果。当将上述实现与GenericInterfaceImpl一起使用时,“类型参数”解析为sun.reflect.generics.reflectiveObjects.TypeVariableImpl,而不是像处理TypedInterfaceImpl时那样的java.lang.String

用于getGenericInterfaces的Javadocs明确声明,如果没有在源代码中定义类型参数,它将不会解析类型参数(参考:https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getGenericInterfaces--在我的特定情况下,我使用的是java11,但它是相同的),因此根据定义,我理解这个特定方法无法解决这个问题

有没有办法解决这个问题,或者这是Java语言的“核心限制”


共 (1) 个答案

  1. # 1 楼答案

    assertEquals(new GenericInterfaceImpl<String>().getGenericType(), String.class, "Type should resolve to String.class");

    不可能

    assertEquals(new TypedInterfaceImpl().getGenericType(), String.class, "Type should resolve to String.class");

    可能,但不是个好主意;它要求您使用“在实现此接口时,您必须为T选择一个具体的、非类型参数化的类型,否则一切都不正常”来记录接口,这是一个奇怪的警告

    Class<T> getGenericType() {

    坏主意;<>中的东西不一定是Class-例如,它可能是List<String>,它不能表示为类对象(只有List是,有一个对象表示所有列表,无法有一个代表List<String>的j.l.class实例)

    The Javadocs for getGenericInterfaces

    getGenericInterfaces是一个反射工具,但它只反映类型的定义。给定class Foo<T> implements Thingie<T>getGenericInterfaces只能在整个Foo类上执行,然后返回一个表示Thingie<T>的对象。给定new Foo<String>()这样的实例,不可能派生字符串

    Is there a way to solve this problem at all or is this a "core limitation" of the Java language?

    这是一个核心限制,所以,不,不是直接的

    一个技巧是添加一个方法:

    public interface Foo<T> {
       public Class<T> getType();
    }
    

    让实施者担心这个问题。这仍然是一个坏主意,例如,Class对象不能表示List<String>,因此您已经有效地使Foo无法正确地表示任何您希望T具有类型参数的对象

    退后一步。你到底想做什么?没有人醒来就走:我知道!我将构建一个接口,它可以报告它自己的类型参数,但是具体化了!你想建造什么?聊天应用?photoshop的插件系统

    java.lang.Class是一个非常糟糕的工厂,目的是在它上面调用.newInstance()。因此,如果你打算这样做,就用工厂代替

    Anotehr解决方案,但您可能不想要这个,在您兴奋之前,它有很多限制,是一个称为超级类型令牌的概念;如果你必须知道的话,你可以在网上搜索