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个”。
这些问题全是由子类中覆盖了父类的成员变量造成的,所以不要轻易覆盖父类的成员变量,而且很少一定要这么做。
相关推荐
首先,`super`关键字代表父类的对象,它用于在子类中访问父类的成员变量或方法。与之相对的是`this`关键字,它指代当前对象。当访问属性或方法时,如果未明确指定`this`或`super`,则会按照以下顺序查找:局部变量 -...
子类会自动获得父类的所有属性和方法,还可以添加自己的属性或方法,甚至覆盖父类的方法。 3. **多态** - 多态是指一个接口可以被不同类的对象实现。简单来说,多态允许我们使用一个通用的类型来表示不同类型的...
8. 代码示例:子类Sub试图覆盖父类Super的getNum()方法。选项B会引发编译错误,因为它改变了返回类型,这不属于合法覆盖。 9. `main`方法:`main`方法是Java程序的入口点,必须是public static,并且参数为String[]...
子类可以覆盖父类的方法并添加新的方法和变量。 - **多态**:允许子类对象向上转型为父类引用,从而实现了方法的重写和动态绑定,提高了程序的灵活性。 #### 异常的语法 - **异常处理**:Java使用try-catch-...
5. **子类覆盖父类方法**:子类可以覆盖(重写)父类的非私有实例方法,但不能覆盖私有方法。 6. **构造函数**:构造函数可以重载,即在同一个类中可以有多个构造函数,但不能覆盖,因为构造函数不是继承的一部分。...
- 子类可以覆盖父类的方法,以实现特定的功能。 - **继承的语法特点**: - 在Java中,子类通过关键字`extends`继承父类。 - Java不支持多重继承,但可以通过接口实现多继承的效果。 - **super的使用方法**: -...
当子类试图覆盖父类的一个方法但忘记使用`override`关键词时,将出现此错误。 ### 错误1021:重复标识符 在相同作用域内使用相同的标识符定义多个实体,将导致编译错误。 ### 错误1022:`final`与覆盖冲突 如果...
例如,可以创建一个`Product`类,包含显示产品信息的方法,然后为不同类型的 product 创建子类,如`SoundItem`或`ViewableItem`,覆盖父类的方法以适应各自的需求。通过数据库中产品的`type`字段实例化相应类,可以...
//r是私有成员变量,不能直接访问,通过作用域进行访问被派生类覆盖的函数f() } }; class B : virtual public R{ private: int b; public: B(int x, int y) :R(x), b(y) {} protected: void fB()//增加一个保护...
localVSmember.java 局部变量与成员变量同名问题示例 onlyTest.java 对象传值示例 otherClass.java 从类的外部访问对象的成员 showInstVar.java 演示不同的对象拥有不同的成员变量 showMain.java 演示main方法...
尝试从外部直接访问这些成员会引发`AttributeError`异常。但可以通过修改名字的方式访问它们: ```python foo = Foo() print(foo._Foo__name) # 输出:'private name' foo._Foo__spam() # 输出:'private method' `...
11. 结构和类的区别是结构是值类型,不具备继承特性,不能定义虚方法和抽象方法,不能有无参构造函数,不能为成员变量设初值。 12. 类型的初始化器是一个 static 方法,名称与类型相同,无参数无返回。 13. C# 中...
- **重写**(Overriding):子类覆盖父类的方法,方法名、参数列表、返回类型必须完全相同,但方法体可以不同。 ##### 静态内部类的作用 - **静态内部类**不需要外部类的实例就可以创建,通常用于封装与外部类相关的...
- **protected**:受保护的访问修饰符,表示该成员变量或方法可以在当前类、子类以及同一个包中的其他类中访问。 - **public**:公共访问修饰符,表示该成员变量或方法可以在任何地方被访问。 #### 类型定义与继承 ...
对象是类的实例,而类则定义了一组特性和行为,这些特性称为属性(或成员变量),行为则表现为方法(或成员函数)。本文将深入探讨PHP中的类与对象,特别是关于继承的概念。 首先,让我们了解如何在PHP中创建类。...
- **继承所有非私有成员**:子类继承父类所有的非私有属性和方法。 #### 子类的构造器 当子类创建实例时,它会先实例化父类,再实例化自身。子类构造器通常需要显式地调用父类的构造器,这通常是通过`super()`实现...
即使子类覆盖父类的函数时不显式声明 `virtual`,由于C++的隐式继承特性,多态依然能够实现。这意味着在父类指针或引用调用该函数时,会根据实际的对象类型调用相应的实现。 4. **C 与 C++ 的差异**:C 是面向过程...
public void test(int i) { // 覆盖父类方法 // ... } } ``` 注意,在方法覆盖时,子类方法的访问级别不能比父类方法更低,例如父类方法是 `public`,则子类覆盖的方法也必须是 `public` 或者更高。 #### 11....
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 使用接口仅需一步...
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 使用接口仅需一步...