ThinkingInJava 学习 之 0000004 初始化与清理
1. 用构造器确保初始化。
不接受任何参数的构造器叫做默认构造器。
Tree tree = new Tree(12);
如果Tree(int)时Tree类的唯一的构造器,那么编译器将不会允许你以其他任何方式创建Tree对象。
2. 方法重载
方法名相同而形式参数不同
1. 区分重载方法
每个重载的方法都必须有一个独一无二的参数类型列表。
1. 参数个数
2. 参数类型
3. 参数顺序
public void println(int decimal){
System.out.println("int decimal : " + decimal + " String str : " + "Oracle");
}
public void println(String str){
System.out.println("int decimal : " + 12 + " String str : " + str);
}
public void println(int decimal,String str){
System.out.println("int decimal : " + decimal + " String str : " + str);
}
public void println(String str,int decimal){
System.out.println("int decimal : " + decimal + " String str : " + str);
}
2. 涉及基本类型的重载
如果实参数据类型小于形参数据类型,实参数据类型就会被提升。char型实参会提升为int型。
如果实参数据类型大于形参数据类型,通过类型转换执行窄化转换。
3. 以返回值区分重载方法
NO WAY
3. 默认构造器
如果类中无构造器,编译器会自动创建默认构造器。
4. this关键字
1. 在构造器中调用构造器
在构造器中,如果为this添加了参数列表,将产生对符合此参数列表的某个构造器的明确调用。
public Flower() {
// System.out.println("this is this Constructor");//编译错误:必须将构造器调用置于最起始处
this(1,"lo");
// this(2,"ve");//编译错误:不能调用两个
}
public Flower(int flower, String flowerName) {
this.flower = flower;
this.flowerName = flowerName;
}
2. static 的含义
Java 有垃圾回收器负责回收无用对象占据的内存资源。但也有特殊情况:假定对象(并非使用new)获得了一块“特殊”的内存区域,由于垃圾回收器只知道shifang那些经由new分配的内存,所以它不知道该如何释放该对象的这块“特殊”内存。
为了应对这种情况,Java允许在类中定义一个名为finalize()的方法。
工作原理“假定”:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。所以要是打算用finalize(),就能在垃圾回收时刻做一些重要的清理工作。
⊙ C++中的对象一定会使用析构函数销毁
⊙ Java中的对象并非总是被垃圾回收
⊙ 对象可能不被垃圾回收
⊙ 垃圾回收并不等于“析构”
Class : Potato
package lime.thinkingInJava._005001.ins;
public class Potato {
private static int idBuilder = 0;
private int id;
public Potato() {
id = ++idBuilder;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("call Finalize() And id = " + id);
System.exit(0);
}
}
Class : Main
package lime.thinkingInJava._005001.ins;
public class _InsMain {
public static void main(String[] args) {
{
for(int i = 0;i < Integer.MAX_VALUE;i++){
new Potato();
}
}
}
}
Console :
call Finalize() And id = 447009
1. finalize()的用途
finalize()方法不能作为通用的清理方法。
⊙ 垃圾回收只与内存有关
使用垃圾回收器的唯一原因是为了回收程序不再使用的内存。所以对于与垃圾回收有关的任何行为来说(尤其时finalize()方法),它们必须同内存及其回收有关。
但这是否以为着要是对象中含有其他对象,finalize()就应该明确释放那些对象呢?不,无论对象时如何创建的,垃圾回收器都会负责释放对象占据的所有内存。这就将对finalize()的需求限制到一种特殊情况,即通过某种创建对象方式以外的方式为对象分配了存储空间。不过,Java中一切皆为对象,那这种特殊情况时怎么回事呢?
之所以要有finalize(),是由于在分配内存时可能采用了类似C语言中的做法,而非Java中的通常做法。这种情况主要发生在使用“本地方法”的情况下,本地方法是一种在Java中调用非Java代码的方式。
本地方法目前只支持C和C++,但它们可以调用其他语言写的代码,所以实际上可以调用任何代码。
在非Java代码中,也许会调用C的malloc()函数鞋类来分配存储空间,而且除非调用了free()函数,否则存储空间将得不到释放,从而造成内存泄露。当然,free()时C和C++中的函数,所以需要在finalize()中用本地方法调用它。
至此,已经明白了不要过多地使用finalize()的道理了。它确实不是进行普通的清理工作的合适场所。那么,普通的清理工作应该在哪里执行呢?
2. 你必须实施清理
3. 终结条件
4. 垃圾回收器如何工作
6. 成员初始化
对于方法的局部变量,Java 以编译时错误的形式来提示程序员进行变量的初始化。
对于类变量,Java 会默认初始化值。基本类型数据成员默认初始值,对象引用默认初始化为null。
1. 指定初始化
Class : InitialValues
package lime.thinkingInJava._005001.exercise; import java.text.SimpleDateFormat;
import java.util.Date; public class InitialValues {
// 基本数据类型 默认初始化
int genderCode;
// 对象引用 默认初始化
Date date;
// 基本数据类型指定初始化
boolean bool = true;
char ch = 'x';
byte b = 47;
short s = 0xff;
int i = 999;
long lng = 1;
float f = 3.14f;
double d = 3.14159;
// 对象引用指定初始化
Depth depth = new Depth();
// 调用方法(无参)
String birthday = getBirthdayDate();
// 调用方法(有参:须初始化)
String gender = getSelfGender(genderCode); private String getSelfGender(int genderCode) {
switch (genderCode) {
case 0:
return "男";
case 1:
return "女";
default:
return "ladyboy";
}
} public String getBirthdayDate() {
if (null == date) {
return "1992-03-01";
} else {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
}
} @Override
public String toString() {
return "InitialValues{" + "\n" +
"genderCode=" + genderCode +
", date=" + date + "\n" +
", bool=" + bool +
", ch=" + ch +
", b=" + b +
", s=" + s +
", i=" + i +
", lng=" + lng +
", f=" + f +
", d=" + d + "\n" +
", depth=" + depth + "\n" +
", birthday='" + birthday + '\'' + "\n" +
", gender='" + gender + '\'' + "\n" +
'}';
}
}
7. 构造器初始化
在运行时刻,可以方法或执行某些动作来确定初值,但是却无法阻止自动初始化的进行,自动初始化将在构造器被调用之前发生。
package lime.thinkingInJava._005001.exercise;
public class Counter {
// 自动初始化发生在构造函数调用之前
int i;
public Counter() {
System.out.println("i = " + i);
i = 131;
}
@Override
public String toString() {
return "Counter{" +
"i=" + i +
'}';
}
}
1. 初始化顺序
在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
package lime.thinkingInJava._005001.exercise;
class Window{
public Window(int marker) {
System.out.println("Window(" + marker + ")");
}
}
public class House {
// 构造器之前 定义变量
Window w1 = new Window(1); public House() {
System.out.println("House()");
w3 = new Window(33);
}
// 构造器之后 定义变量
Window w2 = new Window(2);
void f(){
System.out.println("f()");
}
// 方法之后 定义变量
Window w3 = new Window(3);
}
2. 静态数据的初始化
Class : StaticInitialization
package lime.thinkingInJava._005001.exercise;
class Bowl{
Bowl(int marker){
System.out.println("Bowl(" + marker + ")");
}
void f1(int marker){
System.out.println("f1(" + marker + ")");
}
}
class Table {
static Bowl bowl1 = new Bowl(1);
Table(){
System.out.println("Table()");
bowl2.f1(1);
}
void f2(int marker){
System.out.println("f2(" + marker + ")");
}
static Bowl bowl2 = new Bowl(2);
}
class Cupboard {
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboard(){
System.out.println("Cupboard()");
bowl4.f1(2);
}
void f3(int marker){
System.out.println("f3(" + marker + ")");
}
static Bowl bowl5 = new Bowl(5);
}
public class StaticInitialization {
public static void main(String[] args){
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
table.f2(1);
cupboard.f3(1);
}
static Table table = new Table();
static Cupboard cupboard = new Cupboard();
}
Console :
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)
静态数据成员 初始化时刻:只有在第一个Table对象创建(或者第一次访问静态数据)的时候,静态数据成员才会被初始化,此后 静态数据成员 不会再次被初始化。
初始化的顺序:先静态对象(静态数据成员),而后时“非静态”对象。
对象的创建过程:(Dog)
1. 即使没有显示地使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。
2. 然后载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
3. 当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
4. 这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值(对数字来说就是0,对布尔类型和字符型也相同),而引用则被设置成了null。
5. 执行所有出现于字段定义出的初始化动作。
6. 执行构造器。
3. 显式的静态初始化(静态代码块)
Java 允许将多个静态初始化动作组织成一个特殊的“静态子句”,即 “静态块”。
当首次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员时(即便从未生成过那个类的对象),静态块 才执行。
Class : ExplicitStatic
package lime.thinkingInJava._005001.exercise;
public class ExplicitStatic {
static {
j = 110;
}
static int j;
static {
i = 10;
}
static int i;
static {
i = 11;
}
public static void main(String[] args){
System.out.println("j = " + j);
System.out.println("i = " + i);
}
}
Console :
j = 110
i = 11
4. 非静态实例初始化(代码块)
非静态代码块和非静态成员变量 与 静态代码块和静态成员变量 类比:
1. 初始化顺序:静态 --> 非静态;成员变量的定义(声明及默认初始化) --> 成员变量的指定初始化
2. 归属: 静态static 属性(静态代码块和静态成员变量)属于类,存储在 方法区;非静态属性(非静态代码块和非静态成员变量)属于对象,存储在 堆空间;
3. 执行时刻: 静态static 属性 在类加载时执行(仅执行一次);非静态属性 在类被实例化时执行(每有一个对象实例化就执行一次)。
Class : Mugs
package lime.thinkingInJava._005001.exercise;
class Mug{
Mug(int marker){
System.out.println("Mug(" + marker + ")");
}
void f(int marker){
System.out.println("f(" + marker + ")");
}
}
public class Mugs {
Mug mug1;
Mug mug2;
{
mug1 = new Mug(1);
mug2 = new Mug(2);
System.out.println("mug1 & mug2 initialized");
}
Mugs(){
System.out.println("Mugs()");
}
Mugs(int i){
System.out.println("Mugs(int)");
}
public static void main(String[] args){
System.out.println("inside main()");
new Mugs();
System.out.println("new Mugs() completed");
new Mugs(1);
System.out.println("new Mugs(1) completed");
}
}
Console :
inside main()
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs(int)
new Mugs(1) completed
8. 数组初始化
1. 可变参数列表
9. 枚举类型
Enum : Spiciness
package lime.thinkingInJava._005009000.exercise;
public enum Spiciness {
NOT,MILD,MEDIUM,HOT,FLAMING
}
Main :SimpleEnumUse
package lime.thinkingInJava._005009000.exercise;
public class SimpleEnumUse {
public static void main(String[] args){
Spiciness howHot = Spiciness.MEDIUM;
System.out.println(howHot);
}
}
编译器自动添加一些特性:
1. toString()方法,以便显示某个enum实例的名字。
2. ordinal()方法,用来标识某个特定enum常量的声明顺序。
3. static values()方法,用来按照enum常量的声明顺序,产生由这些常量值构成的数组。
package lime.thinkingInJava._005009000.exercise;
public class EnumOrder {
public static void main(String[] args){
for(Spiciness s : Spiciness.values()){
System.out.println(s + ", ordinal " + s.ordinal());
}
}
}
enum 可以在switch语句内使用。
啦啦啦
啦啦啦
.
啦啦啦
ThinkingInJava 学习 之 0000004 初始化与清理的更多相关文章
- thinkinginjava学习笔记04_初始化与清理
java沿用了c++的构造器,使用一个和类名完全一样的方法作为类的构造器,可以有多个构造器来通过不同的参数进行构造,称为重载:不仅是构造器可以重载,其他方法也一样通过不同的形参以及不同的返回值来实现重 ...
- Java编程思想——初始化与清理
PS:最近一直忙于项目开发..所以一直没有写博客..趁着空闲期间来一发.. 学习内容: 1.初始化 2.清理 1.初始化 虽然自己的Java基础还是比较良好的..但是在解读编程思想的时候还是发现了 ...
- Java编程思想学习(五)----第5章:初始化与清理
随着计算机革命的发展,“不安全”的编程方式已逐渐成为编程代价高昂的主因之一. C++引入了构造嚣(constructor)的概念,这是一个在创建对象时被自动调用的特殊方法.Java中也采用了构造器,并 ...
- C++学习(9)—— 对象的初始化及清理
1. 构造函数和析构函数 对象的初始化和清理是两个非常重要的安全问题 一个对象或者变量没有初始状态,对其使用后果是未知 同样的使用完一个对象或者变量,没有及时清理,也会造成一些安全问题 C ...
- [THINKING IN JAVA]初始化和清理
4.5初始化和清理 5.1 构造器初始化 无参:如果一个类没有构造器,那么会有一个默认的无参构造器,并且只能通过无参构造器初始化对象: 带参:传入参数初始化成员变量或者其它初始化操作需要的参数,如果类 ...
- 图解 & 深入浅出Java初始化与清理:构造器必知必会
Writer :BYSocket(泥沙砖瓦浆木匠) 微 博:BYSocket 豆 瓣:BYSocket FaceBook:BYSocket Twitter ...
- 大家一起和snailren学java-(四)初始化与清理
初始化和清理,是一个生命周期的起始.在java中,对象的初始化和对象的回收是怎样的呢? 在开发c++的时候,有构造器的概念.即对象的创建,首先默认调用构造器进行初始化.在java中也有“构造器”.ja ...
- Chapter5_初始化与清理_用构造器初始化
接下来进入第五章,java中初始化和清理的问题,这是两个涉及安全的重要命题.初始化的功能主要是为库中的构件(或者说类中的域)初始化一些值,清理的功能主要是清除程序中不再被需要的元素,防止资源过分被垃圾 ...
- 浅谈Java中的初始化和清理
引言 这篇文章我们主要介绍Java初始化和清理的相关内容,这些内容虽然比较基础,但是还是在这边做一个简单的总结,方便以后查阅. 初始化过程 Java尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...
随机推荐
- 关于数据库alter的一系列操作总结
表操作 对于表的操作——创建(create),删除(drop)来说,基本上大家都很清楚,而作为很少被使用到的修改(alter)命令往往存在一些问题,现在做一下总结: 添加列:alter table 表 ...
- Maven入门指南⑥:将项目发布到私服
1 . 修改私服中仓库的部署策略 Release版本的项目应该发布到Releases仓库中,对应的,Snapshot版本应该发布到Snapshots仓库中.Maven根据pom.xml文件中版本号&l ...
- 查询返回JSON数据结果集
查询返回JSON数据结果集 设计目标: 1)一次性可以返回N个数据表的JSON数据 2)跨数据库引擎 { "tables": [ { "cols": [ { & ...
- 移动电源、3G路由拆机
这款电源4400mAh,淘宝也就八十元左右,可以作为无线路由使用,可以插3G网卡,总的来说还算不错,关键是外观精美,网上一堆和华美A100那样的,可惜实在太丑,这款外观虽然漂亮,但是和一百多的相比不支 ...
- vmware中如何检查cpu的使用状况-一个考题引发的思考
来自一个VCP的考题,有点兴趣.可参看: 如何在VMware里使用esxtop? http://thocm.com/a/caozuoxitongzixun/xunihuazonghezixun/VMw ...
- Boost中的智能指针(转)
这篇文章主要介绍 boost中的智能指针的使用.(转自:http://www.cnblogs.com/sld666666/archive/2010/12/16/1908265.html) 内存管理是一 ...
- PHP——自定义比较算法
很多时候,程序都是直接写好逻辑运算,提供给用户的是一个值,然后后台去比较:但是有时会提供一种类似计算器一样的交互方式的时候,PHP只能读懂用户的输入来进行比较了- 最近的一个项目涉及到一个由用户自定义 ...
- Atitit 提升效率 界面gui方面的前后端分离与cbb体系建设 规范与推荐标准
Atitit 提升效率 界面gui方面的前后端分离与cbb体系建设 规范与推荐标准 1. 界面gui方面的前后端分离重大意义1 2. 业务逻辑也适当的迁移js化1 3. 常用分离方法2 3.1. 页面 ...
- pyenv BUILD FAILED解决方法
在本机mac上安装pyenv安装成功后,用pyenv来安装python 3.5.0又出现了如下的问题: -> pyenv install 3.5.0 Downloading Python-3.5 ...
- Qt 密码框不可选中、复制、粘贴、无右键菜单等
在做用户登录.修改密码的时候,往往会用到密码框,其中一些功能要求与普通的输入框不同. 例如:不能选中.复制.粘贴.无右键菜单等功能,当然设置密码不可见是必须的! 一般的密码框:(默认 可以选中,复制, ...