java - javac 能否推断出将 x.getClass() 和 x 一起使用的正确泛型?

标签 java generics

我想要一个通用方法,它接受某种类型 T 的对象,以及一个表示该类型的类。最终我打算用它来创建一个 Map<Class<?>, Object> ,我知道每个类都会映射到一个完全属于自己类型的对象;我知道我无法让编译器相信这一点,但我想尽可能多地保持代码的编译时通用安全性。这是一个演示我遇到的问题的最小示例:

public class Example {
  public static <T extends Number> void foo(Class<T> c, T x) {
    ;
  }

  public static void bar(int x) {
    foo(Integer.class, x);
  }

  public static void baz(Number x) {
    foo(x.getClass(), x);
  }
}

我可以写 foo方法没有问题,它有我想要的签名,如果我在编译时确切知道我有什么类型,我可以使用它,如 bar , 但我不能在任何类型的对象上使用它,正如我在 baz 中尝试的那样: baz不编译,引用:

Example.java:11: error: method foo in class Example cannot be applied to given types;
    foo(x.getClass(), x);
    ^
  required: Class<T>,T
  found: Class<CAP#1>,Number
  reason: inferred type does not conform to lower bound(s)
    inferred: CAP#1
    lower bound(s): Number
  where T is a type-variable:
    T extends Number declared in method <T>foo(Class<T>,T)
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Number from capture of ? extends Number

我想我理解这里的问题:x.getClass()返回 Class<? extends Number> , 它建立了 <? extends Number>作为T ,但是 x继续有类型 Number , 需要 T成为Number ,因此冲突。当我写这篇文章时,我希望编译器知道 x.getClass()x确实共享完全相同的T ,但它不知道这一点是有道理的。

那么,我在这里做什么?有没有办法我可以写类似 foo 的东西还有类似 baz 的东西?我应该放弃编译时安全并在运行时进行一些转换吗?有没有更好的方法来实现我的最终目标 Map<Class, Object>

最佳答案

根据 the documentation for Object.getClass() :

The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called.

注意关于“静态类型的删除”的部分。这意味着,如果你有一个类型变量 T例如,声明为 <T extends Number> , 和一个变量 T x , 然后返回值 x.getClass()不是 Class<? extends T> ,但是Class<? extends Number> .如果没有任何不安全的强制转换,这确实让您很难做您想做的事情(诚然,这取决于您到底想做什么)。

但是,您可以将不安全性包含在它自己的函数中。例如,这有效:

public class test {
    public static <T extends Number> void foo(Class<T> c, T x) {
        ;
    }

    @SuppressWarnings("unchecked")
    public static <T> Class<? extends T> getClass2(T x) {
        return((Class<? extends T>)x.getClass());
    }

    public static void bar(int x) {
        foo(Integer.class, x);
    }

    public static void baz(Number x) {
        foo(getClass2(x), x);
    }
}

关于java - javac 能否推断出将 x.getClass() 和 x 一起使用的正确泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36163287/

相关文章:

java - 在 Java 中如何使用泛型引用嵌套类型?

Java 泛型 : Set vs. Set<Object>

java - 如何将项目添加到同一父类(super class)型的通用列表中?

java - Intellij 无法解析符号 'lang3' apache

java - Hibernate 不生成 id

java - 覆盖 "when thread is released"行为的方法名称或机制是什么

java - 如何使用 LocalBroadcastManager 调用不同的方法

java - add()操作在 "? extends"和 "? super"的区别

java - 在java泛型类中将Integer转换为int

javax.jms.JMSSecurityException : User name [null] or password is invalid