我正在尝试使用泛型构建一个简单的界面,这是我正在尝试使用的代码:
public interface MyInterface<T>
{
public ArrayList<T> items;
//...
}
但是我从非静态上下文中获取有关访问静态变量T的错误。我怎样才能完成我想要做的事情?这就是我设想使用实现此接口的类的方法:
MyInterface<SomeObject> foo = new MyInterfaceImpl<>();
for (SomeObject bar: foo.items)
{
bar.someMethod();
}
这可以通过接口指定吗?
答案 0 :(得分:3)
在接口中声明的所有变量都是默认的static和final所以你的泛型类型T不适用于ArrayList
。因此它正在促进错误无法对非静态类型T
来自Java Language Specification Sec. 8.1.2
答案 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必须使用适当的类进行参数化,如果它是通用的,或者它不是通用的,那么就不需要括号。