有关java构造器的笔记
当程序中首次出现使用一个类A时, 无论是使用A的静态成员还是创建一个对象(声明一个A类对象不算), 那么类加载器就会首先对A进行加载, 在对A进行加载的过程中, 如果A有一个extends的父类B, 那么就先对这个B类进行加载, 如果B类还有父类, 就再加载B的父类,就这样层层向上加载, 直到加载Object基类为止,每个类在加载过程中完成了对该类的静态成员的默认初始化. 当Object类加载完成后, 就从Object类开始依次向下进行静态初始化直到A类, 然后执行A的静态初始化, 此时执行的静态初始化只伴随着类加载执行这一次, 执行之后就再也不执行了. 所谓默认初始化就是将基本数据类型初始化为0, 引用数据类型初始化为null. 静态初始化是按照静态变量和静态代码块的初始化顺序和声明顺序一致这一准则进行指定初始化.
然后如果使用的是new A a()(也就是实例初始化) , 就会为对象分配存储空间, 首先将这片存储空间清零(所谓清零就是对所有的非静态成员变量进行默认初始化), 然后开始执行A的构造函数, 无论是否明确的使用了super()调用A父类的构造函数, 都会在真正执行A的构造函数之前创建A的父类对象, 然后返回A的构造函数, 此时也并非开始执行构造函数内的程序, 而是对A的成员变量进行指定初始化, 初始化的顺序和静态指定初始化的顺序一致, 最后执行A的构造函数内的程序, 完成初始化
当初始化涉及多态时, 如果父类的非静态代码块或者父类的构造函数中调用了涉及到多态的函数, 那么这个函数是A类相应重写的函数.
class Glyph
{
{
draw() ; //会调用子类的
} void draw()
{
System.out.println("Glyph draw()") ;
} public Glyph()
{
System.out.println("Glyph() before draw()") ;
draw(); //会调用子类的
System.out.println("Glyph() after draw()") ;
}
} public class RoundGroph extends Glyph
{
private int radius = 1 ;
RoundGroph(int i)
{
radius = i ;
System.out.println("RoundGroph.Grougph().radius= " + radius) ;
} void draw()
{
System.out.println("RoundGroph.draw().radius= " + radius) ;
} public static void main(String args[])
{
RoundGroph a = new RoundGroph(22) ;
}
}
之所以会出现这种情况是因为 动态绑定 . java之所以有多态, 就是由于动态绑定.
这个是有关动态绑定的一片非常好的文章:http://www.cnblogs.com/yyyyy5101/archive/2011/08/02/2125324.html
上述代码就是对《thinking in java》这段话的一个解释
如果构造器只是在构建对象的一个步骤,并且 该对象所属的类 是从 这个构造函数所属的类 导出的,那么导出部分在当前构造器正在被调用的时刻仍然是没有初始化的。然而一个动态绑定的方法调用却会深入到继承层次结构的内部,调用导出类的方法。如果我们在构造函数中这么做,那么就可能调用某个方法,而这个方法所使用的成员可能还尚未初始化--这肯定会招灾引祸。
上面代码中的RoundGroph是Glyph的子类。按照上面对于有继承关系的初始化过程的描述,当遇到new RoundGroph(22),就会分配存储空间,并对RoundGroph的成员进行默认初始化,然后初始化他所持有的RoundGroph对象,在初始化Glyph的过程中会调用draw(),这个方法是动态绑定的,在RoundGroph还未完全初始化的情况下调用RoundGroph的draw(),如果此时draw()中使用了未初始化的子类成员变量,那么就会导致莫名的错误,也就是《thingking in java》中所说的招灾引祸。
因此,最好不要在构造器中调用函数, 在构造器中唯一能够安全调用的就是private 或 final函数, 如果一定要调用带有动态绑定的函数, 就一定要非常小心了.
//thinking in java笔记,如果有不对的地方,还望指正^_^
有关java构造器的笔记的更多相关文章
- java 构造器学习笔记
构造器(构造器不是方法也不是类的成员) 以前创建对象的方式, public class Constructor{ public static void main(String[] args){ per ...
- java effective 读书笔记
java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...
- 《Thinking In Java》阅读笔记
<Thinking In Java>阅读笔记 前四章:对象导论. 一切都是对象. 操作符. 控制执行流程 public在一个文件中只能有一个,可以是一个类class或者一个接口interf ...
- Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
- JAVA Web学习笔记
JAVA Web学习笔记 1.JSP (java服务器页面) 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . JSP全名为Java Server Pages,中文名叫java服务器 ...
- Java编程思想 笔记
date: 2019-09-06 15:10:00 updated: 2019-09-24 08:30:00 Java编程思想 笔记 1. 四类访问权限修饰词 \ 类内部 本包 子类 其他包 publ ...
- Kotlin for Java Developers 学习笔记
Kotlin for Java Developers 学习笔记 ★ Coursera 课程 Kotlin for Java Developers(由 JetBrains 提供)的学习笔记 " ...
- Java IO学习笔记七:多路复用从单线程到多线程
作者:Grey 原文地址:Java IO学习笔记七:多路复用从单线程到多线程 在前面提到的多路复用的服务端代码中, 我们在处理读数据的同时,也处理了写事件: public void readHandl ...
随机推荐
- 利用canvas写一个验证码小功能
刚刚开始接触canvas,写个验证码小功能练练手,实现效果图如下: 主要代码如下: html <!DOCTYPE html> <html lang="en"> ...
- CF666E Forensic Examination SAM+倍增,线段树和并
题面: 给你一个串S以及一个字符串数组T[1..m],q次询问,每次问S的子串S[p_l..p_r]在T[l..r]中的哪个串里的出现次数最多,并输出出现次数.如有多解输出最靠前的那一个. 分析: 第 ...
- Java中的线程安全和非线程安全以及锁的几个知识点
1. 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据污染. 线程不安全就是不提供 ...
- 夯实Java:从面向对象说起
作者:伯特出处:github.com/ruicbAndroid/LoulanPlan声明:本文出自伯特的<LoulanPlan>,转载务必注明作者及出处. 刚学习 Java 那会就接触了& ...
- JavaScript 高级技巧 Memoization
memoization 来源于拉丁语 memorandum ("to be remembered"),不要与 memorization 混淆了. 首先来看一下维基百科的描述: In ...
- Spring Boot 返回Html界面
@Controller public class HelloController { @RequestMapping("/") public String index(){ ret ...
- HDU 6216 A Cubic number and A Cubic Number(数学/二分查找)
题意: 给定一个素数p(p <= 1e12),问是否存在一对立方差等于p. 分析: 根据平方差公式: 因为p是一个素数, 所以只能拆分成 1*p, 所以 a-b = 1. 然后代入a = b + ...
- metadata的使用以及简单的orm模式
使用sqllite3和metadata简单的封装了个简单的orm #!/usr/bim/python #-*-coding: utf-8 -*- import threading import sql ...
- 【Kubernetes】Kubernetes的Service外部访问方式:NodePort和LoadBalancer
Kubernetes的Pod的寿命是有限的,它们不会复活,因此尽管每个Pod都有自己的IP地址,但是这些IP地址是不可靠的,会随着Pod的消亡而消失. 这就带来一个问题,如果一些Pod的集合(称之为b ...
- POJ 1635 树的最小表示法
题目大意: 用一堆01字符串表示在树上走动的路径,0表示往前走,1表示往回走,问两种路径方式下形成的树是不是相同的树 我们可以利用递归的方法用hash字符串表示每一棵子树,然后将所有子树按照字典序排序 ...