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中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构
随机推荐
- String ,StringBuffer,StringBuilder精髓比較
1. 在运行速度方面的比較:StringBuilder > StringBuffer > String 2. StringBuffer与StringBuilder.他们是字符串变量,是可改 ...
- 关于oracle的备份 导入
****假设要保存为bat文件.最好用汉字 导入: imp clsoftoa/clsoftoa@orcl124 --要导入的数据库的 username/password@数据库名 fromuser= ...
- 屌丝程序猿赚钱之道之taobao 2
续上篇,之前写的案例,都是比較0基础的. 案例4: 代写情书.软文.论文等等. 这是我一个同学的真实故事. 我隔壁寝室的小王平时没事就爱谢谢博客.逛逛论坛.大二的时候接触了威客网,開始在网上 ...
- asp.net Form 认证【转】
第一部分 如何运用 Form 表单认证 一. 新建一个测试项目 为了更好说明,有必要新建一个测试项目(暂且为“FormTest”吧),包含三张页面足矣(Default.aspx.Logi ...
- Java-UrlRewrite中文api文档
安装 1. 下载jar包, 并加入到WEB-INF/lib下 2. 在WEB-INF/web.xml中增加下面的配置 <filter> <filter-name>UrlRewr ...
- svn代码统计工具的金额
StatSVN介绍 StatSVN是Java写开源统计程序,从statCVS从移植.从能Subversion版本号来获取信息库,该项目开发的叙述性说明,然后生成各种表格和图表.例:时间线.针对每一个开 ...
- 自定义ComboBox,简简单单实现
private void Button_Click(object sender, RoutedEventArgs e) { Popup1.PlacementTarget = TesTextBox; P ...
- Android学习之 AChartEngine 图表绘制
Android 开源图表绘制工具AChartEngine地址:http://code.google.com/p/achartengine/ AChartEngine Android实现图表绘制和展示( ...
- macbook连接linuxserver后不显示matlab桌面[问题]
macbook 登录远程linuxserver.Macbook今天,系统版本号10.9.4.这是更新,打开matlab当提醒x11不存在.一个接着安装Xquarz2.7.6. matlab它可以在本地 ...
- Cocos2d-x 地图步行实现1:图论Dijkstra算法
下一节<Cocos2d-x 地图行走的实现2:SPFA算法>: http://blog.csdn.net/stevenkylelee/article/details/38440663 本文 ...