简体   繁体   English

如何在Java接口中使用泛型?

[英]How to use generics in a java interface?

I'm trying to build a simple interface using generics, here's the code I'm trying to use: 我正在尝试使用泛型构建一个简单的接口,这是我正在尝试使用的代码:

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

However I'm getting an error about accessing static variable T from a non static context, etc. How can I accomplish what I'm trying to do? 但是,从非静态上下文等访问静态变量T时出现错误。如何完成我想做的事情? This is how I envision using a class which implements this interface: 这是我设想使用实现此接口的类的方式:

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

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

Is this possible to specify via interfaces? 是否可以通过接口指定?

All the variable declared in interface those are by-default static and final So your generic type T can not be applicable to ArrayList . 接口中声明的所有变量都是默认的static和final,因此您的通用类型T不适用于ArrayList so it is promoting error Cannot make a static reference to the non-static type T 因此它正在引发错误无法静态引用非静态类型T

From the Java Language Specification Sec. 摘自Java语言规范部分。 8.1.2 8.1.2

  • It is a compile-time error to refer to a type parameter of a generic class C anywhere in: 在以下任何地方引用通用类C的类型参数是编译时错误:
  • the declaration of a static member of C (§8.3.1.1, §8.4.3.2, §8.5.1), or C的静态成员的声明(第8.3.1.1节,第8.4.3.2节,第8.5.1节),或
  • the declaration of a static member of any type declaration nested within C, or 嵌套在C中的任何类型声明的静态成员的声明,或者
  • a static initializer of C (§8.7), or C的静态初始值设定项(第8.7节),或者
  • a static initializer of any class declaration nested within C. 嵌套在C中的任何类声明的静态初始化器。

The main problem is the data member, which is static by default when declared in an interface. 主要问题是数据成员,在接口中声明时默认情况下是静态的。

A static data member is not allowed to refer to generic parameters. 静态数据成员不允许引用通用参数。 This would break the type safety if it was allowed, since different instances should be allowed to have a different type argument, but the static member is shared by all of them, so it can't be linked to a particular type argument. 如果允许的话,这将破坏类型安全性,因为应该允许不同的实例具有不同的类型实参,但是静态成员由所有实例共享,因此不能将其链接到特定的类型实参。

Basically an interface describes capabilities(aka what a class can do) not implementation(aka how an instance achieves those capabilities). 基本上是一个接口描述能力(又名什么类可以做)不执行(实例又名如何实现这些功能)。

From this other stackoverflow question 另一个stackoverflow问题

Interface variables are static because Java interfaces cannot be instantiated in their own right; 接口变量是静态的,因为不能单独实例化Java接口。 the value of the variable must be assigned in a static context in which no instance exists. 必须在不存在任何实例的静态上下文中分配变量的值。 The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code. final修饰符确保分配给接口变量的值是一个真正的常量,不能由程序代码重新分配。

What you actually need here is a abstract base class 您实际上真正需要的是一个抽象基类

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> {
   //...
}

Abstract base classes have the advantage that they can include from 0 to 100% implementation including public/protect/private instance fields. 抽象基类的优点是它们可以包含0%到100%的实现,包括公共/保护/私有实例字段。

Following Eyal's explanation, do like this: 按照Eyal的解释,执行以下操作:

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

Implementing classes will hold a dynamic data member: 实现类将包含一个动态数据成员:

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

You have to do this: 您必须这样做:

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

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

Note that MyInterfaceImpl has to be parametrized with appropriate class if it's generic or if it's not generic than no brackets would be needed there. 请注意,如果MyInterfaceImpl是通用的,或者不是通用的,则必须使用适当的类进行参数设置,因为在那里不需要括号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM