1

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

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

但是,我在从非静态上下文等访问静态变量 T 时遇到错误。我怎样才能完成我想要做的事情?这就是我设想使用实现此接口的类的方式:

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

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

这可以通过接口指定吗?

4

5 回答 5

3

在接口中声明的所有变量都是默认静态和最终的所以你的泛型类型 T 不能适用于ArrayList. 所以它正在促进错误无法对非静态类型 T 进行静态引用

来自Java 语言规范 Sec。8.1.2

  • 在以下任何地方引用泛型类 C 的类型参数是编译时错误:
  • C 的静态成员的声明(§8.3.1.1、§8.4.3.2、§8.5.1),或
  • 嵌套在 C 中的任何类型声明的静态成员的声明,或
  • C 的静态初始化程序(第 8.7 节),或
  • 嵌套在 C 中的任何类声明的静态初始化程序。
于 2013-02-13T08:17:37.190 回答
2

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

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

于 2013-02-13T08:23:35.953 回答
1

基本上,接口描述的是功能(也就是类可以做什么)而不是实现(也就是实例如何实现这些功能)。

this other stackoverflow question

接口变量是静态的,因为 Java 接口不能单独实例化;变量的值必须在不存在实例的静态上下文中分配。final修饰符确保分配给接口变量的值是一个真正的常量,程序代码不能重新分配。

你在这里真正需要的是一个抽象基类

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% 的实现,包括公共/保护/私有实例字段。

于 2013-02-13T08:25:34.193 回答
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; }
}
于 2013-02-13T08:29:27.003 回答
0

你必须这样做:

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

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

请注意,如果 MyInterfaceImpl 是泛型的或不是泛型的,则必须使用适当的类对其进行参数化,而不需要括号。

于 2013-02-13T08:15:44.110 回答