Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Java, cannot iterate over a functional interface?

Context

I have an interface Job which contains a single method as shown below.

@FunctionalInterface
public interface Job {
  public void run() throws Exception;
}

In one of my classes, I have a list of these Jobs like so:

class MyClass<A, B, C, D, E, F> { // I know, it's a large number of generic types
  transient final ArrayList<Job> hooks;

  /* Constructor */
  public MyClass(){
    hooks = new ArrayList<>();
  }
}

Problem

From another class in the same package as MyClass, I am trying to loop over the contents of member hooks like so:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class DifferentClass {
  @SuppressWarnings("rawtypes")
  void procedure(MyClass a){
    for (final Job h : a.hooks) { // Compilation error here
      try {
        h.run();
      } catch (Exception e) {
      }
    }
  }

But Eclipse compiler doesn’t let me do that. I obtain the following error:

Type mismatch: cannot convert from element type Object to Job

However, if the above loop is within a method of class MyClass then the compiler doesn’t complain:

class MyClass<A, B, C, D, E, F> { // I know, it's a large number of generic types
  transient final ArrayList<Job> hooks;

  void procedureInClass() {
    for (final Job h : hooks) { // No compilation error in this case
      try {
        h.run();
      } catch (Exception e) {
      }
    }
  }

  /* Constructor */
  public MyClass(){
    hooks = new ArrayList<>();
  }
}

To make matter more confusing, if I compile my project from the command line using maven and OpenJDK v1.8.0_312, my project compiles without problem in both cases.

Question

What is preventing from looping over the contents of member MyClass#hooks from outside that class within the Eclipse IDE?

(edit) Following very helpful comments I added the generic types / @SuppressWarnings that I originally omitted.

>Solution :

This is because by declaring a as MyClass without the generic specification, you are declaring it as a raw type

Generally we are used to List<SomeType> being generic, that at run-time undergoes type-erasure. Further, that if we have old code like :

List myRawTypeVariable = new ArrayList();

that myRawType is a raw type, in that we can add any Object and only get Objects out.

However, it turns out that (as you have discovered) raw types go further than that, and type-erasure has compile-time implications as well.

The Java Language Specification (JLS) says this (source : https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.8 )

The type of a constructor (§8.8), instance method (§8.4, §9.4), or
non-static field (§8.3) of a raw type C that is not inherited from its
superclasses or superinterfaces is the raw type that corresponds to
the erasure of its type in the generic declaration corresponding to C.

Note that this is NOT limiting type erasure to ONLY those of the generic type; The types of ALL instance methods get taken to their raw types !

In other words, by not specifying the generic type of MyClass, you are making MyClass a raw type – and therefore turning off all Generic type-checking for that class (except for methods, etc otherwise specified, from inheritance or interfaces).

So even though hooks is declared as being a List<Job>, because you are using MyClass as a raw-type, it’s dropping the <Job> generic and treating that method as simply returning a List (effectively a List<Object> ).

So the fix is to add the generic specifier, so :

  void procedure(MyClass<?> a){
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading