【问题标题】:Loosing List type on abstract class implementing generic interface在实现泛型接口的抽象类上丢失列表类型
【发布时间】:2013-03-06 15:09:18
【问题描述】:

我在理解以下场景时遇到了一些麻烦。 我有一个由抽象类和扩展抽象类的具体类实现的“通用”接口。

问题是抽象类中返回参数化列表的所有方法都丢失了它们的类型,所以我收到一个编译错误,告诉我它无法从对象转换为原始 List 类型。

谁能提供一些见解?

最后,我希望在抽象类上有一个 getId 和 setId 方法,其返回类型为 java.lang.object<T extends Object>,具体类将其返回类型实现为任何他们想要的类型。

这是我的不同对象的代码:

通用接口

public interface MyInterface<T>{

   public T getId();
   public void setId(T id);

}

实现接口的抽象类

public abstract class MyAbstractClass<T> implements MyInterface<T>{

  private List<String> texts;
  private List<Integer> notes;

   public List<String> getTexts(){
     return texts;
   }

   public List<Integer> getNotes(){
     return notes;
   }
}

实现抽象类的具体类

public class MyConcreteClass implements MyAbstractClass<Integer>{

    private Integer id;

    public Integer getId(){
       return this.id;
    }


    public void setId(Integer id){
          this.id = id;
    } 

}

其他类:

 public class SomeOtherClass{

   public void process(List<T extends MyAbstractClass> myClassList){

  // Compilation error -> 
  // Type mismatch: cannot convert from element type Object to String  
       for(MyAbstractClass myObj : myClassList){

            System.out.println("object Id : " + myObj.getId());

              // Compilation error -> 
              // Type mismatch: cannot convert from element type Object to String  
             for(String txt : myObj.getTexts()){


             }
       }
   }

}

【问题讨论】:

  • 您可能需要public void process(MyAbstractClass&lt;Integer&gt; myClass){。请注意将 添加到参数类型。
  • 是的,但问题是我希望能够处理我的抽象类的所有子类型,以便在 for 循环中调用 getId() 方法。我刚刚编辑了代码以更好地展示我正在尝试的内容

标签: java generics type-erasure


【解决方案1】:

我认为您需要另一个界面。请参阅此处,MyAbstractClass 实现了两个接口 MyInterface&lt;T&gt;, MyOtherInterface

  public static interface MyInterface<T> {
    public T getId();

    public void setId(T id);
  }

  public static interface MyOtherInterface {
    public List<String> getTexts();

    public List<Integer> getNotes();
  }

  public abstract class MyAbstractClass<T> implements MyInterface<T>, MyOtherInterface {
    private List<String> texts;
    private List<Integer> notes;

    public List<String> getTexts() {
      return texts;
    }

    public List<Integer> getNotes() {
      return notes;
    }
  }

  public static class MyConcreteClass extends MyAbstractClass<Integer> {
    private Integer id;

    public Integer getId() {
      return this.id;
    }

    public void setId(Integer id) {
      this.id = id;
    }
  }

  public class SomeOtherClass {
    public void process(MyOtherInterface myClass) {

      // NO Compilation error
      for (String str : myClass.getTexts()) {
        // some processing
      }
    }
  }

【讨论】:

  • 这几乎是完美的,但我无法在 process 方法的 foreach 循环中调用 getId() 方法。我开始认为我无法做到这一点。 . 我稍微修改了处理方法,以更好地反映我的实际代码
  • 那么它必须是MyConcreteClassMyInterface&lt;Integer&gt;,除非你想通过强制转换来破解它,这太可怕了。
  • 是的,我宁愿不使用强制转换,因为我同意这不是很好......我接受你的答案,因为我认为这是最接近的一个。天哪,我总是被 Java 擦除所愚弄
【解决方案2】:

当您使用泛型类型 MyAbstractClass&lt;T&gt; 作为原始类型 (MyAbstractClass) 时,其成员声明中与泛型相关的所有内容都将被禁用(即 List&lt;String&gt; 变为 List)。

因此,您需要将方法的参数声明为参数化类型。如果您不关心实际类型参数,请使用通配符:

public void process(MyAbstractClass<?> myClass) { ... }

【讨论】:

    猜你喜欢
    • 2020-05-14
    • 2010-11-08
    • 2012-04-11
    • 1970-01-01
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多