简体   繁体   中英

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? 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 . so it is promoting error Cannot make a static reference to the non-static type T

From the Java Language Specification Sec. 8.1.2

  • It is a compile-time error to refer to a type parameter of a generic class C anywhere in:
  • the declaration of a static member of C (§8.3.1.1, §8.4.3.2, §8.5.1), or
  • the declaration of a static member of any type declaration nested within C, or
  • a static initializer of C (§8.7), or
  • a static initializer of any class declaration nested within 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

Interface variables are static because Java interfaces cannot be instantiated in their own right; 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.

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.

Following Eyal's explanation, do like this:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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