Java拾遗(一):浅析Java子类和父类的实例化顺序 及 陷阱
本文主要介绍Java里经常使用的子类和父类的变量实例化顺序及陷阱,并结合一个Android实例来探讨此问题。日后编程中应尽量避免此陷阱。
首先看以下一段代码:
定义一个虚类Server.java
package org.yanzi.test1; public abstract class Server {
private static final int DEFAULT_PORT = 900;
public Server() {
// TODO Auto-generated constructor stub
int port = getPort();
System.out.println("port = " + port + " DEFAULT_PORT = " + DEFAULT_PORT);
}
protected abstract int getPort(); }
然后定义一个子类SimpleServer.java
package org.yanzi.test1; public class SimpleServer extends Server {
private 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;
} }
測试代码:
package org.yanzi.test1; public class Test1 { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
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.运行子类的构造函数。
至此完成,终于的结论就是构造函数越简单越好,不要在构造函数里做太多操作。回过头再来看杂家的前文:Android自己定义UI陷阱:LayoutInflater.from().inflate()一定不能工作在父类或虚类里 假设把initView()放在父类里,则子类LAYOUT_ID在使用时还会是0.因此即便要用也要将此弄成static类型的。
Java拾遗(一):浅析Java子类和父类的实例化顺序 及 陷阱的更多相关文章
- java中子类继承父类程序执行顺序
java中子类继承父类程序执行顺序 FatherTest.java public class FatherTest { private String name; public FatherTest() ...
- java中子类继承父类程序执行顺序问题
Java中,new一个类的对象,类里面的静态代码块.非静态代码.无参构造方法.有参构造方法.类的一般方法等部分,它们的执行顺序相对来说比较简单,用程序也很容易验证.比如新建一个测试父类. public ...
- Java入门-浅析Java学习从入门到精通【转】
一. JDK (Java Development Kit) JDK是整个Java的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具和Java基础的类库 ...
- Java 中变量初始化、子类和父类构造器调用的顺序
先说结论 变量初始化 -> 父类构造器 -> 子类构造器 贴代码 Animcal.java 父类 public class Animal { private static int inde ...
- Java子类继承父类的执行顺序
父类的静态代码块(static) 子类的静态代码块(static) 父类的非静态代码块(父类成员初始化) 父类的构造方法 子类的非静态代码块(子类成员初始化) 子类的构造方法
- [ Java学习基础 ] 浅析Java方法调用
先看一个示例,读者可先自行阅读判断输出结果: public class TestClass { private static void testMethod(){ System.out.printl ...
- JAVA面试题 浅析Java中的static关键字
面试官Q1:请说说static关键字,你在项目中是怎么使用的? static 关键字可以用来修饰:属性.方法.内部类.代码块: static 修饰的资源属于类级别,是全体对象实例共享的资源: 使用 s ...
- java 子类重写父类的方法应注意的问题
若想实现一个合格重写方法,而不是重载,那么必须同时满足下面的要求! A.重写规则之一: 重写方法不能比被重写方法限制有更严格的访问级别.(但是可以更广泛,比如父类方法是包访问权限,子类的重写方法 ...
- java 子类、父类中静态代码块、字段,非静态代码块、字段以及构造函数的初始化顺序和次数
一个类中的数据初始化顺序是面试官非常喜欢出的面试题之一,本文用一个实例来介绍java中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构
随机推荐
- Qt调用word 例子
Qt调用word 例子 Getting Microsoft Word Object to SaveAs #include <QtGui> #include <QAxObject> ...
- hdu 4472 Count (2012 ACM-ICPC 成都现场赛)
递推,考虑到一n可以由i * j + 1组合出来,即第二层有j个含有i个元素的子树...然后就可以了.. #include<algorithm> #include<iostream& ...
- Spring框架简单介绍
原文地址: http://my.oschina.net/myriads/blog/37922 1.使用框架的意义与Spring的主要内容 随着软件结构的日益庞大,软件模块化趋势出现,软件开发也须要多 ...
- HDU2586 How far away ?(LCA模板题)
题目链接:传送门 题意: 给定一棵树,求两个点之间的距离. 分析: LCA 的模板题目 ans = dis[u]+dis[v] - 2*dis[lca(u,v)]; 在线算法:详细解说 传送门 代码例 ...
- 通信协议:HTTP、TCP、UDP(转)
原文出处: 碧雪轩的博客 TCP HTTP UDP: 都是通信协议,也就是通信时所遵守的规则,只有双方按照这个规则“说话”,对方才能理解或为之服务. TCP HTTP UDP三者的关系 ...
- oracle数据库恢复与备份
一.oracle数据库恢复 1.恢复刚才删除的一条数据 delete from emp e where e.empname='SMITH' select * from flashback_transa ...
- java 线程 新类库中的构件 countDownLatch 使用
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlhbmdydWkxOTg4/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- Objective-C之成魔之路【9-类构造方法和成员变量作用域、以及变量】
郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 构造方法 ...
- 初窥Linux 之 文件权限
一.用户与用户组 为了更好地理解文件权限,我们需要先有用户和用户组的概念.因为在Linux里面,任何一个文件都具有“User(用户).Group(用户组)及Others(其他用户)”3种身份的个别权限 ...
- Sql Server函数全解<四>日期和时间函数
原文:Sql Server函数全解<四>日期和时间函数 日期和时间函数主要用来处理日期和时间值,本篇主要介绍各种日期和时间函数的功能和用法,一般的日期函数除了使用date类型的参数外, ...