【问题标题】:Error using generic return type (incompatible types: cannot be converted to T)使用泛型返回类型时出错(不兼容的类型:无法转换为 T)
【发布时间】:2020-12-26 21:59:37
【问题描述】:
public class Main{
    private MyQueue queue = null;
    private MyStack stack = null;
    private MyList list = null;

    public static void main(String args[]){
        Main m = new Main();
        m.run();
    }
    
    public void run(){
        // only one data structure is not null.
        // for example, let's suppose that it's queue
        this.queue = new MyQueue();
        
        int intToAdd = 6;   // I want to add this number
        this.selectStruct().insert(intToAdd);       // I want to invoke the "insert" method of the current data structure in use
    }
    
    private <T> T selectStruct(){       // this should check with data structure is in use (so which of them is not null) and then return the reference
        if (this.queue!=null){
            return this.queue;
        }
        if (this.stack!=null){
            return this.stack;
        }
        if (this.list!=null){
            return this.list;
        }
    }
}

我想使用这个名为selectStruct 的方法来选择当前正在使用的数据结构并返回引用。然后从这个引用中调用insert 调用正确类的正确插入方法。

问题是我有几个错误。我从来没有使用过泛型,所以我有点困惑。

$ javac Main.java
Main.java:22: error: incompatible types: MyQueue cannot be converted to T
                        return this.queue;
                                   ^
  where T is a type-variable:
    T extends Object declared in method <T>selectStruct()
Main.java:25: error: incompatible types: MyStack cannot be converted to T
                        return this.stack;
                                   ^
  where T is a type-variable:
    T extends Object declared in method <T>selectStruct()
Main.java:28: error: incompatible types: MyList cannot be converted to T
                        return this.list;
                                   ^
  where T is a type-variable:
    T extends Object declared in method <T>selectStruct()
Main.java:17: error: cannot find symbol
                this.selectStruct().insert(intToAdd);
                                   ^
  symbol:   method insert(int)
  location: class Object
4 errors

【问题讨论】:

    标签: java generics signature


    【解决方案1】:

    MyQueueMyStackMyList 实现相同的接口,其中包含您希望所有数据结构实现的方法,例如:

    public interface IDataStructure {
        void insert(int intToAdd);
    }
    

    你的类应该如下所示:

    public class MyQueue implements IDataStructure{
    
        @Override
        public void insert(int intToAdd) {
            // TODO 
        }
    
    }
    
    public class MyStack implements IDataStructure{
    
        @Override
        public void insert(int intToAdd) {
            // TODO 
        }
    
    }
    
    public class MyList implements IDataStructure{
    
        @Override
        public void insert(int intToAdd) {
            // TODO 
        }
    
    }
    

    最后,您可以修改 selectStruct() 方法以返回 IDataStructure:

    private IDataStructure selectStruct() {
        if (this.queue != null) {
            return this.queue;
        }
        if (this.stack != null) {
            return this.stack;
        }
        if (this.list != null) {
            return this.list;
        }
        return null;
    }
    

    【讨论】:

    • 感谢您的回答 :) 由于 MyQueue、MyStack 和 MyList 已经实现了一些特定的接口,我认为与其创建 IDataStructure 接口,不如创建一个实现 SAME 接口的 IDataStructure 抽象类(它们对于每个数据结构都是相同的)。所以在此之后,我不再在 MyQueue、MyStack 和 MyList 中编写工具,而是编写“扩展 IDataStructure”,工作就完成了。我已经完成了它并且它有效,但我想知道它是否适合面向对象编程。
    • @Sperly 只是为了正确理解:您的所有数据结构都需要实现多个接口才能用作数据结构?那么你选择一个实现这些接口的抽象类是一个很好的选择。举个例子:假设您决定一个数据结构需要不同的特定逻辑,或者您决定删除一个接口。在这些情况下,您需要更改所有具体类。在您的情况下,大多数更改将在您的抽象类中。所以是的,我认为你的想法很好。
    • 但是请为它想一个别的名字。 IDataStructure 中的I 代表接口。你需要像AbstractDataStructure 这样的东西。但当然,这种命名取决于您必须遵循的约定。
    【解决方案2】:

    当你声明一个带有类型参数 T 的方法时(比如private &lt;T&gt; T selectStruct()),你是说这个方法的用户可以选择他们想要使用这个方法的任何类型。

    所以在selectStruct的正文中,你不知道调用者会使用哪种类型,当然你也不能返回任何具体的类型。这就是为什么像return this.queue; 这样的每个 return 子句都会产生错误的原因。

    【讨论】:

    • 感谢您的回答。所以没有办法解决这个问题?
    • 你应该改变你使用泛型的方式。 @Michael Chatiskatzi 的回答向您展示了如何做到这一点。我只是告诉你为什么不支持你使用它的方式。
    • 是的,我知道,我只是好奇如何使用泛型来做到这一点。
    猜你喜欢
    • 2016-10-17
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 2019-09-06
    • 1970-01-01
    • 2018-12-01
    • 1970-01-01
    相关资源
    最近更新 更多