Java类中,静态初始化器,构造函数,成员变量的加载顺序,一直没有仔细研究过。细节较不准确,所以编程吃了暗亏,纠结了几个小时才发现隐藏的错误。
于是自己做了一个小测验,算是祝自己理解Java类成员变量加载顺序这个问题吧。
测试代码如下:
package com.javaeye.aspnetdb;
/**
*
* @author aspnetdb 周洋
* 父类
*/
public class OrderFather {
public static String strMsg = "父类Msg";
static {
System.out.println("父类静态初始化器");
System.out.println("父类成员变量=" + strMsg);
}
public OrderFather() {
System.out.println("父类的构造函数");
System.out.println("父类构造函数中,父类成员变量=" + strMsg);
}
public void say() {
System.out.println("父类说点什么,子类还是父类=" + strMsg);
}
}
package com.javaeye.aspnetdb;
/**
*
* @author aspnetdb 周洋
* 子类
*/
public class OrderSon extends OrderFather{
public static String strMsg = "子类Msg";
public OrderSon(){
System.out.println("子类构造函数");
System.out.println("构造函数中,子类类成员变量=" + strMsg);
}
static {
System.out.println("子类静态初始化器");
System.out.println("子类成员变量=" + strMsg);
}
public void say() {
System.out.println("子类说点什么,子类还是父类=" + strMsg);
}
}
package com.javaeye.aspnetdb;
/**
*
* @author aspnetdb 周洋
* 测试的主类
*/
public class ClassOrderMain {
public static void main(String[] args) {
OrderSon son = new OrderSon();
son.say();
System.out.println("分咯线*****************************我咯咯咯");
OrderFather father = new OrderFather();
father.say();
System.out.println("分格线*****************************我格格格");
OrderFather father_son = new OrderSon();
father_son.say();
}
}
测试结果:
父类静态初始化器
父类成员变量=父类Msg
子类静态初始化器
子类成员变量=子类Msg
父类的构造函数
父类构造函数中,父类成员变量=父类Msg
子类构造函数
构造函数中,子类类成员变量=子类Msg
子类说点什么,子类还是父类=子类Msg
分咯线*****************************我咯咯咯
父类的构造函数
父类构造函数中,父类成员变量=父类Msg
父类说点什么,子类还是父类=父类Msg
分格线*****************************我格格格
父类的构造函数
父类构造函数中,父类成员变量=父类Msg
子类构造函数
构造函数中,子类类成员变量=子类Msg
子类说点什么,子类还是父类=子类Msg
可以看到,无论是父类还是子类,静态初始化器只执行一次,且父类的初始化器优先于子类的初始化器执行。
如果大家够仔细,debug一下,就可以看到父类还是子类,都是按照如下顺序来执行的。
初始化成员变量->执行初始化器->执行构造函数
第三个例子中,我顺便也测试了一下函数覆盖的问题。
可以看到,申请了子类大小的空间,调用从父类那里继承的方法,最后还是会访问实际申请出来的那个对象的方法。
方法中访问的成员变量也是实际申请出来的对象的变量。
注意:这篇博客只是做一个简单的测试,至于为什么是这个结果,我记得《Thinking in Java》中有写到过。以后如果有空,会不上原因分析的。
分享到:
相关推荐
static表示“全局”或者“静态”的意思,用来修饰成员... 用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象市,不生成static变量的副本,而是类的所有实例共享同一个static变量。
Swing是Java的一个用户界面工具包,允许开发者创建窗口应用程序。实验报告可能包含了Swing组件的布局、事件监听和处理、界面美化等方面的介绍。 4. Java事件处理机制:文档中提到了实现了“ActionListener”和...
**案例背景**:本案例通过编写一个简单的Java程序,使用单例模式初始化静态变量和对象,来演示类的加载过程以及类加载器的委托机制。 **案例源码**: ```java public class Singleton { private static Singleton...
**题目3**:成员变量初始化顺序 此题涉及类、对象、静态变量和实例变量的概念。在Java中,静态变量的初始化发生在类加载时,而实例变量在创建对象时初始化。代码展示了不同类型的变量初始化的顺序,即静态变量先于...
在本实验报告中,我们主要探讨了Java编程语言中的面向对象程序设计,涉及了类的定义、对象的创建与使用,以及访问控制修饰符的概念。以下是相关知识点的详细说明: 1. 类的定义: - Rectangle类:Rectangle类用于...
如“static int x”定义了一个静态变量x,属于类本身而不是类的某个特定对象。静态变量和方法可以在不创建类的实例的情况下被使用。 3. 构造函数(Constructor) 构造函数是一种特殊的方法,它在创建对象时被自动...
在服务阶段,每次请求都会创建一个Servlet实例来处理,因此优化JSP代码以减少内存占用是必要的。 8. **会话管理**:JSP中的session对象允许在用户的不同请求之间共享数据。需要注意的是,过多使用session可能导致...
总之,“实验室成员管理系统”是一个结合了数据结构、文件操作、GUI编程和面向对象设计的项目,对于学习和实践Java技术来说是一个很好的实例。开发者需要掌握Java的基础语法、GUI编程技巧、文件I/O以及数据处理逻辑...
3. **抽象类和抽象方法**:虽然实验中没有明确提到抽象类,但在Java中,如果一个类包含至少一个抽象方法,那么这个类必须声明为抽象类。抽象方法没有具体的实现,需要由其子类来完成。子类继承抽象类后,必须实现...
首先,我们看到ReadConfig类有一个私有成员变量paramA用于存储读取的参数值,以及一个构造方法用于加载配置文件。在这个构造方法中,通过FileInputStream和Properties类来读取和解析ini文件,获取"data"的值。 实验...
2. **类与对象**:类的定义、构造函数、成员变量和方法、对象的创建和使用、封装原则。 3. **继承与多态**:单一继承、抽象类、接口、多态的概念及其应用,例如方法重写和重载。 4. **异常处理**:try-catch-...
`Circle`类包含一个浮点型成员变量`Radius`表示半径,以及对应的构造方法和计算面积、周长的方法。而`Cylinder`类继承自`Circle`,添加了一个表示高度的成员变量`height`,以及构造方法和计算体积的方法。 在完成...
2. LR语法表:LR语法表是存储在文件中的一个二维数组,用于存储语法规则和对应的状态转换信息。 3. 语法树:语法树是LR语法分析器生成的数据结构,用于存储语法分析结果。 Parser类的成员变量 Parser类有多个成员...
实验一:Java运行环境的搭建 这个实验的目的是让学生学会如何下载和安装Java SDK,配置Java程序的运行环境,以及编写和运行Java Application程序。实验内容包括: 1. 安装特定版本的JDK(如JDK 1.6),并更改安装...
6. **内部类**:内部类是定义在一个类内部的类,分为成员内部类和局部内部类。成员内部类可以直接访问外部类的所有成员,包括私有成员。静态内部类则不需要外部类的实例就可以创建,而成员内部类需要外部类的实例。 ...
- **protected**:除了所在类和同一个包内的类,子类也可以访问。 - **default**(无修饰符):同包访问权限,只对同一包内的类可见。 掌握这些基础概念对于理解和编写高质量的Java代码至关重要。通过实验,你可以...
类是对象的蓝图,而对象是程序中的实体,它们具有属性(成员变量)和行为(方法)。 3. **异常处理**:Java提供了强大的异常处理机制,通过try-catch-finally语句块来捕获和处理运行时错误。这有助于提高程序的健壮...
- 对于类,如果一个类被声明为`final`,则它不能被继承,从而防止了对类结构的意外修改。 3. **`super`关键字**: - `super`用于访问父类的成员。在子类中,当子类和父类有同名成员时,可以使用`super`来调用父类...
`School`类有一个静态成员`sh`,这意味着无论创建多少个`School`对象,`sh`始终只有一个实例,即静态内存空间只分配一次。通过`getSchool()`方法获取的是同一个对象的引用,因此`s1`和`s2`指向相同的内存地址,输出...