Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么通过方法返回子类对象调用超类变量?_Java - Fatal编程技术网

Java 为什么通过方法返回子类对象调用超类变量?

Java 为什么通过方法返回子类对象调用超类变量?,java,Java,我知道变量没有多态性。如果我们执行新的Subclass().x,那么在运行时将打印值20。 但是这里是 Parent p = new Child(); p.getObject(); 子类的getObject()将被调用,因为子类的getObject将覆盖超类的getObject()。因此子类方法getObject()返回新的Child(),所以打印的值应该是Child.x ie 20的值。但是输出是10。为什么x的值是超类的值???我知道有一些帖子与此相关,但并不是所有地方都解释了这一点

我知道变量没有多态性。如果我们执行新的Subclass().x,那么在运行时将打印值20。 但是这里是

Parent p = new Child();   
p.getObject();
子类的getObject()将被调用,因为子类的getObject将覆盖超类的getObject()。因此子类方法getObject()返回新的Child(),所以打印的值应该是Child.x ie 20的值。但是输出是10。为什么x的值是超类的值???我知道有一些帖子与此相关,但并不是所有地方都解释了这一点。请帮忙

class MainClass {
     public static void main(String[] args) {
      Parent p = new Child();
      System.out.println(p.getObject().x);
     }
    }

    class Parent {
     int x = 10;

     public Parent getObject() {
      return new Parent();
     }
    } 

    class Child extends Parent {
     int x = 20;

     public Child getObject() {
      return new Child();
     }
    }

您正在类
Parent
中访问变量
x
,因为
p.getObject()
的声明类型是
Parent


顺便说一句:访问对象内部的变量直接违反了OOP最基本的原则:信息隐藏/封装!您应该仅对用作纯数据容器且自身没有业务逻辑的数据传输对象/值对象执行此操作。即使在那里,您也应该使用getter/setter方法,而不是直接访问变量…

您正在访问类
Parent
中的变量
x
,因为
p.getObject()
的声明类型是
Parent


顺便说一句:访问对象内部的变量直接违反了OOP最基本的原则:信息隐藏/封装!您应该仅对用作纯数据容器且自身没有业务逻辑的数据传输对象/值对象执行此操作。即使在那里,您也应该使用getter/setter方法而不是直接变量访问…

这都是关于Java中的内存分配的

Parent p=new Child()
意味着您正在堆上创建一个属于类Child的对象和一个名为p的对该对象的引用,但此引用旨在与类Parent的对象一起操作。 因此,您正在分配一个类型为Child的对象,但引用正在使用Parent操作

这意味着,引用将无法看到子对象的x属性。它将只看到父属性


检查一下,它也是关于Java中内存分配的

Parent p=new Child()
意味着您正在堆上创建一个属于类Child的对象和一个名为p的对该对象的引用,但此引用旨在与类Parent的对象一起操作。 因此,您正在分配一个类型为Child的对象,但引用正在使用Parent操作

这意味着,引用将无法看到子对象的x属性。它将只看到父属性


查看,以及

您所做的被称为阴影。若您声明的变量名称已在可访问范围内定义,那个么该变量将隐藏(隐藏)已定义的变量。若要使用外部作用域中的变量,必须写入该变量的绝对路径或使用该变量唯一的访问器

public class A {
    int a;

    public A(int a) {
        System.out.println(a); // arg "a" has shadowed class field
        System.out.println(this.a);

        // that's why we are using this assignment:
        this.a = a;
    }
}
你的例子也是如此
child.x
已隐藏了
parent.x
字段。如果对象引用为
子类
类型i。e<代码>子项c=新子项(),则默认情况下将使用最近的可访问变量
x
Child.x
)。如果您的对象引用属于
父对象
类型i。e<代码>父级p=新父级(),然后再次使用最近的可访问的
x
Parent.x
)。这同样适用于
Parent p=new Child()由于
p
新的子项
但升级为
Parent
类型,因此
p.x
将显示
Parent.x

您只需记住,多态性不适用于类字段。除非字段值包装在某个getter中,否则不能重写它

因此,如果您需要覆盖显示的值,则必须将该值包装在某个getter中,该getter将被
子类
覆盖:

public class Test {
    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.getObject().getValue()); // 20
        System.out.println(p.getValue()); // 20
    }

    static class Parent {
        int x = 10;

        public int getValue() {return x;}

        public Parent getObject() {return new Parent();}
    }

    static class Child extends Parent {
        int x = 20;

        @Override
        public int getValue() {return x;} // return Child.x

        @Override
        public Child getObject() {return new Child();}
    }
}

你所做的被称为“阴影”。若您声明的变量名称已在可访问范围内定义,那个么该变量将隐藏(隐藏)已定义的变量。若要使用外部作用域中的变量,必须写入该变量的绝对路径或使用该变量唯一的访问器

public class A {
    int a;

    public A(int a) {
        System.out.println(a); // arg "a" has shadowed class field
        System.out.println(this.a);

        // that's why we are using this assignment:
        this.a = a;
    }
}
你的例子也是如此
child.x
已隐藏了
parent.x
字段。如果对象引用为
子类
类型i。e<代码>子项c=新子项()
,则默认情况下将使用最近的可访问变量
x
Child.x
)。如果您的对象引用属于
父对象
类型i。e<代码>父级p=新父级(),然后再次使用最近的可访问的
x
Parent.x
)。这同样适用于
Parent p=new Child()由于
p
新的子项
但升级为
Parent
类型,因此
p.x
将显示
Parent.x

您只需记住,多态性不适用于类字段。除非字段值包装在某个getter中,否则不能重写它

因此,如果您需要覆盖显示的值,则必须将该值包装在某个getter中,该getter将被
子类
覆盖:

public class Test {
    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.getObject().getValue()); // 20
        System.out.println(p.getValue()); // 20
    }

    static class Parent {
        int x = 10;

        public int getValue() {return x;}

        public Parent getObject() {return new Parent();}
    }

    static class Child extends Parent {
        int x = 20;

        @Override
        public int getValue() {return x;} // return Child.x

        @Override
        public Child getObject() {return new Child();}
    }
}

在java中,不需要简单地重写变量!还有。。。。您正在执行返回新父对象()的操作;如果我写new Child().x,那么打印的值将是20,而不是p.getObject().x。但是p.getObject()输出是new Child(),然后转换为new Child().x,但输出仍然是10。为什么父类中的getObject()会被子类getObject()覆盖,对吗?java中的变量不是简单的覆盖!还有。。。。您正在执行返回新父对象()的操作;如果我写新的Child().x,那么打印的值将是20,而不是p.getObject().x