为什么Java中的final常量可以被重写?
考虑 Java 中的以下接口:
public interface I {
public final String KEY = "a";
}
以及以下类:
public class A implements I {
public String KEY = "b";
public String getKey() {
return KEY;
}
}
为什么类 A 可以覆盖接口 I 的最终常量?
自己尝试一下:
A a = new A();
String s = a.getKey(); // returns "b"!!!
Consider the following interface in Java:
public interface I {
public final String KEY = "a";
}
And the following class:
public class A implements I {
public String KEY = "b";
public String getKey() {
return KEY;
}
}
Why is it possible for class A to come along and override interface I's final constant?
Try for yourself:
A a = new A();
String s = a.getKey(); // returns "b"!!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
你把它隐藏起来了,这是“Scope”的一个功能。 任何时候你在一个较小的作用域中,你都可以重新定义你喜欢的所有变量,外部作用域变量将被“隐藏”
顺便说一句,如果你愿意,你可以再次作用域:
现在KEY将返回“c”;
编辑是因为重读时原著很烂。
You are hiding it, it's a feature of "Scope". Any time you are in a smaller scope, you can redefine all the variables you like and the outer scope variables will be "Shadowed"
By the way, you can scope it again if you like:
Now KEY will return "c";
Edited because the original sucked upon re-reading.
尽管您正在隐藏变量,但知道您可以更改 java 中的最终字段是非常有趣的,因为您可以阅读 此处:
Despite the fact that you are shadowing the variable it's quite interesting to know that you can change final fields in java as you can read here:
看起来您的类只是隐藏变量,而不是覆盖它:
这将打印“B”和“A”,正如您所发现的那样。 您甚至可以为其赋值,因为 A.KEY 变量未定义为最终变量。
但 -
It looks like your class is simply hiding the variable, not overwriting it:
This will print "B", and "A", as you found. You can even assign to it, as the A.KEY variable is not defined as final.
But -
作为设计考虑,
静态方法始终返回父键。
正如乔姆所注意到的那样。 使用重新定义的接口成员的静态方法的设计可能是一个严重的问题。 一般来说,尽量避免对常量使用相同的名称。
As a design consideration,
The static methods always returns the parent key.
Just like Jom has noticed. The design of static methods using re-defined interface members could be a heavy problem. In general, try to avoid use the same name for the constant.
您不应该以这种方式访问常量,而应使用静态引用:
You should not access your constant in this way, use the static reference instead:
静态字段和方法附加到声明它们的类/接口(尽管接口不能声明静态方法,因为它们是需要实现的完全抽象类)。
因此,如果您有一个带有 public static (vartype) (varname) 的接口,
该字段附加到该接口。
如果您有一个类实现该接口,则编译器技巧会将 (this.)varname 转换为 InterfaceName.varname。 但是,如果您的类重新定义了 varname,则会将一个名为 varname 的新常量附加到您的类,并且编译器现在知道将 (this.)varname 翻译为 NewClass.varname。 这同样适用于方法:如果新类没有重新定义方法,则 (this.)methodName 被翻译为 SuperClass.methodName,否则,(this.)methodName 被翻译为 CurrentClass.methodName。
这就是为什么您会遇到警告“x 字段/方法应该以静态方式访问”。 编译器告诉您,尽管它可能会使用该技巧,但它更愿意您使用 ClassName.method/fieldName,因为出于可读性目的,它更加明确。
Static fields and methods are attached to the class/interface declaring them (though interfaces cannot declare static methods as they are wholly abstract classes which need to be implemented).
So, if you have an interface with a public static (vartype) (varname),
that field is attached to that interface.
If you have a class implement that interface, the compiler trick transforms (this.)varname into InterfaceName.varname. But, if your class redefines varname, a new constant named varname is attached to your class, and the compiler knows to now translate (this.)varname into NewClass.varname. The same applies for methods: if the new class does not re-define the method, (this.)methodName is translated into SuperClass.methodName, otherwise, (this.)methodName is translated into CurrentClass.methodName.
This is why you will encounter the warning "x field/method should be accessed in a static way". The compiler is telling you that, although it may use the trick, it would prefer that you used ClassName.method/fieldName, because it is more explicit for readability purposes.