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中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构
随机推荐
- hibernate得知——Set设置配置
Set设置配置 创建数据表:表关系的员工有多重身份 create table EMPLOYEE ( id INT NOT NULL auto_increment, first_name VARCHAR ...
- WP开发使用BingMaps地图服务
原文:WP开发使用BingMaps地图服务 WP8使用BingMaps地图在 SOAP服务如何计算路径 首先需要用到3个服务 1.GeoCode服务-转换地址到地理的经纬度(WebServices地址 ...
- SVNKIT一段代码的分析
打印SVNkit版本库中的结构: 函数如下: 调用方法如下: listEntries(repository, ""); System.out.println("XXXXX ...
- Android该HTTP下载
今天学习了Android开发中比較难的一个环节,就是断点续传下载,非常多人看到这个标题就感觉头大.的确,假设没有良好的逻辑思维,这块的确非常难搞明确.以下我就将自己学到的知识和一些见解写下供那些在这个 ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(四) Logging Application Block
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(四) Logging Application Block 企业库日志应用程序模块工作原理图: 从上图我们可以 ...
- sed中求公共前缀
string1="test toast" string2="test test" printf "%s\n%s\n" "$stri ...
- hdu2457 Trie图+dp
hdu2457 给定n个模式串, 和一个文本串 问如果修改最少的字符串使得文本串不包含模式串, 输出最少的次数,如果不能修改成功,则输出-1 dp[i][j] 表示长度为i的字符串, 到达状态j(Tr ...
- JS获得URL参数
使用JavaScript获得URL在参数值 方法一: function getUrlParam(name) { var reg = new RegExp("(^|&)&qu ...
- UVa 11463 - Commandos
主题:有一个敢死队,要销毁的建筑群,他们从一个特定建筑物离开,最后到一组特定的建筑物的. 现在,各个建筑物之间进行连接的路由,班车需要在建筑物1时间单位,我问的第一次集合. 分析:图论,最短路径.直接 ...
- OS调度算法常用摘要
一.常见的批处理作业调度 1.先来先服务调度算法(FCFS):就是依照各个作业进入系统的自然次序来调度作业.这样的调度算法的长处是实现简单,公平. 其缺点是没有考虑到系统中各种资源的综合使用情况,往往 ...