Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 upgrade causes compiler error with inherited static enum

Tags:

java

java-8

We're upgrading a Java 6 project to Java 8. Recompiling with Java 8 gives errors in a java.awt.Frame subclass, I've simplified to the following:

org/example/Foo.java

package org.example;

import org.example.Type;
import java.awt.Frame;

public class Foo extends Frame {
    public Foo() {
        System.out.println(Type.BAZ);  // <=== error here, BAZ cannot be resolved
    }
}

org/example/Type.java

package org.example;

public class Type {
    public static final int BAZ = 1;
}

What appears to be happening is a static enum java.awt.Window.Type introduced in Java 7 is taking precedence even though there is an import for org.example.Type. Is this correct?

Does this mean we'll have to fully qualify all references to our Type with org.example.Type?

like image 868
Adam Avatar asked Jun 11 '15 14:06

Adam


1 Answers

What appears to be happening is a static enum java.awt.Window.Type introduced in Java 7 is taking precedence even though there is an import for org.example.Type. Is this correct?

Yes. The Type class is new, but the behavior is not. This is by design, and not new to Java 8.

Does this mean we'll have to fully qualify all references to our Type with org.example.Type?

Yes, as long as you're extending a class that contains a Type member.

I would question why you're extending Frame though: most times people extend Frame or JFrame, they shouldn't be. Favor composition over inheritance, and all that.

Another approach might be to use a static import to specifically import the Type members, in this case BAZ. something like this:

package org.example;

import static org.example.Type.BAZ;
import java.awt.Frame;
public class Foo extends Frame {
   public Foo() {
      System.out.println(BAZ);  
   }
}

That will be a pain in the neck if Type has a bunch of members though. Yet another approach might be to make Type an interface, and then have Foo implement that interface:

public interface Type {
    public static final int BAZ = 1;
}
public class Foo extends Frame implements Type{
    public Foo() {
        System.out.println(BAZ);  
    }
}

You could also create a Type instance in your Foo class, or rename Type to avoid the conflict, or create a bridge between Foo and Type.

These are all slightly hackish solutions to simply not extending Frame though.

like image 108
Kevin Workman Avatar answered Sep 28 '22 03:09

Kevin Workman