隐藏属性的Java字段

时间:2012-12-21 04:55:13

标签: java field

我刚开始学习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 个答案:

答案 0 :(得分:3)

当你致电s1.toString()时,它发现只在toString()类中定义Super方法,因此使用该方法,因为子类中有超类方法。 您的超类方法toString()正在使用它自己的类变量str(在超类中初始化值)作为方法的返回值,因此行为即输出为{ {1}}。

如果要将输出作为I'm super!,则需要重用与超类中相同的变量,并为其分配新的字符串值,即I'm sub.\n。最好的选择是使用构造函数:

I'm sub.\n

答案 1 :(得分:2)

你在你的孩子班级中隐藏(遮蔽)str。由于您未在子类中重写toString(),因此将在父类中进行调用,并且它将看到父类str

如果你这样做了:

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

它会输出你期望的东西。

答案 2 :(得分:1)

此调用使用超类:

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

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

如果它们意味着不同的东西,你可以给它们不同的名字。或者可以使用getter方法Sub访问(或修改)父项的属性。

答案 3 :(得分: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
        }
    }
}

有关详细信息,请参阅Controlling Access to Members of a Class