我最近一直在做一些 Java 和 Grails3 编程。 我发现了一些我不理解的行为。
有两个常规类:
class Super {
static String desc = "Super"
}
和
class Sub extends Super {
static String desc = "Sub"
}
现在,我在 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
1,2,4,5的结果在这两种情况下是相同的并且易于预测([Super],[Sub],[Super],[Sub])
但在第 3 种情况下,当运行上述代码时,Java 类的输出将是:Sub object, super reference: [Super]
在 Groovy 中,它将产生:Sub object, super reference: [Sub]
为什么 Groovy 对 static
变量的解释不同?
最佳答案
正如@dmahapatro 所说,它基于 Multi Methods ,但这是一个微妙的例子。在文档中,该示例基于给定参数的方法选择,其中变量是参数持有的实例的父类型。 Java 在编译时选择方法签名,因为那时它只有参数变量声明的类(Object),而不是实例的类(String)。 Groovy 延迟了它的决定,因此它可以确定参数变量引用的实例的类,并使用它来确定哪个方法签名最匹配。
在上面的示例中,由于您指的是基于类而不是基于实例的静态成员,因此 Java 的继承思想(虚拟方法)没有发挥作用。 Java 再次从引用变量(Super.desc)的类中选择静态。 Groovy 再次采用延迟的、基于实例的路径,并询问实例它的静态成员是什么 (Sub.desc)。
请注意,大多数人会认为情况 3 的风格不好(询问实例类静态成员的值是什么),因此通常不应出现。
关于java - Groovy 和 Java 静态变量行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35946952/