4

我刚开始学习Java,所以如果答案有些明显,请多多包涵。我做了一些研究,但无济于事。

据我了解,属性不会被覆盖,而只会隐藏字段。为了确定是使用超类还是子类中的属性,Java 会检查引用的类型。

然后我不明白这里的输出:

public class Super {
    String str = "I'm super!\n";

    public String toString() {
        return str;
    }
}

public class Sub extends Super {
    String str = "I'm sub.\n";
}

public class TestFH {
    public static void main(String[] args) {
        Sub s1 = new Sub();

        System.out.printf(s1.toString());
    }
}

它给了我:

I'm super!

我知道我可以通过方法覆盖轻松实现我想要的。我只是好奇引擎盖下发生了什么。

提前致谢。

4

4 回答 4

4

当您调用时s1.toString(),它会查找toString()仅在Super类中定义的方法,因此使用该方法作为超类方法在子类中可用。您的超类方法toString()使用它自己的类变量str(在超类中初始化值)作为方法的返回值,因此行为即输出为I'm super!.

如果您想获得输出,I'm sub.\n那么您需要重用与超类中相同的变量并将新的字符串值分配I'm sub.\n给它。最好的选择是使用构造函数:

  public class Super {
     String str = "I'm super!\n";

     public Super(String stringValue){
         this.str = stringValue;
     }

     public String toString() {
        return str;
     }
  }

  public class Sub extends Super {
     public Sub(){
       super("I'm sub.\n");
     }
  }

  public class TestFH {
    public static void main(String[] args) {
       Sub s1 = new Sub();
       System.out.printf(s1.toString());
    }
  }
于 2012-12-21T05:00:10.767 回答
2

str在你的孩子班里隐藏(阴影)。由于您没有toString()在子类中覆盖,因此正在父类中进行调用,并且它会看到父类的str.

如果你这样做:

public class Sub extends Super {
    public Sub() {
        this.str = "I'm sub.\n";
    }
}

它会输出你所期望的。

于 2012-12-21T05:06:55.097 回答
1

此调用使用超类:

Sub s1 = new Sub();
System.out.printf(s1.toString());

原因是Sub 没有覆盖 str,它只是声明了另一个恰好具有相同名称的变量。换句话说, sub 只是将变量隐藏在Super(数据成员不是多态的)中。

如果它们的含义不同,你可以给它们起不同的名字。或者也许可以Sub使用 getter 方法访问(或修改)父级的属性。

于 2012-12-21T04:59:32.900 回答
1

您没有将字符串文字分配给"I'm sub.\n"共享的超类字段,而是创建了子类本地的字段并将其分配给该字段。

例如,

public class EncapsulationDemo {

    public static void main(String[] args){
        MySuperObject obj = new MySubObject();

        System.out.println(obj); // prints I'm sub.
    }

    private static class MySuperObject{
        String str = "I'm super."; // protected, can be accessed directly 
                                   // by subclasses

        @Override
        public String toString(){
            return str;
        }
    }

    private static class MySubObject extends MySuperObject{
        MySubObject(){
            super();
            str = "I'm sub."; // assign to superclass field
        }
    }
}

有关详细信息,请参阅控制对类成员的访问

于 2012-12-21T05:02:46.723 回答