Java的初始化与清理
大家都知道,Java是站在巨人的肩上成功的,它是在C&C++的基础上进一步的开发,投入面向对象开发的怀抱。Java吸取了很多以前的教训,加入自己很多独创的方式。在程序语言发展初期,许多C程序员经常忘记初始化变量,在程序结束后也经常忘记对创建的数据类型进行释放内存,造成内存泄漏。这些"不安全"的编程方式当然需要程序员有良好的编程习惯,但如果编程语言能够加入自动清理与初始化的工作,这回大大降低开发成本。随着技术的发展,C++语言引入了构造器(constructor),即在创建对象自动调用的初识方法,Java语言采用这一方法,并加入垃圾回收器,负责自动回收用户创建的内存,进一步降低程序员的开发成本。
Java的初始化与构造器
创建Java的对象最普遍发的方法是使用new方法,如下所示。而创建对象必须使用构造器,构造器实际就是Java对象初始化的方法,用户可以在该方法中添加自定义初始化行为。
Object obj = new Object(); // 左侧为声明对象,右侧为实际创建一个对象
构造器它是一个隐含为静态的无返回值的方法,名称与类名相同,编译期会自动调用该方法。如果用户没有创建构造器,编译期会为你自动生成一个默认构造器。总之,构造器个数至少有一个。构造器可以有多个,它可以用户自己选择如何初始化对象,这里是使用重载(Overload)的方法。如下所示:
package com.thinkinjava.initialization;
import static com.thinkinjava.util.Print.*; class Tree {
int height;
Tree() {
print("Planting a seedling");
height = 0;
}
Tree(int initialHeight) {
height = initialHeight;
print("Creating new Tree that is " +
height + " feet tall");
}
void info() {
print("Tree is " + height + " feet tall");
}
void info(String s) {
print(s + ": Tree is " + height + " feet tall");
}
} public class Overloading {
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
Tree t = new Tree(i);
t.info();
t.info("overloaded method");
}
// Overloaded constructor:
new Tree();
}
}
Java的初始化顺序
既然讲到Java初始化,那肯定要关注Java的初始化顺序,这涉及到一些继承的知识,首先看一个实例:
package com.thinkinjava.multiplex; import static com.thinkinjava.util.Print.print; /**
* 初始化顺序
*
*/ // 形状
class Insect {
private int i = 9;
protected int j;
private int k = priInit("Insect.k initialized"); Insect() {
print("i = " + i + ",j = " + j);
j = 39;
} private static int x1 = priInit("static Insect.x1 initialized"); static int priInit(String s) {
print(s);
return 47;
}
} class InitOrder extends Insect {
private int i = 10;
private int k = priInit("InitOrder.k initialized"); public InitOrder() {
print(" k = " + k);
print(" j = " + j);
} private static int x2 = priInit("static InitOrder.x2 initialized"); public static void main(String[] args) {
print("InitOrder constructor");
InitOrder x = new InitOrder();
}
}
/*Output:
static Insect.x1 initialized
static InitOrder.x2 initialized
InitOrder constructor
Insect.k initialized
i = 9,j = 0
InitOrder.k initialized
k = 47
j = 39
*/
如上所示,当运行该Java程序时,首先访问程序入口,即InitOrder.main()方法,于是类加载器加载InitOrder.class类文件,而对它的加载过程中,通过extends关键字可知该类有个父类,于是加载该父类,如果该父类还有它自身的父类,继续加载,然后执行最高一层类的static初始化,然后是其子类,依次执行,最后所有的类的已加载完成,开始执行main方法:在main方法中开始创建对象,对象被创建之后,虚拟机会为其分配内存,主要用来存放对象的实例变量及其从父类继承过来的实例变量(即使这些从父类继承过来的实例变量有可能被隐藏也会被分配空间)。在为这些实例变量分配内存的同时,这些实例变量也会被赋予默认值。在内存中创建对象后,开始调用父类的构造器,父类的构造器能够使用super调用或被编译期自动调用,父类在执行构造器语句之前,会对父类实例变量按照次序进行初始化。父类完成父类子对象的初始化后,子类开始的顺序执行,先实例变量初始化,然后执行构造器语句。最后整个对象构造完成。
Java的对象与清理
Java的显著优点就是Java有良好的垃圾清理机制,C++中创建对象,使用对象后,需要使用delete操作符删除对象,就会调用对应的析构函数。而Java中没有析构函数,Java的finalize()并不是类似C++的析构函数,Java的finalize()只是用来回收本地方法(c/c++)占用的内存(调用本地方法类似free)。通常意义上来讲,Java程序员只需创建对象,而不需我们自己去销毁对象,因为垃圾回收机制会帮我们回收对象,虽然不知道什么时候回收,是否会被回收。
然后可能会出现这种情况,类可能要在生命周期内执行一些必需的清理活动,这就需要程序员自己书写清理方法,在清理方法中必须注意清理顺序,即其顺序与初始化顺序相反,为防止出现异常,可以将清理动作放入finally中。如实例所示:
import static com.thinkinjava.util.Print.print; /**
* 确保正确清理
* */ // 形状
class Shape {
Shape(int i) {
print("Shape constructor");
} // 处理
void dispose() {
print("Shape dispose");
}
} class Circle extends Shape {
Circle(int i) {
super(i);
print("Circle constructor");
} void dispose() {
print("Circle dispose");
super.dispose();
}
} // 三角形
class Triangle extends Shape {
Triangle(int i) {
super(i);
print("Triangle constructor");
} void dispose() {
print("Triangle dispose");
super.dispose();
}
} class Line extends Shape {
private int start, end; Line(int start, int end) {
super(start);
this.start = start;
this.end = end;
print("Drawing Line: " + start + ", " + end);
} void dispose() {
// 擦除线条
print("Erasing Line: " + start + ", " + end);
super.dispose();
}
} public class CADSystem extends Shape {
private Circle c;
private Triangle t;
private Line[] lines = new Line[3]; public CADSystem(int i) {
super(i + 1);
for (int j = 0; j < lines.length; j++) {
lines[j] = new Line(j, j * j);
}
c = new Circle(1);
t = new Triangle(1);
print("Combined constructor");
} public void dispose() {
print("CADSystem.dispose()");
// 清理的顺序与初始化顺序相反
t.dispose();
c.dispose();
for (int i = lines.length - 1; i >= 0; i--) {
lines[i].dispose();
}
super.dispose();
} public static void main(String[] args) {
CADSystem x = new CADSystem(47);
try {
// 程序编码与异常处理
} finally {
x.dispose();
}
} }
/**
Output:
Shape constructor
Shape constructor
Drawing Line: 0, 0
Shape constructor
Drawing Line: 1, 1
Shape constructor
Drawing Line: 2, 4
Shape constructor
Circle constructor
Shape constructor
Triangle constructor
Combined constructor
CADSystem.dispose()
Triangle dispose
Shape dispose
Circle dispose
Shape dispose
Erasing Line: 2, 4
Shape dispose
Erasing Line: 1, 1
Shape dispose
Erasing Line: 0, 0
Shape dispose
Shape dispose*/
Java的初始化与清理的更多相关文章
- Chapter5_初始化与清理_用构造器初始化
接下来进入第五章,java中初始化和清理的问题,这是两个涉及安全的重要命题.初始化的功能主要是为库中的构件(或者说类中的域)初始化一些值,清理的功能主要是清除程序中不再被需要的元素,防止资源过分被垃圾 ...
- Java编程思想——初始化与清理
PS:最近一直忙于项目开发..所以一直没有写博客..趁着空闲期间来一发.. 学习内容: 1.初始化 2.清理 1.初始化 虽然自己的Java基础还是比较良好的..但是在解读编程思想的时候还是发现了 ...
- 图解 & 深入浅出Java初始化与清理:构造器必知必会
Writer :BYSocket(泥沙砖瓦浆木匠) 微 博:BYSocket 豆 瓣:BYSocket FaceBook:BYSocket Twitter ...
- 浅谈Java中的初始化和清理
引言 这篇文章我们主要介绍Java初始化和清理的相关内容,这些内容虽然比较基础,但是还是在这边做一个简单的总结,方便以后查阅. 初始化过程 Java尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...
- Java编程思想学习(五)----第5章:初始化与清理
随着计算机革命的发展,“不安全”的编程方式已逐渐成为编程代价高昂的主因之一. C++引入了构造嚣(constructor)的概念,这是一个在创建对象时被自动调用的特殊方法.Java中也采用了构造器,并 ...
- Java 初始化和清理
初始化和清理是影响代码安全的两个重要因素. 一.初始化 1. 方法重载 构造器与类名相同,成为强制重载方法名的原因之一.重载规则:每个重载的方法必须拥有独一无二的参数类型列表.不能根据返回值来区分重载 ...
- 《Java编程思想》——初始化与清理(一)读书笔记
第一次写这个,这一章都用word写的,结果复制过来没图片....只能上传word文档了.以后改用markdown比较好 word文档地址:<Java编程思想>--初始化与清理(一)读书笔记
- java初始化与清理
初始化与清理 欢迎转载,转载烦请注明出处,谢谢. https://www.cnblogs.com/sx-wuyj/p/11177257.html 1.用构造器确保初始化 java中通过提供构造器,可以 ...
- Java编程思想之五初始化与清理
随着计算机革命的发展,"不安全"的编程方式已经逐渐称为编程代价高昂的主因之一. 初始化和清理正是涉及安全的两个问题. 5.1 用构造器确保初始化 通过提供构造器,类的设计者可确保每 ...
随机推荐
- 【Laravel】Mac下玩转Laravel
1 apache 首先Mac系统是自带了Apache,只需要执行 sudo apachectl start 就可以打开Apache服务,然后访问 http://localhost 就可以访问到,it' ...
- 腾讯云CMQ消息队列在Linux环境下的使用
版权声明:本文由李少华原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/76 来源:腾云阁 https://www.qclou ...
- linux常用的一些访问目录
救命三键(Ctrl+Alt+Delete) /var/log 如果是网络服务的问题时,请到 这个目录里头去查阅一下 log file (登录档): /etc/rc.local 修改挂载 ...
- Jenkins反序列化漏洞cve-2017-1000353
一.漏洞原理: 本地没有环境:参考:https://blogs.securiteam.com/index.php/archives/3171 进行学习理解记录. 首先这是一个java反序列化漏洞 ...
- jquery.js与sea.js综合使用
jquery.js与sea.js综合使用 目录 模块定义 define id dependencies factory exports require require.async require. ...
- 【BZOJ4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+动态规划
[BZOJ4922][Lydsy六月月赛]Karp-de-Chant Number Description 卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令人捉摸不透,有时候会让水平很 ...
- 项目中启动另外的一个app
NSMutableString *webViewContent = [[NSMutableStringalloc] init]; [webViewContent appendString:@" ...
- Andorid- 反序列化,采用pull解析 xml 文件
MainActivity.java 主入口,通过获得 XML文件 ,然后将解析后的文件标签以及文本内容拼接到 StringBuffer中,最后显示在TextView上 package com.exam ...
- python 对文件的操作
观看的技术文来源:http://www.cnblogs.com/alex3714/articles/5717620.htmlimport sys# data = open("yesterda ...
- 限制ip ssh远程登录
有时候为了服务器的安全考虑,我们可以在服务器上做限制,禁止其他ip地址连接服务器. 方法一:修改ssh配置文件 其实做这个操作很简单,只需要改/etc/ssh/sshd_config配置文件,再最后一 ...