如何将泛型参数传递给方法?

时间:2015-07-19 02:44:18

标签: java generics

我正在尝试存储作为抽象类的子类的对象,但这里有一个问题:

abstract class Letter {
    public void store_object(Letter letter) {
        HashMap<Class<? extends Letter>, ? extends Letter> map = new HashMap<>();
        map.put(letter.getClass(), letter); <-- this line throws an error
    }
}
class A extends Letter {}
class B extends Letter {}

map.put引发错误的原因是letter不是Letter的子类(它是Letter的直接实例)。

有没有办法将方法参数更改为Letter的通用子类?类似的东西:

public void store_object(? extends Letter letter) {

public void store_object(Object<? extends Letter> letter) {

错误是:

no suitable method found for put(Class<CAP#1>,NewClass19.Letter)
    method Map.put(Class<? extends NewClass19.Letter>,CAP#2) is not applicable
      (argument mismatch; NewClass19.Letter cannot be converted to CAP#2)
    method AbstractMap.put(Class<? extends NewClass19.Letter>,CAP#2) is not applicable
      (argument mismatch; NewClass19.Letter cannot be converted to CAP#2)
    method HashMap.put(Class<? extends NewClass19.Letter>,CAP#2) is not applicable
      (argument mismatch; NewClass19.Letter cannot be converted to CAP#2)
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends NewClass19.Letter from capture of ? extends NewClass19.Letter
    CAP#2 extends NewClass19.Letter from capture of ? extends NewClass19.Letter

3 个答案:

答案 0 :(得分:2)

我真的不确定你在这里尝试做什么,但这会使你的代码编译:

abstract class Letter {
    public <T extends Letter> void store_object(T letter) {
        HashMap<Class<? extends Letter>, T> map = new HashMap<>();
        map.put(letter.getClass(), letter); // <-- this line throws an error
    }
}
class A extends Letter {}
class B extends Letter {}

为什么每次调用HashMap方法时都会生成新的store_object?你真正的问题是什么?请阅读What is the XY problem?

相关:Canonical Java Generics FAQ

顺便说一下,Object<Anything>始终是错误的,因为Object未参数化。

所以我看到了你的编辑,而且这对我来说是编译的:

private static HashMap<Class<? extends Test>, Test> map = new HashMap<>();

static void addTest(Test test) {
    map.put(test.getClass(), test);
}

你的问题究竟是什么?

答案 1 :(得分:0)

鉴于B extends AClass<? extends B> Class<? extends A>的子类型,因此使用Class<? extends Letter>的通用边界是无用的。

相反,只需将密钥类型指定为<Class<?>,您的代码就会编译(实际上,您实际上不会丢失任何内容):.

答案 2 :(得分:-3)

它必须是<? super Letter>。有一个很好的首字母缩写词可以帮助你记住PECS

如果要使用通用参数,请执行以下操作:

public <T extends Letter> void method(T arg1) 

** ^ oops there are no lower bounds (super) on type parameters

编辑:刚看到你的编辑。最初我以为你只是把对象放到一些集合中。静态映射声明类型参数是正确的。因为这个实例将被 使用和存储的所有内容使用,所以它必须是<Class<? extends>, VCorePanel>

static Map<Class<? extends VCorePanel>, VCorePanel> self...pm;
public static showPanel(T newInstance){
    ...
    VCorePanel OldInstance = self_panel_map.get(newInstance.getClass()); //use
    ...
    self_panel_map.put(newInstace.getClass(), newInstance); //storage
}

PS。如果您使用的是Java 8,则可以传入构造函数而不是使用反射库。如果你愿意,可以考虑一下。