1

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?

Ali
  • 261,656
  • 265
  • 575
  • 769
  • Making MyInterface extend Iterable will allow you to iterate on it using the for loop as you wrote it. – Eyal Schneider Feb 13 '13 at 08:16
  • That's not the problem, the problem is that the line ` public ArrayList items;` is giving me an error about accessing static variable T from non static context – Ali Feb 13 '13 at 08:17

5 Answers5

3

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.
Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
2

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.

Eyal Schneider
  • 22,166
  • 5
  • 47
  • 78
  • Right, I understand the reasoning, but how can I accomplish what I'm wanting then? – Ali Feb 13 '13 at 08:24
  • Click: I'm not sure what exactly you need. What you can't do for sure, is iterate over the static list and expect all the elements to be of type SomeObject. Are you sure you need a static global list? or maybe you actually need a list per instance? – Eyal Schneider Feb 13 '13 at 08:54
1

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.

Community
  • 1
  • 1
Liviu T.
  • 23,584
  • 10
  • 62
  • 58
1

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; }
}
Little Bobby Tables
  • 5,261
  • 2
  • 39
  • 49
0

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.

ATrubka
  • 3,982
  • 5
  • 33
  • 52
  • that's exactly what i posted. this is only the dummy code however. I'm having trouble with the code in the first part of the question.. – Ali Feb 13 '13 at 08:16
  • This is different from your code: new MyInterfaceImpl(); – ATrubka Feb 13 '13 at 08:17
  • 2
    not necessary with Java7 [see diamond](http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html) – oliholz Feb 13 '13 at 08:18