有关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 ...
随机推荐
- sin_addr.s_addr和sin_addr.S_un.S_addr
sin_addr.s_addr和sin_addr.S_un.S_addr 先mark一下,等下写
- windows中彻底卸载mysql
1)停止MySQL服务 打开控制面板→管理工具→服务(找到MySQL) 2)卸掉mysql server 打开控制面板→程序与功能→找到mysql server然后卸载 3)将mysql目录下的安装文 ...
- spring tool suite (sts) 创建springmvc(没有实践)
摘自:STS(Spring Tool Suite)建立默认的spring mvc项目 老外的原创,网址:http://www.codejava.NET/frameworks/spring/spring ...
- wap学习记录
针对移动端浏览器: 大部分的浏览器内核都是webkit内核,对h5和c3的支持非常好 库 国内比较流行的框架 : 妹子UI bootstrap中解决ie8以及以下的h5标签和媒体查询兼容问题的两个库分 ...
- 谈一谈flex布局使用中碰到的一些问题
起因 工作以后由于大量使用到了flex布局而碰到了一些尚不清楚的问题,以及一些有意思的特性,在此写篇博客记录一下. flex三个值的含义 众所周知,flex布局所有的属性有两种:一种作用在弹性容器(F ...
- CTO俱乐部官方群聊-探讨创业和跳槽
今天,CTO俱乐部官方群,有交流,若干活跃分子探讨了创业和跳槽等相关话题. 感觉质量很不错,就整理了下. 老徐 17:02:00 跳来跳去也不是长久之计,除了涨点工资 张苗苗 17:02:46 ...
- java环境配置——jdk8
在官网下载最新版本的jdk 测试版本:jdk-8u60-windows-x64.exe 测试环境:Windows Server 2012 R2 Standard X64 开始执行安装 安装过程中会选 ...
- 【带权并查集】HDU 3047 Zjnu Stadium
http://acm.hdu.edu.cn/showproblem.php?pid=3047 [题意] http://blog.csdn.net/hj1107402232/article/detail ...
- /etc/fstab readyonly 解决办法
阿里云主机切换地区强制升级后,“新的磁盘盘符识别为vdb1,但是在/etc/fstab中记录的挂载信息还是旧的xvdb1,导致磁盘挂载失败” 机子启动出错了. 按提示 输入 root的密码,进入以Re ...
- JS把数字金额转换成中文大写数字的函数
//把数字金额转换成中文大写数字的函数 function num2rmb ($num){ $c1="零壹贰叁肆伍陆柒捌玖"; $c2="分角元拾佰仟万拾佰仟亿" ...