Java的子类和父类实例化顺序
2016-04-25 20:16
381 查看
Java类首次载入时,会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的,静态成员变量
和静态初始快级别相同,非静态成员变量和非静态初始化快级别相同,
初始化顺序:先初始化父类的静态代码--->初始化子类的静态代码--->(创建实例时,如果不创建,则后面的不执行)
初始化父类的非静态代码---->初始化父类构造函数---->初始化子类非静态代码---->初始化子类构造函数
//抽象类
public abstract class Server{
private static final int default_port = 900;
public Server(){
int port = getPort();
System.out.println("port="+port+"default_port="+default_port);
}
protected abstract int getPort();
}
//子类
public class SimpleServer extends Server{
private int mport = 100;
public Simple(int port){
this.mport=port;
}
protected int getPort(){
return mport;
}
}
//测试类
public class Test1 {
public static void main(String[] args) {
Server s = new SimpleServer(600);
}
}
测试结果
port=0 default_port = 900
在测试代码里,传了一个参数600,我们希望getPort得到也是600,但遗憾的是得到的是一个大大的0!!!出现这个问题是因对Java子类和父类实例化顺序存在模糊,下面来看下其正确顺序:
1、new一个SimpleServer,SimpleServer的构造函数接收参数600;
2、初始化父类Server的静态变量,DEFAULT_PORT赋值为900;
3、为了实例化子类,首先实例化其父类Server。子类有参数的构造中默认包含了super方法,即调用父类的无参构造函数。因此就到了int port = getPort();这一句,调用子类的getPort方法。子类的getPort方法返回mPort,此时mPort还没有赋值,因此还是0.这就是得到大大的0的原因!!!
4、父类初始化完毕后,开始初始化子类的实例变量,mPort赋值100;
5、执行子类的构造函数,mPort赋值600;
6、子类实例化完毕,对象创建完了!
真相大白了,再做一个测试。将SimpleServer里的实例变量mPort搞成静态变量如下:
package org.yanzi.test1;
public class SimpleServer extends Server {
private static int mPort = 100;
public SimpleServer(int port) {
// TODO Auto-generated constructor stub
this.mPort = port;
}
@Override
protected int getPort() {
// TODO Auto-generated method stub
return mPort;
}
}
测试结果:
port = 100 DEFAULT_PORT = 900
其执行顺序是:
1.第一个步骤同上,SimpleServer接收构造参数600
2.初始化父类的静态代码块,当然包括静态变量,然后初始化子类的静态变量
3.初始化父类的非静态代码,包括非静态的变量等;
4.执行父类的构造函数;
5.初始化子类的非静态代码
6.执行子类的构造函数。
和静态初始快级别相同,非静态成员变量和非静态初始化快级别相同,
初始化顺序:先初始化父类的静态代码--->初始化子类的静态代码--->(创建实例时,如果不创建,则后面的不执行)
初始化父类的非静态代码---->初始化父类构造函数---->初始化子类非静态代码---->初始化子类构造函数
//抽象类
public abstract class Server{
private static final int default_port = 900;
public Server(){
int port = getPort();
System.out.println("port="+port+"default_port="+default_port);
}
protected abstract int getPort();
}
//子类
public class SimpleServer extends Server{
private int mport = 100;
public Simple(int port){
this.mport=port;
}
protected int getPort(){
return mport;
}
}
//测试类
public class Test1 {
public static void main(String[] args) {
Server s = new SimpleServer(600);
}
}
测试结果
port=0 default_port = 900
在测试代码里,传了一个参数600,我们希望getPort得到也是600,但遗憾的是得到的是一个大大的0!!!出现这个问题是因对Java子类和父类实例化顺序存在模糊,下面来看下其正确顺序:
1、new一个SimpleServer,SimpleServer的构造函数接收参数600;
2、初始化父类Server的静态变量,DEFAULT_PORT赋值为900;
3、为了实例化子类,首先实例化其父类Server。子类有参数的构造中默认包含了super方法,即调用父类的无参构造函数。因此就到了int port = getPort();这一句,调用子类的getPort方法。子类的getPort方法返回mPort,此时mPort还没有赋值,因此还是0.这就是得到大大的0的原因!!!
4、父类初始化完毕后,开始初始化子类的实例变量,mPort赋值100;
5、执行子类的构造函数,mPort赋值600;
6、子类实例化完毕,对象创建完了!
真相大白了,再做一个测试。将SimpleServer里的实例变量mPort搞成静态变量如下:
package org.yanzi.test1;
public class SimpleServer extends Server {
private static int mPort = 100;
public SimpleServer(int port) {
// TODO Auto-generated constructor stub
this.mPort = port;
}
@Override
protected int getPort() {
// TODO Auto-generated method stub
return mPort;
}
}
测试结果:
port = 100 DEFAULT_PORT = 900
其执行顺序是:
1.第一个步骤同上,SimpleServer接收构造参数600
2.初始化父类的静态代码块,当然包括静态变量,然后初始化子类的静态变量
3.初始化父类的非静态代码,包括非静态的变量等;
4.执行父类的构造函数;
5.初始化子类的非静态代码
6.执行子类的构造函数。
相关文章推荐
- java---Serializable(序列化)
- 关于Java的构造器和直接为成员变量赋值的区别
- 我的学习之路-JAVA-03
- DaoFactory.java
- Java修饰符的访问权限
- java double转string
- 我的Java后端书架 (2016年暮春3.0版)
- Java关键字之final
- Mixing JUnit, Hamcrest and Mockito: Explaining java.lang.NoSuchMethodError: org/hamcrest/Matcher.des
- 使用MyEclipse连接数据库
- springMVC与MyBatis整合
- Spring结合Quartz实现多任务定时调用
- Java基础(持续更新)
- IDEA中引入struts2时报错 ClassNotFoundException
- Java序列化(Serializable)与反序列化
- Spring4 hibernate4与strtus2的整合
- java web 连接数据库异常 Before start of result set
- MyEclipse连接MySQL
- JAVA内存模型
- spring-boot 初学一