通用参数作为变量- Java



构造函数NotePanel(itemClass)引用了缺失的类型itemClassI有一个类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)指的是缺失的类型itemClass。"有人能告诉我怎么做吗?

如果这是不够的代码,我很乐意提供更多。我所有的进口都是有序的(谢谢你,组织进口!)我没有看到任何明显的问题,但我也是一个使用泛型的新手。

提前感谢!

你想做的是不能工作,因为泛型类型参数只存在于编译时;由于类型擦除,它们在运行时没有影响。因此,使用在运行时获得的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子类。

最新更新