这让我困扰了很长时间,所以我想我会继续问问。
如果我写
import java.util.*;
import java.lang.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
new Shape();
new Triangle();
}
public static class Shape
{
static String name = "shape";
Shape()
{
printName();
}
public void printName()
{
System.out.println( name() );
}
public String name()
{
return name;
}
}
public static class Triangle extends Shape
{
static String name = "triangle";
public String name()
{
return name;
}
}
}
然后输出
shape
triangle
但如果我写
import java.util.*;
import java.lang.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
new Shape();
new Triangle();
}
public static class Shape
{
static String name = "shape";
Shape()
{
printName();
}
public void printName()
{
System.out.println( name );
}
}
public static class Triangle extends Shape
{
static String name = "triangle";
}
}
然后输出
shape
shape
在第一个版本中,我必须将相同的函数getName()一遍又一遍地复制/粘贴到每个子类中。必须有一个更好的方法。在第二个例子中我需要改变什么?
答案 0 :(得分:5)
无法从父类访问静态字段。类Shape
不会“看到”类name
的静态字段Triangle
并使用自己的静态字段name
。
UPD:您问:第二个例子中您需要更改什么?更具体地说,您的第一个示例是正确“修复”您的第二个示例。唯一正确的方法是使用一些getter方法,例如name()
方法。
UPD2:(来自我的评论):嗯,另一种方式:原谅任何类型的字段name
。使用名为name()
的方法(非静态!),它将在每个类中返回所需的名称。其中只有return "shape";
或return "triangle"
;
答案 1 :(得分:1)
好吧,我已经用否定键回答了这个问题。但作为一种笑话和有趣的解决方案(可以工作!!! ),您可以将printName()
方法更改为此方法:
public void printName() throws NoSuchFieldException, IllegalAccessException {
System.out.println((String)(this.getClass().getDeclaredField("name").get(this)));
}
这只是一个更改,您需要在第二个示例中执行此操作才能获得输出
shape
triangle
答案 2 :(得分:0)
这是Java如何将名称解析为值的一个很好的例子。您有两个名为name
的变量,一个位于Shape
,另一个位于Triangle
。即使Triangle
是Shape
的子类,这些也是完全不相关的变量。这是因为它们是静态的;静态事物永远不会覆盖,因为它们属于类,而不是对象。在Shape
中,当您引用name
时,这是Shape.name
的真正简写。同样,在Triangle
中,name
表示Triangle.name
。 相同符号指的是不同范围中的不同变量。
在此代码中:
public class Shape {
static String name = "shape";
public static void main(String[] args) {
System.out.println(name);
}
}
class Colour {
static String name = "colour";
}
你不会想到输出会是“颜色”,你呢?这正是您显示的代码中的情况。这两个类之间的继承关系只是一个红色的鲱鱼。
如果您希望名称是多态的,那么您唯一的选择是使用实例方法,因为实例方法是唯一可以是多态的。最简洁的方法是将常量内联到方法中:
class Main {
public static void main(String[] args) {
new Shape();
new Triangle();
}
public static class Shape {
Shape() {
printName();
}
public void printName() {
System.out.println(name());
}
public String name() {
return "shape";
}
}
public static class Triangle extends Shape {
@Override
public String name() {
return "triangle";
}
}
}
答案 3 :(得分:0)
您可以使用最终字段并在构造函数中设置它,但恕我直言,最好覆盖getter。
public static class Shape
{
protected final String name;
public Shape()
{
this("shape");
}
protected Shape(String name)
{
this.name = name;
}
public void printName()
{
System.out.println( name() );
}
public String name()
{
return name;
}
}
public static class Triangle extends Shape
{
public Triangle()
{
super("triangle");
}
}