如何在java界面中使用泛型?

时间:2013-02-13 08:13:20

标签: java generics interface

我正在尝试使用泛型构建一个简单的界面,这是我正在尝试使用的代码:

public interface MyInterface<T>
{
   public ArrayList<T> items;
   //...
}

但是我从非静态上下文中获取有关访问静态变量T的错误。我怎样才能完成我想要做的事情?这就是我设想使用实现此接口的类的方法:

MyInterface<SomeObject> foo = new MyInterfaceImpl<>();

for (SomeObject bar: foo.items)
{
     bar.someMethod();
}

这可以通过接口指定吗?

5 个答案:

答案 0 :(得分:3)

在接口中声明的所有变量都是默认的static和final所以你的泛型类型T不适用于ArrayList。因此它正在促进错误无法对非静态类型T

进行静态引用

来自Java Language Specification Sec. 8.1.2

  • 引用泛型的类型参数是编译时错误 C级的任何地方:
  • C的静态成员的声明(§8.3.1.1,§8.4.3.2,§8.5.1), 或
  • 声明嵌套的任何类型声明的静态成员 在C之内,或
  • C(第8.7节)的静态初始化程序,或
  • 嵌套在C。
  • 中的任何类声明的静态初始值设定项

答案 1 :(得分:2)

主要问题是数据成员,在接口中声明时默认是静态的。

不允许静态数据成员引用泛型参数。如果允许的话,这将破坏类型安全性,因为应该允许不同的实例具有不同的类型参数,但静态成员由所有实例共享,因此它不能链接到特定的类型参数。

答案 2 :(得分:1)

基本上,界面描述的功能(又名 一个类可以做什么 )不是实现(又名 如何 实例实现了这些能力。)

来自this other stackoverflow question

  

接口变量是静态的,因为Java接口不能   以自己的方式实例化;变量的值必须是   在静态上下文中分配,其中不存在实例。决赛   修饰符确保分配给接口变量的值为a   无法通过程序代码重新分配的真常量。

您实际需要的是 抽象 基类

class abstract Base<T> implements MyInterface<T> {
    //btw it's recommended that you use interfaces as the declaring type not implementations
    public List<T> items = new ArrayList<T>;
}

class MyInterfaceImpl<T> extends Base<T> {
   //...
}

抽象基类的优势在于它们可以包含0到100%的实现,包括公共/保护/私有实例字段。

答案 3 :(得分:1)

按照Eyal的解释,请这样做:

public interface MyInterface<T> {
  Collection<T> getItems();
}

实现类将包含动态数据成员:

public class MyImpl<T> implements MyInterface<T> {
  private Collection<T> items;
  public Collection<T> getItems() { return items; }
}

答案 4 :(得分:0)

你必须这样做:

MyInterface<SomeObject> foo = new MyInterfaceImpl<SomeObject>();

for (SomeObject bar: foo.items)
{
    bar.someMethod();
}

请注意,MyInterfaceImpl必须使用适当的类进行参数化,如果它是通用的,或者它不是通用的,那么就不需要括号。