繁体   English   中英

通用参数作为变量-Java

[英]Generic parameter as variable - Java

构造函数NotePanel(itemClass)引用缺少的类型itemClass我有一个类NotePanel<T extends AbstractNoteItem> extends JPanel ,还有一个单独的类中的方法,该方法返回应在方法期间创建的NotePanel

public class NoteList extends JList {
    ...
    public class NoteListModel extends AbstractListModel {
        ...
        public NotePanel getPanelFromIndex(int index) {
            if (!indexExists(index)) {
                // FYI, indexExists(int) works fine
                return null;
            } else {
                AbstractNoteItem item = getElementAt(index);
                // FYI, getElementAt(int) works fine
                assert (item != null);  
                Class<?> itemClass = item.getClass();
                return (new NotePanel<itemClass> (item));
            }
        }
    }
}

返回新的NotePanel的行上有错误:“构造函数NotePanel(itemClass)引用缺少的typeItemClass。” 有人可以告诉我如何进行这项工作吗?

如果这还不够,我将很乐意提供更多代码。 我所有的进口货物都已整理好(谢谢您,整理进口货物!)。 我看不到任何明显的问题,但是使用泛型也是新手。

提前致谢!

您尝试执行的操作无法正常工作,因为泛型类型参数仅在编译时存在。 由于类型擦除,它们在运行时没有影响。 因此,将在运行时获得的Class<?>用作通用类型参数是没有意义的。

在不知道为什么首先要使NotePanel通用的情况下,很难提出适当的替代方案。

您只能使用常量通用参数。 在这里,它可以像AbstractNoteItem一样紧密,但不会更窄。

大概在做

new NotePanel<AbstractNoteItem> (item)

可以,您想要什么,但是没有看到全局,很难确定。

同样,您的返回类型是普通的NotePanel,因此参数化其构造并不重要。 无论您将它退还给谁,都不会看到参数化。

如另一个答案中所述,关键是Java泛型仅在编译时。 它们与生成不同代码的C ++模板不同,它只是编译时类型检查的一种更奇特的形式。

以下内容可能有效也可能无效。 这是有关泛型方法的教程。

public class NoteList extends JList {
    ...
    public class NoteListModel extends AbstractListModel {
        ...
        public < T extends AbstractNoteItem > NotePanel < T > getPanelFromIndex(int index) {
            if (!indexExists(index)) {
                // FYI, indexExists(int) works fine
                return null;
            } else {
                T item = ( T ) ( getElementAt(index) ) ; // this should generate a warning
                // FYI, getElementAt(int) works fine
                assert (item != null);  
                // not needed // Class<?> itemClass = item.getClass();
                return (new NotePanel<T> (item));
            }
        }
    } }

调用方法

class NoteItemImpl extends AbstractNoteItem { ... stuff ... }

Notelist notelist ; 
// implicit type argument specification
NotePanel < AbstractNoteItem > n1 = notelist . getPanelFromIndex ( 1 ) ;  
NotePanel < NoteItemImpl > n2 = notelist . getPanelFromIndex (2 ) ; // may generate class cast exception

// explicit type argument specification
NotePanel < AbstractNoteItem > n3 = notelist . < AbstractNoteItem > getPanelFromIndex ( 3 ) ;
NotePanel < NoteItemImpl > n4 = notelist . < NoteItemImpl > getPanelFromIndex ( 4 ) ; // may generate class cast exception

如果我正确理解了此问题,则说明您有一个具有注释项成员的NotePanel类。 此注释项是AbstractNoteItem的子类。 但是,您不想为注释项指定AbstractNoteItem类型,因为您希望直接访问子类方法。

现在,如果所有这些子类方法都具有相同的名称和相同的签名(在整个层次结构中),那么您根本就不需要泛型。 普通的老式多态性将为您工作。

但是,如果子类方法完全不同,则您需要的是单独的NotePanel类,每种注释项类型一个。 在您的问题中,您似乎想使用泛型来生成它们。 由于擦除,这在Java中实际上是不可能的。 如另一个答案中所述,C ++泛型将创建多个类,但是您不会在Java中得到它。

但是,如果这些单独的NotePanel类在每个AbstractNoteItem子类中都具有调用不同方法的方法,那么我认为您真的需要编写单独的NotePanel子类! 如果需要,这种并行的类层次结构并没有那么糟糕。

如果走这条路,那么用创建正确类型的NoteItem子类的工厂方法替换对NoteItem构造函数的调用(您无法使用的调用)。

暂无
暂无

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

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