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

Why does following code compile and run successfully?

我在 JAVA 中有 2 个 classes:

Parent Class:

public class Parent {
    private int age;

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

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

Child Class:

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中不被继承 在child class 实例上调用getAge() 方法时,为什么它运行 成功,甚至输出为0?

您正在访问 getAge() 方法,该方法 public 是合法的。 getAge() 的实现正在访问它的 private 成员,而不是你。

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

numbers: 0 or 0.0
booleans: false
object references: null 

这意味着将字段显式设置为 0、false 或 null(视情况而定)是不必要且多余的。由于包含此语言功能是为了在一定程度上减少重复编码,因此最好充分利用它。坚持将字段显式初始化为 0、false 或 null 是一种习惯用法,可能不适合 Java 编程语言。

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

继承:您从 method 而不是 variable 获得价值。

默认值

  • Class 类型(非原始,对象):null
  • 基本类型(整数、浮点等):0

请参考 Java 关于继承的文档:https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

私有成员不被继承,但是 public 访问它的方法是。

当您创建 Child 类型的对象时,超类的所有变量如果不是直接可用的,也会被创建。

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

对于 Parent class 没有构造函数,因此 JAVA 创建默认构造函数。

当 Child 扩展 Parent 他实际上首先去他的 parent constactor。

您可以在 Parent class 中构建此构造函数:

public Parent(){
   this.age = 15;
}

你会看到child打印出来的时候年龄是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;
    }

}
  • 无法在 class 之外访问私有变量。但我们可以通过 gettersetter 使其可访问。 OOP 封装 的概念出现了。
  • public methods, variables 在父 class 中定义可以在子 class 中访问。 OOP 继承 的概念出现了。

访问修饰符 顾名思义只能影响 variables/methods 的可访问性而不影响继承,您不能直接在 [=28] 中访问 age 变量=] class 因为它是 private 但这并不意味着它不存在于 child object.

所以在你的情况下,两个 public 方法都可以从两个 classes 访问但是在你的 Child class 中你不能直接使用 age 除非您将其访问修饰符更改为 protectedpublic

为了更好地理解看看Controlling Access to Members of a Class

你也可以检查Do access modifiers prevent inheritance?

加上我的几美分。 Child class 无法访问 Parent class 的 private 变量 age。但是年龄状态仍然是Childobject的一部分。您可以使用 get 和 set 方法进行访问。为了进一步说明,您可以在 child object 上调用 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

私有成员没有继承权,但是我们可以通过public方法访问。因此,在您的情况下,私有成员可以通过 public 方法访问。 之所以值为零,是因为变量 age 的值是父 class 对象而不是子 class 对象。因此,当您通过子 class 对象访问 age 变量的值时,它会打印变量 age 的默认值。