Dave Hartnoll
Dave Hartnoll

Reputation: 1144

Why can't Java 7 diamond operator be used with anonymous classes?

Consider this Java code which attempts to instantiate some Lists:

List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<>();
List<String> list3 = new ArrayList<String>() { };
List<String> list4 = new ArrayList<>() { };
List<String> list5 = new ArrayList<Integer>() { };

list1 and list2 are straightforward; list2 uses the new diamond operator in Java 7 to reduce unnecessary repetition of the type parameters.

list3 is a variation on list1 using an anonymous class, potentially to override some methods of ArrayList.

list4 attempts to use the diamond operator, similar to list2, but this is a compile error, with the message '<>' cannot be used with anonymous classes.

list5 produces an error that proves the compiler knows what type is actually needed. The error message is Type mismatch: cannot convert from new ArrayList<Integer>(){} to List<String>

So, with the declaration of list4, why can't the diamond operator be used with anonymous classes? There is a similar question here with an accepted answer that contains the following explanation from JSR-334:

Using diamond with anonymous inner classes is not supported since doing so in general would require extensions to the class file signature attribute to represent non-denotable types, a de facto JVM change.

I need some help understanding that reasoning. Why would an explicit type versus the identical and apparently easily inferred type require any difference in the resulting class file? What difficult use case would be covered by "doing so in general"?

What is the underlying reason for this?

Upvotes: 41

Views: 7393

Answers (5)

user2485429
user2485429

Reputation: 567

From Java 9, diamond operator <> can be used with anonymous classes. See here.

Upvotes: 0

hoan
hoan

Reputation: 1098

From Java 10, you can do easily with var, the compiler will take care of the Type inference.

var list1 = new ArrayList();
var list2 = new ArrayList<String>();
var list3 = new ArrayList<String>() { };
var list4 = new ArrayList<>() { };
var list5 = new ArrayList<Integer>() { };

Upvotes: 1

jitendra varshney
jitendra varshney

Reputation: 3562

You can use it in java 9 Example Diamond operator

 MyHandler<Integer> intHandler = new MyHandler<>(1) {

        @Override
        public void handle() {
            // handling code...
        }
 };

Upvotes: 2

Durgpal Singh
Durgpal Singh

Reputation: 11953

You can use diamond opeator in Java9

MyHandler<Integer> intHandler = new MyHandler<>(1) {

        @Override
        public void handle() {
            // handling code...
        }
    };

    MyHandler<? extends Integer> intHandler1 = new MyHandler<>(10) {

        @Override
        void handle() {
            // handling code...
        }
    };

    MyHandler<?> handler = new MyHandler<>("One hundred") {

        @Override
        void handle() {
            // handling code...
        }
    };
}

Upvotes: 2

assylias
assylias

Reputation: 328608

This was discussed on the "Project Coin" mailing list. In substance (emphasis mine):

Internally, a Java compiler operates over a richer set of types than those that can be written down explicitly in a Java program. The compiler-internal types which cannot be written in a Java program are called non-denotable types. Non-denotable types can occur as the result of the inference used by diamond. Therefore, using diamond with anonymous inner classes is not supported since doing so in general would require extensions to the class file signature attribute to represent non-denotable types, a de facto JVM change. It is feasible that future platform versions could allow use of diamond when creating an anonymous inner class as long as the inferred type was denotable.

Note that it is not supported in Java 8 either but will be included as a new feature in Java 9 (Item 3 of "Milling Project Coin").

Upvotes: 24

Related Questions