简体   繁体   English

如何将通用参数传递给方法?

[英]How do I pass a generic parameter to a method?

I am trying to store objects that are a sub-class of an abstract class, but there is a problem illustrated here: 我正在尝试存储作为抽象类的子类的对象,但是这里说明了一个问题:

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 {}

The reason map.put throws an error is that letter is not a sub-class of Letter (it is a direct instance of Letter ). 究其原因map.put抛出一个错误是, letter不是一个子类的Letter (这是一个直接的实例Letter )。

Is there a way to change the method parameter to be a generic sub-class of Letter? 有没有一种方法可以将方法参数更改为Letter的通用子类? Something like: 就像是:

public void store_object(? extends Letter letter) {

or 要么

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

The error is: 错误是:

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

I'm really not sure what you're trying to do here, but this will make your code compile: 我真的不确定您要在这里做什么,但这会使您的代码编译:

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 {}

Why are you generating a new HashMap every time the store_object method is called? 为什么每次调用store_object方法时都会生成一个新的HashMap What is your real problem? 你真正的问题是什么? Please read What is the XY problem? 请阅读什么是XY问题?

Related: Canonical Java Generics FAQ 相关: Canonical Java泛型常见问题解答


By the way, Object<Anything> is always wrong because Object is not parameterized. 顺便说一句, Object<Anything>总是错误的,因为未对Object进行参数化。


So I saw your edit, and FYI this compiles for me: 因此,我看到了您的编辑,仅供参考,我为您编译:

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

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

What's your problem exactly? 到底是什么问题

Given B extends A , Class<? extends B> 给定B extends AClass<? extends B> Class<? extends B> is not a subtype of Class<? extends A> Class<? extends B> 不是 Class<? extends A>的子类型Class<? extends A> Class<? extends A> , so using a generic bound of Class<? extends Letter> Class<? extends A> ,因此使用Class<? extends Letter>的泛型边界Class<? extends Letter> Class<? extends Letter> is useless. Class<? extends Letter>是没有用的。

Instead, specify the key type as simply <Class<?> and your code will compile (and you actually don't lose anything by doing this):. 相反,只需将键类型指定为<Class<?> ,您的代码将被编译(这样做实际上不会丢失任何内容):

It needs to be <? super Letter> 它必须是<? super Letter> <? super Letter> instead. <? super Letter> There's a nice acronym to help you remember PECS 有一个很好的首字母缩写词可以帮助您记住PECS

If you want to use generic parameters do : 如果要使用通用参数,请执行以下操作:

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

**^ oops there are no lower bounds (super) on type parameters ** ^ 哎呀,类型参数没有下限(超级)

Edit: Just saw your edit. 编辑:刚刚看到您的编辑。 Originally I thought you were just placing objects into some collection. 本来我以为您只是将对象放入某个集合中。 The static map declaration type arguments are correct. 静态映射声明类型参数正确。 because this one instance will be used by everything for both usage and storage, so it needs to be <Class<? extends>, VCorePanel> 因为这一个实例将通过一切为使用和储存使用,因此它需要<Class<? extends>, VCorePanel> <Class<? extends>, VCorePanel> . <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. ps。 if you are using java 8, you can just pass in a constructor as opposed to using the reflection library. 如果您使用的是Java 8,则可以传入构造函数,而不是使用反射库。 look into it if you'd like. 如有需要,请调查一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM