`
woodenfish
  • 浏览: 5960 次
社区版块
存档分类
最新评论

覆盖了父类的成员变量引发的问题

    博客分类:
  • Java
阅读更多

    this代表什么呢?代表当前类的某个对象?请看下面这段代码:

package cn.com.wg.task01;
 
public class CallOrder {
   class Base {
      private int i = 2;
      public Base() {
         System.out.println(this);
         this.display();
      }
      public void display() {
         System.out.println("Base " +this.i);
      }
   }
 
   class Child extends Base {
      private int i = 22;
      public Child() {
         System.out.println(this);
         i = 222;
      }
      public void display() {
         System.out.println("Child " + i);
      }
   }
 
   public void init() {
      new Child();
   }
 
   public static void main(String[] args) {
      new CallOrder().init();
   }
}

输出结果是什么呢?

cn.com.wg.task01.CallOrder$Child@d0da1d8
Child 0
cn.com.wg.task01.CallOrder$Child@d0da1d8

 

此时,子类和父类构造函数的this代表同一个对象!!!this理解为代表调用该方法的那个对象更合适。

我们知道子类的构造函数会调用父类的构造函数(如果没有显示的调用,默认隐式调用无参的构造函数),所以在该程序中,父类的无参构造函数会在子类的构造函数中调用。因此,子类和父类构造函数的this代表同一个对象。

 

那么,输出的“Child 0”怎么解释呢?这里就牵涉到JVM的内存分配了。下面简单介绍。

当JVM遇到new关键字时,就会开始在内存中给对象分配空间。一个简单的java对象的在内存中包括三个部分:对象头、变量、填充区域。new结束后,变量域是初始化后的值(即boolean为false,char为'\0',其他基本类型为0,对象为null)。当遇到new后的类名是才开始执行我们代码中的构造函数。

 

这是用javap看到的class文件中Child的构造函数内容:

 


 

这是Base类的构造函数:

在Base类的构造函数中调用display方法,显然是调用在Child里写的display方法,i也是Child里的i。但是Child中,i的初始化是在调用display之前完成的,所以此时i=0;

 

如果我们把Child里的display去除,会输出什么呢?“Base 2”。此时调用的display肯定是Base里的了,而且i的初始化在调用display之前,而且这个i是在Base中声明的。那么,问题来了,Child对象中有几个i变量呢?“2个”。

 

 

这些问题全是由子类中覆盖了父类的成员变量造成的,所以不要轻易覆盖父类的成员变量,而且很少一定要这么做

 

 

  • 大小: 59.5 KB
  • 大小: 10.3 KB
分享到:
评论

相关推荐

    Java面向对象的学习(关键字)

    首先,`super`关键字代表父类的对象,它用于在子类中访问父类的成员变量或方法。与之相对的是`this`关键字,它指代当前对象。当访问属性或方法时,如果未明确指定`this`或`super`,则会按照以下顺序查找:局部变量 -...

    程序员面试宝典 读书笔记

    子类会自动获得父类的所有属性和方法,还可以添加自己的属性或方法,甚至覆盖父类的方法。 3. **多态** - 多态是指一个接口可以被不同类的对象实现。简单来说,多态允许我们使用一个通用的类型来表示不同类型的...

    java试题集.pdf

    8. 代码示例:子类Sub试图覆盖父类Super的getNum()方法。选项B会引发编译错误,因为它改变了返回类型,这不属于合法覆盖。 9. `main`方法:`main`方法是Java程序的入口点,必须是public static,并且参数为String[]...

    笔试题之Java基础部分

    子类可以覆盖父类的方法并添加新的方法和变量。 - **多态**:允许子类对象向上转型为父类引用,从而实现了方法的重写和动态绑定,提高了程序的灵活性。 #### 异常的语法 - **异常处理**:Java使用try-catch-...

    全国计算机等级考试二级Java试卷.docx

    5. **子类覆盖父类方法**:子类可以覆盖(重写)父类的非私有实例方法,但不能覆盖私有方法。 6. **构造函数**:构造函数可以重载,即在同一个类中可以有多个构造函数,但不能覆盖,因为构造函数不是继承的一部分。...

    JAVA知识点列表 JAVA知识点列表

    - 子类可以覆盖父类的方法,以实现特定的功能。 - **继承的语法特点**: - 在Java中,子类通过关键字`extends`继承父类。 - Java不支持多重继承,但可以通过接口实现多继承的效果。 - **super的使用方法**: -...

    ActionScript 3.0编译器编译错误大全

    当子类试图覆盖父类的一个方法但忘记使用`override`关键词时,将出现此错误。 ### 错误1021:重复标识符 在相同作用域内使用相同的标识符定义多个实体,将导致编译错误。 ### 错误1022:`final`与覆盖冲突 如果...

    php中高级OOP技术

    例如,可以创建一个`Product`类,包含显示产品信息的方法,然后为不同类型的 product 创建子类,如`SoundItem`或`ViewableItem`,覆盖父类的方法以适应各自的需求。通过数据库中产品的`type`字段实例化相应类,可以...

    C++多重继承引发的重复调用问题与解决方法

    //r是私有成员变量,不能直接访问,通过作用域进行访问被派生类覆盖的函数f() } }; class B : virtual public R{ private: int b; public: B(int x, int y) :R(x), b(y) {} protected: void fB()//增加一个保护...

    Java开发技术大全(500个源代码).

    localVSmember.java 局部变量与成员变量同名问题示例 onlyTest.java 对象传值示例 otherClass.java 从类的外部访问对象的成员 showInstVar.java 演示不同的对象拥有不同的成员变量 showMain.java 演示main方法...

    浅谈Python中带_的变量或函数命名

    尝试从外部直接访问这些成员会引发`AttributeError`异常。但可以通过修改名字的方式访问它们: ```python foo = Foo() print(foo._Foo__name) # 输出:'private name' foo._Foo__spam() # 输出:'private method' `...

    .NET知识点整理学习资料.pdf

    11. 结构和类的区别是结构是值类型,不具备继承特性,不能定义虚方法和抽象方法,不能有无参构造函数,不能为成员变量设初值。 12. 类型的初始化器是一个 static 方法,名称与类型相同,无参数无返回。 13. C# 中...

    java经典问题答案

    - **重写**(Overriding):子类覆盖父类的方法,方法名、参数列表、返回类型必须完全相同,但方法体可以不同。 ##### 静态内部类的作用 - **静态内部类**不需要外部类的实例就可以创建,通常用于封装与外部类相关的...

    面试总结一

    - **protected**:受保护的访问修饰符,表示该成员变量或方法可以在当前类、子类以及同一个包中的其他类中访问。 - **public**:公共访问修饰符,表示该成员变量或方法可以在任何地方被访问。 #### 类型定义与继承 ...

    详解php中的类与对象(继承)

    对象是类的实例,而类则定义了一组特性和行为,这些特性称为属性(或成员变量),行为则表现为方法(或成员函数)。本文将深入探讨PHP中的类与对象,特别是关于继承的概念。 首先,让我们了解如何在PHP中创建类。...

    JAVA编程基础-06面向对象高级特性-zhouxl.pdf

    - **继承所有非私有成员**:子类继承父类所有的非私有属性和方法。 #### 子类的构造器 当子类创建实例时,它会先实例化父类,再实例化自身。子类构造器通常需要显式地调用父类的构造器,这通常是通过`super()`实现...

    近期出现的C++面试题整理(附详细答案).docx

    即使子类覆盖父类的函数时不显式声明 `virtual`,由于C++的隐式继承特性,多态依然能够实现。这意味着在父类指针或引用调用该函数时,会根据实际的对象类型调用相应的实现。 4. **C 与 C++ 的差异**:C 是面向过程...

    java基础知识总结

    public void test(int i) { // 覆盖父类方法 // ... } } ``` 注意,在方法覆盖时,子类方法的访问级别不能比父类方法更低,例如父类方法是 `public`,则子类覆盖的方法也必须是 `public` 或者更高。 #### 11....

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    12.1.2 引发问题的自行车 335 12.1.3 仔细分析recordTransport()方法 338 12.2 初用接口 339 12.2.1 准备好需要用到的类 339 12.2.2 认识接口的代码组成 340 12.2.3 什么是接口 341 12.2.4 使用接口仅需一步...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    12.1.2 引发问题的自行车 335 12.1.3 仔细分析recordTransport()方法 338 12.2 初用接口 339 12.2.1 准备好需要用到的类 339 12.2.2 认识接口的代码组成 340 12.2.3 什么是接口 341 12.2.4 使用接口仅需一步...

Global site tag (gtag.js) - Google Analytics