7

Following a review of the var feature as seen here:

I have encountered difficulties with setting up my Eclipse/IntelliJ IDEA IDEs with JDK 10 and am therefore asking help from Stack Overflow users who have a working Java 10 environment.

Consider the following:

public class A {
   public void someMethod() { ... }
}
public class B extends A{
   @Override
   public void someMethod() { ... }
}
...
...
...
var myA = new A(); // Works as expected
myA = new B(); // Expected to fail in compilation due to var being
               // syntactic sugar for declaring an A type
myA = (A) (new B()); // Should work
myA.someMethod(); // The question - which someMethod implementation is called?

When using var, I expect the JVM to recognize the deriving class type which the variable holds. And to execute B:someMethod() instead of A:someMethod() when executing myA.someMethod().

Is this indeed the case?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rann Lifshitz
  • 4,040
  • 4
  • 22
  • 42
  • 6
    Why do you expect `myA = new B()` to fail when `myA` is a variable of type `A` and `B` is a subtype of `A`? – Holger Apr 10 '18 at 11:39
  • @Holger I was under the impression that var inspection did not allow deriving types to be the definitions of a declared base type. As a java veteran I did not desire this expected behaviour, and I am glad there is no problem with redefinitions of deriving types being used as values for declared var base types. – Rann Lifshitz Apr 10 '18 at 12:16
  • 3
    With `myA = new B()` you are not redefining the variable. You are just assigning a new value. The type of the variable still is `A`, determined by the initializer used at the variable declaration. – Holger Apr 10 '18 at 12:20
  • @Holger : I somehow came to believe that when using var, reassignment of values triggers a redefinition of the var type. This is clearly not the case. – Rann Lifshitz Apr 10 '18 at 18:33
  • 3
    Its simpler than you think. When you say `var x = e`, whatever the type of `e` is, the compiler pretends you declared that as the type of `x`. Thereafter, nothing is different. Same old static typing, just with the compiler picking some types for you from context. – Brian Goetz Apr 11 '18 at 13:01

1 Answers1

9

Thanks to nullpointer providing a link to an online Java 10 compiler, I got the following interesting results:

public class Main {
    static class A {
           public void someMethod() { System.out.println(this.getClass().getName()); }
    }
    static class B extends A{
           @Override
           public void someMethod() { System.out.println("Derived: " + this.getClass().getName()); }
    }
    public static void main(String[] args) {
        var myA = new A();
        myA.someMethod();
        myA = new B(); // does not fail to compile!
        myA.someMethod();
    }
}

And the outputs:

Main$A // As expected
Derived: Main$B  // As expected in inheritance

Conclusion - var is syntactic sugar: var myA = new A() is equivalent to A myA = new A(), with all the OOP associated with it.

PS: I tried to play a little with a var holding an anonymous class and came up with this interesting behavior - thanks (yet again) to nullpointer for mentioning it as a duplicate of why can't we assign two inferred variables as an anonymous class to each other:

static interface Inter {
    public void method();
}

public static void main(String[] args) {
    var inter = new Inter() {
        @Override
        public void method() {System.out.println("popo");}
    };
    inter.method();
    inter = new Inter() {
        @Override
        public void method() {System.out.println("koko");}
    };
    inter.method();
}

And the output:

Main.java:11: error: incompatible types: <anonymous Inter> cannot be converted to <anonymous Inter>
        inter = new Inter() {
                ^

The second assignment to var fails due to the second anonymous class type differing from the first anonymous class type - enforcing the syntactic sugar role of the var keyword.

It is surprising that the error message is not more refined - currently it makes little sense since the type names displayed in the error are identical!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rann Lifshitz
  • 4,040
  • 4
  • 22
  • 42