为啥下面的代码编译运行成功? [复制]

Posted

技术标签:

【中文标题】为啥下面的代码编译运行成功? [复制]【英文标题】:Why does following code compile and run successfully? [duplicate]为什么下面的代码编译运行成功? [复制] 【发布时间】:2015-10-14 17:06:20 【问题描述】:

我有 2 个 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());         
    

输出是:

  Parent   35
  Child     0

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

【问题讨论】:

你在这里调用了public方法而不是private变量 【参考方案1】:

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

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

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

【讨论】:

谢谢,但是由于该方法现在已被继承并且正在从子类实例中调用它,它不只是在自己的范围内查找变量吗? 不,超类的公共方法体可以访问私有变量,也可以访问超类的其他私有方法。实现细节隐藏到不知道如何收集数据的子类中。【参考方案2】:

访问修饰符顾名思义只能影响变量/方法的可访问性而不是继承,您不能直接在 Child 类中访问 age 变量,因为它是 private 但它不会t 表示子对象不存在。

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

更多了解请看Controlling Access to Members of a Class

您也可以查看Do access modifiers prevent inheritance?

【讨论】:

【参考方案3】:

继承:您从method 获得价值,而不是从variable默认值

类类型(非原始,对象):null 原始类型(int、float 等):0

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

【讨论】:

【参考方案4】:

对于 Parent 类没有构造函数,因此 JAVA 会创建一个默认构造函数。

当 Child 扩展 Parent 时,他实际上首先去他的父 constactor。

你可以在父类中构建这个构造函数:

public Parent()
   this.age = 15;

当您打印它时,您会看到孩子的年龄为 15 岁。

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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

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

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

【讨论】:

【参考方案7】:
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;
    


不能在类外访问私有变量。但我们可以通过gettersetter 访问它。 OOP 封装的概念在这里出现。 在Parent类中定义的publicmethodsvariables可以在子类中访问。 OOP 继承的概念在这里出现。

【讨论】:

【参考方案8】:

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

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

【讨论】:

【参考方案9】:

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

【讨论】:

以上是关于为啥下面的代码编译运行成功? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个类不编译? [复制]

使用部分函数时并未include其所在头文件,但是能编译成功且能运行,为什么?

ASP.NET编译成功后,为啥有些功能不会执行?麻烦高手解答!

没有头文件,为啥下面的程序能运行

尽管注释掉了所需的头文件,为啥这个 C++ 程序仍能编译和运行? [复制]

为啥相同的代码相同的编译器在不同电脑上的运行结果不同?