`
tianlihu
  • 浏览: 311231 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

java 类的初始化顺序和多态

阅读更多
  类的初始化顺序是老生长谈的问题。但是它仍然是面试中常见的,也可以说是不可缺少的题目。因为在项目开发过程中,经常会因为这个出现BUG,且这样的BUG一般很难查。

  从C语言转用java语言的人常常会这样写代码:
public class Sample {

	private String str = null; // str = "";

	private boolean flag = false;

	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}

	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}
	
	// Other code
	// ........
}

  他们总是喜欢在声明的时候初始化,我在学java之初,也有人告诉我这样写,说这是好习惯。后面的工作中,发现这是很大的错误,我们的项目中,因为这种写法,出现了很多BUG。看一下下面这个简单的例子:
class A {

	public A() {
		initAttrs();
	}

	public void initAttrs() {
		System.out.println("initAttrs in A");
	}
}

class B extends A {

	public String s = null;

	public B() {
		super();
	}

	public void initAttrs() {
		s = "aaa";
	}
}

public class InheritProblem {

	public static void main(String[] args) {
		B b = new B();
		System.out.println(b.s);
	}
}

  在这段代码,其实是一个小的框架思想,initAttrs方法是用来初始化成员属性用的,为什么不用B类的构造方法去做呢?因为如果有很多初始化的事情要做,全部都放在构造器中做,就会显得很复杂,不利于维护。团队开发时,也不太方便。且如果放在构造器中来写,子类继承时,将不能重写其代码。写成这样,子类仅需要关注自己要初始化的东西就好了。
  这段代码运行的结果出乎一般人的意料。大多数人会回答结果是:
  aaa
 
  但是结果却是:
  null

  为什么会这样呢?这就需要细说一下类的初始化顺序和方法的重写了。
  先从简单的讲起。方法的多态有两种,一种是重载,一种是重写。重载没有什么好说的,两个方法有一样的名字,参数和返回值有些差异(其实这里面有点小小的问题,我会在别的文章再说)。重写就不一样了,重写是方法的参数必须是一样的,但返回值可以不一样,子类方法的返回值要和父类方法返回值一样或是其子类,重写必须存在于父类和子类之间,子类重写父类的方法。这时,用子类对象去访问该方法,永远调用到的是子类的方法,即使是强行转化为父类的引用,就像父类的方法不存在一样。看下面的例子:
class A {
	public String str;
	
	public A() {
		str = "a";
	}

	public String getAStr() {
		return str;
	}

	public String print() {
		return "A Print";
	}
}

class B extends A {
	public String str;

	public B() {
		str = "b";
	}
	
	public String getBStr() {
		return str;
	}

	public String print() {
		return "B Print";
	}
}

public class InheritProblem {

	public static void main(String[] args) {
		A a = new B();
		System.out.println("a.str=" + a.str);
		System.out.println("a.getAStr()=" + a.getAStr());
		System.out.println("a.print()=" + a.print());
		System.out.println("--------------------------------");
		B b = new B();
		System.out.println("b.str=" + b.str);
		System.out.println("b.getAStr()=" + b.getAStr());
		System.out.println("b.getBStr()=" + b.getBStr());
		System.out.println("b.print()=" + b.print());
		System.out.println("--------------------------------");
		A c = b;
		System.out.println("c.str=" + c.str);
		System.out.println("c.getAStr()=" + c.getAStr());
		System.out.println("c.print()=" + c.print());
		System.out.println("--------------------------------");
	}
}

未完,待续
0
0
分享到:
评论

相关推荐

    成员的初始化顺序和多态性

    这是我获得的java的代码,这个主要关于成员的初始化顺序和多态性,这个代码主要用于学习和交流,希望大家喜欢。

    Java 基础核心总结 +经典算法大全.rar

    类的初始化 成员初始化 构造器初始化初始化顺序 数组初始化 对象的销毁 对象作用域 this 和 super 访问控制权限继承 多态组合代理 向上转型static final 接口和抽象类接口 抽象类异常 认 识 Exception 什么是 ...

    java基础核心总结归纳---参考手册--心得手册-学习资料-总结经验

    初始化顺序 16 this 和 super 16 访问控制权限 16 继承 17 多态 17 代理 17 Static 17 Final 17 接⼝和抽象类 18 接⼝ 18 抽象类 18 异常 18 认识 Exception 18 什么是 Throwable 18 常⻅的 Exception 19 与 ...

    Java开发技术大全(500个源代码).

    errorInit.java 演示变量初始化错误的程序 integerExample.java 演示各种整型变量的使用 isPrime.java 判断素数 leapYearByIf.java 用if语句判断闰年 leapYearByLogical.java 用逻辑表达式判断闰年 lowToUpper...

    Thinking in java4(中文高清版)-java的'圣经'

    5.6.1 指定初始化 5.7 构造器初始化 5.7.1 初始化顺序 5.7.2. 静态数据的初始化 5.7.3. 显式的静态初始化 5.7.4. 非静态实例初始化 5.8 数组初始化 5.8.1 可变参数列表 5.9 枚举类型 5.10 总结 第6章 访问权限控制 ...

    关于Java的几个经典问题

    1.类的初始化顺序 2.到底创建了几个String对象(三)——变量(属性)的覆盖 (四)——final、finally和finalize的区别 (五)——传了值还是传了引用(六)——字符串(String)杂谈 (七)——日期和时间的处理 ...

    JAVA面试题解惑系列合集

    1.1 JAVA面试题解惑系列(一)——类的初始化顺序 1.2 JAVA面试题解惑系列(二)——到底创建了几个String对象? 1.3 JAVA面试题解惑系列(三)——变量(属性)的覆盖 1.4 JAVA面试题解惑系列(四)——final、...

    Java入门教程(微学苑)-part1

    4.6 多态和动态绑定 66 4.7 动态绑定 69 4.8 instanceof 运算符 70 4.9 多态对象的类型转换 71 4.10 Java static关键字以及Java静态变量和静态方法 72 4.11 static 的内存分配 73 4.12 静态方法 74 4.13 静态初始器...

    疯狂JAVA讲义

    5.3.2 成员变量的初始化和内存中的运行机制 128 5.3.3 局部变量的初始化和内存中的运行机制 130 5.3.4 变量的使用规则 130 5.4 隐藏和封装 132 5.4.1 理解封装 132 5.4.2 使用访问控制符 132 5.4.3 package和...

    Java面试题解惑系列

    来自网络,主要包括以下内容:1、类初始化的顺序;2、到底创建了几个String对象;3、变量(属性)的覆盖;4、final,finally,finalize;5.传了值还是传了引用;6.String杂谈;7.日期与时间的处理;8.基本类型总结;9....

    JAVA复习资料

    12、在Java中有一种叫作__构造方法__的特殊方法,我们在程序中用它来对类的对象成员进行初始化。 13、面向对象技术具有_封装性___、_继承性___、_抽象性___、多态性等特性。 14、Java中所有类都是类 _Object___...

    JAVA基础课程讲义

    对象和类的概念 56 类和对象初步 57 测试类的定义方式 57 简单的学生类编写示例 58 内存分析 59 属性(field,或者叫成员变量) 59 引用类型 60 类的方法 60 对象的创建和使用 60 构造器(或者叫做构造方法,...

    java面试资料(转载)

    包括:多线程,类的初始化顺序,继承,多态,日期和时间的处理等内容

    JAVA面试题解惑系列114页.pdf

    (一)类的初始化顺序 (二)到底创建了几个String 对象? (三)变量(属性)的覆盖 (四)final、finally 和finalize 的区别 (五)传了值还是传了引用? (六)字符串(String)杂谈 (七)日期和时间的处理 (八...

    J2SE(javaSE基础知识).doc

    java简介、java不同版本、java特点、jdk、第一个程序、jdk、jre、jvm、eclipse配置、注释、标识符、变量、数据类型、运算符、分支语句、命名规范、循环语句、数组、main方法、面向对象、成员变量和局部变量、构造...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    第6章 Java的类(Class)和对象(Object) 132 教学视频:59分钟 6.1 驾驶汽车向类(Class)的世界进发 132 6.1.1 汽车带来的问题 132 6.1.1 类的组成 134 6.1.3 使用自定义的Car类 136 6.1.4 类和对象 139 ...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    第6章 Java的类(Class)和对象(Object) 132 教学视频:59分钟 6.1 驾驶汽车向类(Class)的世界进发 132 6.1.1 汽车带来的问题 132 6.1.1 类的组成 134 6.1.3 使用自定义的Car类 136 6.1.4 类和对象 139 ...

    corejava培训文档

    5.3. 初始化数组 5.4. 多维数组 5.5. 数组拷贝 6. 五 对象和类 6.1. 面向对象与面向过程 6.2. 对象的概念 6.3. 成员变量和局部变量 6.4. 成员方法 6.5. This关键字 6.6. 访问控制符 6.7. 构造方法 6.8....

    AIC的Java课程1-6章

     弄清构造函数和终结方法在继承层次结构中的调用顺序,强调子类必须调用超类的构造函数分配空间和初始化超类数据。  掌握方法重写(override)的基本要求。  理解和使用关键字final。  理解包的...

    java初学者必看

    16.3.2 JDBC常见接口和类 16.3.3 JDBC数据库连接步骤 16.3.4 加载JDBC驱动程序 16.3.5 获取Connection连接对象 16.4 Java与各种数据库连接 16.5 本章习题 第17章 Java Web应用——JSP 17.1 JSP技术概述 17.2...

Global site tag (gtag.js) - Google Analytics