Java 为什么下面的代码编译并运行成功?

Java 为什么下面的代码编译并运行成功?,java,inheritance,encapsulation,Java,Inheritance,Encapsulation,我有两个JAVA类: 父类: public class Parent { private int age; public void setAge(int age) { this.age = age; } public int getAge(){ return this.age; } } public class Child extends Parent{ pub

我有两个JAVA类:

父类:

public class Parent {
    private int age;

    public void setAge(int age) {           
        this.age = age;
    }

    public int getAge(){
        return this.age;
    }       
}
public class Child extends Parent{      

    public static void main(String[] args){

        Parent p = new Parent();
        p.setAge(35);
        System.out.println("Parent   "+p.getAge());

        Child c = new Child();
        System.out.println("Child  " + c.getAge());         
    }
}
子类:

public class Parent {
    private int age;

    public void setAge(int age) {           
        this.age = age;
    }

    public int getAge(){
        return this.age;
    }       
}
public class Child extends Parent{      

    public static void main(String[] args){

        Parent p = new Parent();
        p.setAge(35);
        System.out.println("Parent   "+p.getAge());

        Child c = new Child();
        System.out.println("Child  " + c.getAge());         
    }
}
输出为:

  Parent   35
  Child     0
私有成员不是在JAVA中继承的
在子类实例上调用
getAge()
方法时,为什么它会成功运行,甚至输出为
0

您正在访问
getAge()
方法,该方法是公共的合法的。
getAge()
的实现是访问它的
私有成员,而不是您。

编程语言最基本的方面之一是如何初始化数据。对于Java,这是在语言规范中明确定义的。对于字段和阵列组件,创建项时,系统会自动将其设置为以下默认值:

numbers: 0 or 0.0
booleans: false
object references: null 
这意味着显式地将字段设置为0、false或null(视情况而定)是不必要和冗余的。由于包含此语言功能部分是为了减少重复编码,因此充分利用它是一个好主意。坚持字段应显式初始化为0、false或null是一种习惯用法,这可能不适合Java编程语言


此外,将字段显式设置为0、false或null甚至可能导致同一操作执行两次(取决于编译器)

继承:您从
方法
获取值,而不是从
变量
获取值

默认值

  • 类类型(非原语,对象):
    null
  • 基元类型(int、float等):0

请参考Java文档了解继承:

私有成员未被继承,但访问它的公共方法是

当您创建类型为
Child
的对象时,如果不能直接使用,也会创建超类的所有变量


如果超类中有公共方法,则可以从子类访问它们。如果这些方法访问超类的私有变量值,您可以通过公共方法间接访问它们。

对于父类,没有constractor,因此JAVA生成default constractor

当孩子延伸父母时,他实际上是先去他的父母那里

您可以在父类中生成此构造函数:

public Parent(){
   this.age = 15;
}
当你打印出来的时候,你会看到孩子的年龄是15岁

public class Child extends Parent{      

    public static void main(String[] args){

        Parent p = new Parent();
        p.setAge(35);
        System.out.println("Parent   "+p.getAge());


        Child c = new Child();
        System.out.println("Child  " + c.age);      //can't access private 
        System.out.println("Child  " + c.name);     //can access public variable
        System.out.println("Child  " + c.getAge()); //can access public method
        System.out.println("Child  " + c.getName());//can,t access private method 

    }
}

class Parent {
    private int age;
    public String name;

    public void setAge(int age){

        this.age = age;
    }

    private String getName(){
        return name;
    }

    public int getAge(){
        return this.age;
    }

}
  • 无法在类之外访问私有变量。但是我们可以通过
    getter
    setter
    访问它。这里介绍了
    OOP
    封装的概念
  • 公共
    方法
    父类中定义的变量
    可以在子类中访问。这里有
    OOP
    继承的概念

访问修饰符顾名思义,只能影响变量/方法的可访问性而不是继承性,您不能直接在子类中访问
age
变量,因为它是
private
,但这并不意味着它不存在于子对象中

因此,在您的情况下,两个公共方法都可以从两个类中访问,但在您的子类中,您不能直接使用
age
,除非您将其访问修饰符更改为
protected
public

为了更好地理解,请看一看


你也可以检查一下,加上我的几美分。子类无法访问父类的
private
可变年龄部分。但是年龄状态仍然是子对象的一部分。您可以使用get和set方法进行访问。为了进一步说明,您可以在child对象上调用
setAge()
,以设置适当的child年龄

public class Child extends Parent {
    public static void main(String[] args) {
        Parent p = new Parent();
        p.setAge(35);
        System.out.println("Parent "+p.getAge());

        Child c = new Child();
        c.setAge(20);
        System.out.println("Child " + c.getAge());
    }
}
输出:

Parent 35
Child 20

私有成员不是继承的权利,但我们可以通过公共方法访问它。所以在您的情况下,私有成员是通过公共方法访问的。
而之所以取值为零,是因为变量年龄的取值由父类对象而不是子类对象决定。因此,当您通过子类对象访问age变量的值时,它会打印变量age的默认值。

您在此处调用了
public
方法而不是
private
变量。谢谢,但由于该方法现在已被继承,并且正在从子类实例调用,它是否只会在自己的范围内查找变量?否,超类的公共方法的主体可以访问超类的私有变量和其他私有方法。实现细节隐藏在不知道如何收集数据的子类中。