首先明确一点:Java中除了static方法和final方法(private方法属于final方法)之外,其他所有的方法都是动态绑定的。
设想这样一个场景:在父类的构造器中调用一个动态绑定方法(假设叫做A),其子类重写了A方法,然后生成子类对象(目的是调用构造器),会发生什么?来看下面一个例子:
public class Test{
public static void main(String[] args) {
new B(5);
}
}
class A{
void draw(){
System.out.println("A.draw()");
}
A(){
System.out.println("A() before draw()");
draw();
System.out.println("A() after draw()");
}
}
class B extends A{
private int radius =1;
public B(int r) {
System.out.println("after the base constructor:"+radius);
radius=r;
System.out.println("B.B(), radius="+radius);
}
void draw(){
System.out.println("B.draw(), radius="+radius);
}
}
会出现什么结果?
A() before draw()
B.draw(), radius=0
A() after draw()
after the base constructor:1
B.B(), radius=5
调用父类构造器时,动态绑定的draw方法实际执行的是子类的draw。如果程序运行到构造器的内部,那么整个对象可能只是部分形成。
这里可能造成的一个假象是:非静态成员变量的初始化发生在构造方法执行之后。这样说的理由可能是在构造器内部输出的radius的值为0。但是需要注意,radius是属于B的非静态成员变量,B.draw(), radius=0的输出结果发生在B的构造方法执行之前,这条语句是B父类的构造器输出的。after the base constructor:1才是B构造器执行的第一条语句,也是构造方法执行的一个标志,这时radius已经被初始化为1。
从这个例子可以得到的结论是:
一个动态绑定的方法调用会向外深入到继承层次结构内部,它可以调用子类里的方法。如果我们在构造器内部这样做,那么就可能会调用某个方法,而这个方法所操纵的成员可能还未进行初始化。
这个例子所展示的初始化实际过程是:
- 在其他任何食物发生之前,将分配给对象的存储空间初始化成二进制的0
- 调用父类的构造器,父类构造器中的draw方法实际执行的是子类重写过的draw
- 按照声明的顺序调用成员的初始化方法
- 调用子类的构造器
编写构造器的一条准则是:
用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法。
在构造器内唯一能够安全调用的那些方法是父类中的final方法,因为这写方法不能被覆盖。
分享到:
相关推荐
Java中构造器内部的多态方法的行为实例分析是Java编程语言中一个非常重要的知识点,本文将详细介绍Java中构造器内部的多态方法的行为,结合实例形式分析了java构造器内部多态方法相关原理、功能及操作技巧。...
封装是指将对象的状态(属性)和行为(方法)捆绑在一起,并且隐藏对象的内部实现细节,只暴露必要的接口供外部调用的过程。 **特点:** 1. **隐藏内部实现细节:** 对象的内部状态和实现细节被隐藏起来,用户只能...
当子类继承父类时,需要通过显式调用父类的构造器来初始化父类中的数据成员。这通常通过`super()`关键字完成。 **2.5 多层继承** Java支持多层继承,即一个类可以从另一个类继承,而这个父类本身也可以从另一个...
同时,这些类可能会有私有数据成员,以及公有构造函数和访问器方法,体现封装特性。如果文件中还有其他类,可能是为了展示如何通过继承和多态构建复杂的类层次结构。 通过学习和实践这些例子,开发者能够更好地理解...
此外,Java还支持构造器,用于初始化对象的状态,以及getter和setter方法,实现数据的读取和修改。 **继承**是面向对象编程的另一个关键特性,它允许一个类(子类)从另一个类(父类)继承属性和行为。这有助于代码...
在"第一章 类和对象.pdf"中,会详细介绍如何声明和创建类,包括类的构造器、成员变量和方法。 - **对象**:对象是类的实例,它们是程序运行时的实际参与者。对象通过调用类的方法来执行操作。 2. **对象和封装**:...
构造方法不参与多态,因为它们是类的实例化过程的一部分,与具体的类紧密相关。但是,构造方法可以在子类中被重写以满足特定的初始化需求。 **5.6 内部类** 内部类是Java中一种特殊的形式,它在一个类的内部定义。...
子类构造器可以通过`super`关键字调用父类的构造函数,确保初始化过程正确进行。 6. **内部类与匿名类** 内部类是定义在另一个类内部的类,可以是静态的或非静态的。非静态内部类可以访问外部类的所有成员,包括...
封装是面向对象编程的一个核心概念,它指的是将数据(属性)和操作这些数据的方法(行为)捆绑在一起,隐藏内部实现细节,并对外提供简单的接口来访问这些数据。通过封装可以实现数据的安全性,减少耦合度。 - **...
5. **封装**:面向对象编程的一大原则就是封装,它将数据和操作数据的方法捆绑在一起,隐藏内部实现细节,提供公共接口供外部使用。在成绩管理系统中,每个学生对象应该封装其个人信息和成绩,对外只暴露安全的操作...
在设计抽象类时,应避免在其中定义公共或内部受保护的构造函数,而应提供受保护的或内部的构造函数供子类使用。同时,抽象类可以包含非抽象成员,这些成员提供了默认的实现,使得子类在某些情况下不必完全重写所有...
4. **构造器**:特殊的方法,用于初始化新创建的对象。 5. **getter和setter方法**:提供对类中数据的访问和修改的控制,防止直接暴露内部状态。 ### 二、继承 继承允许一个类(子类)继承另一个类(父类)的属性...
Java知识点主要涵盖面向对象编程的基础概念,包括类、对象、接口、变量、构造器、方法重载、继承、重写以及控制修饰符等核心概念。 1. 面向对象特性: - 高内聚、低耦合:类内的元素紧密关联,对外界影响小。 - ...
- **默认构造器**:如果程序员没有定义构造方法,Java会提供一个无参数的默认构造器。但是,一旦程序员定义了一个构造器,Java就不会再提供默认构造器。 - **带参数的构造器**:根据需要,我们可以定义带有不同...
* 局部变量:声明在方法体、方法的形参、内部类、代码块、构造器中 三、方法 * 方法的声明:权限修饰符 返回值类型 方法名(形参列表){方法体} * 方法的重载:同一个类中,允许存在同名方法,参数个数或类型不同 ...
构造器是一种特殊的方法,主要用于初始化对象。每个类至少有一个构造器,如果没有显式地定义构造器,Java编译器会自动提供一个默认构造器。 1. **构造器的命名规则**:构造器的名称必须与类名完全相同。 2. **构造...
本篇文章将深入探讨Java中的类,包括类的定义、构造器、访问修饰符、成员变量、方法、继承、封装、多态等核心概念。 1. **类的定义** 类是创建对象的蓝图,它定义了对象的状态(数据成员或变量)和行为(成员函数...
运行时多态则主要通过方法重写(Overriding)实现,子类可以重写父类中的虚方法,以提供特定的行为。 3. 抽象类(Abstract Class)和接口(Interface):在C#中,抽象类可以包含抽象方法(没有实现的方法),用于...
每个类至少有一个构造方法,即使未显式声明,系统也会自动生成一个默认的无参构造器。 2. **多态**: - **类型**:多态分为编译时多态(函数重载)和运行时多态(方法覆盖或虚函数)。 - **编译时多态**:通过...
本文档涵盖了Java面试中的常见问题,涉及到结构化程序设计、面向对象程序设计、类和对象、继承、多态、封装、抽象、构造器、static域和方法、final关键字、重载、方法签名、方法头、方法体、域的默认初始化值、无...