Groovy 和 Java 静态变量行为

Pur*_*ple 5 java groovy

我最近一直在做一些 Java 和 Grails3 编程。我发现了一些我不明白的行为。

有两个 groovy 类:

class Super {
    static String desc = "Super"
}
Run Code Online (Sandbox Code Playgroud)

class Sub extends Super {
    static String desc = "Sub"
}
Run Code Online (Sandbox Code Playgroud)

现在,我在 Java 和 Groovy 中运行以下代码:

Super aSuper = new Super();
Sub sub = new Sub();
Super superSub = new Sub();

System.out.println("Super object: [" + aSuper.getDesc() + "]"); //1
System.out.println("Sub object: [" + sub.getDesc() + "]");//2
System.out.println("Sub object, super reference: [" + superSub.getDesc()+ "]");//3
System.out.println("Super reference: [" + Super.getDesc()+ "]");//4
System.out.println("Sub reference: [" + Sub.getDesc()+ "]");//5
Run Code Online (Sandbox Code Playgroud)

1,2,4,5的结果在两种情况下都是一样的,容易预测([Super], [Sub], [Super], [Sub])

但是,如果运行上面的代码时,Java 类输出的第 3 种情况将是:Sub object, super reference: [Super] 从 Groovy 中,它将导致:Sub object, super reference: [Sub]

为什么 Groovy 对static变量的解释不同?

bil*_*dev 3

正如 @dmahapatro 所说,它基于MultiMethods,但这是一个微妙的例子。在文档中,该示例基于给定参数的方法选择,其中变量是参数所持有的实例的父类型。Java 在编译时选择方法签名,因为那时它只有参数变量声明的类(Object),而不是实例的类(String)。Groovy 延迟其决策,因此它可以确定参数变量引用的实例的类,并使用它来确定哪个方法签名最匹配。

在上面的示例中,当您引用静态成员时,它是基于类的,而不是基于实例的,因此 Java 的继承思想(虚拟方法)不起作用。Java 再次从引用变量 (Super.desc) 的 Class 中选择 static。Groovy 再次采用延迟的、基于实例的路径,并询问实例它的静态成员是什么 (Sub.desc)。

请注意,大多数人会认为情况 3 是不好的风格(询问实例类静态成员的值是什么),所以通常情况下它不应该出现。