【问题标题】:Java 10 'var' and inheritanceJava 10 'var' 和继承
【发布时间】:2018-09-19 13:22:32
【问题描述】:

在查看var 功能后,如here 所示:

我在使用 JDK 10 设置我的 Eclipse/IntelliJ IDEA IDE 时遇到了困难,因此我向拥有 Java 10 工作环境的 StackOverflow 用户寻求帮助。

考虑以下几点:

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?

当使用var 时,我希望JVM 能够识别变量所持有的派生类类型。并在执行 myA.someMethod() 时执行 B:someMethod() 而不是 A:someMethod()。

真的是这样吗?

【问题讨论】:

  • myAA 类型的变量并且BA 的子类型时,您为什么期望myA = new B() 失败?
  • @Holger 我的印象是 var 检查不允许派生类型成为声明的基类型的定义。作为一名 java 资深人士,我不希望出现这种预期的行为,我很高兴将派生类型的重新定义用作声明的 var 基类型的值。
  • 使用myA = new B() 您不会重新定义变量。您只是在分配一个新值。变量的类型仍然是A,由变量声明时使用的初始化程序确定。
  • @Holger :我不知何故开始相信,在使用 var 时,重新分配值会触发重新定义 var 类型。显然不是这样。
  • 它比你想象的要简单。当您说var x = e 时,无论e 的类型是什么,编译器都会假装您将其声明为x 的类型。此后,没有什么不同。相同的旧静态类型,只是编译器从上下文中为您选择一些类型。

标签: java var java-10


【解决方案1】:

感谢nullpointer 为在线Java 10 编译器提供link,我得到了以下有趣的结果:

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();
    }
}

还有输出:

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

结论 - var 是语法糖: var myA = new A() 等价于 A myA = new A(),所有 OOP 都与之关联。

PS:我试着和一个持有匿名类的 var 玩了一下,并想出了这个有趣的行为 - 再次感谢 nullpointer 提到它作为 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();
}

还有输出:

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

由于第二个匿名类类型与第一个匿名类类型不同,对 var 的第二次赋值失败 - 强制执行 var 关键字的语法糖角色。

令人惊讶的是,错误消息并没有更精确 - 目前它没有什么意义,因为错误中显示的类型名称是相同的!

【讨论】:

  • 兄弟的答案很好!
猜你喜欢
  • 2018-09-07
  • 2016-07-20
  • 1970-01-01
  • 2012-10-18
  • 2011-03-06
  • 2019-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多