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尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...
随机推荐
- Instruments
链接: iOS性能优化:Instruments使用实战 iOS 使用Instruments的工具小结
- 嵌入式Linux学习(一)
嵌入式系统 嵌入式系统是一种专用的计算机系统,作为装置或设备的一部分.通常,嵌入式系统是一个控制程序存储在ROM中的嵌入式处理器控制板.事实上,所有带有数字接口的设备,如手表.微波炉.录像机.汽车等, ...
- 修改Unity中Lua文件的默认打开程序
项目中引用了XLua,而Lua文件又是以txt文件结尾的,当修改系统的扩展脚本编辑器为vs后双击lua文件(xx.txt)默认也使用vs打开了,无提示的黑白文本编辑 昨办? -. 后来看到网上有写Un ...
- OS面试题(转载)
转载自:http://placement.freshersworld.com/power-preparation/technical-interview-preparation/os-intervie ...
- PC高级语言与施耐德、罗克韦尔、台达等PLC的Modbus通讯源代码(ModbusTCP.DLL/ModbusRTU.DLL)
1.0 通讯组件概述 该类通讯组件适用于基于PC高级语言的工业自动化控制系统,用于PC与可编程控制器(PLC).智能仪表等进行数据通讯.组件采用动态链接库文件(*.DLL)的形式,在PC系统的项目工 ...
- 【T05】套接字接口比XTI_TLI更好用
1.用于网络编程的API接口有两种: Berkeley套接字 XTL 2.套接字是加州大学伯克利分校为其Unix操作系统版本开发的,TLI是AT&T(贝尔实验室)为Unix系统V3.0开发的 ...
- WPF 使用HttpListener搭建本地web服务器
准备工作 using Micro.Listener 类(Micro.Listener.dll)下载 调用示例:一.启动服务:new Micro.Listener.ListenerSync(8080). ...
- [javase学习笔记]-6.2 类与对象的关系
这一节我们来看一下类与对象之间的关系. 我们学习java语言,目的就是用java语言对现实生活中的事物进行描写叙述.那么我们如何来描写叙述呢.这就引出了类,我们在实际实现时,是通过类的形式来体现的. ...
- array2json() - Convert PHP arrays to JSON
array2json is a PHP function that will convert the array given as its argument into a JSON string. T ...
- Swift 弱引用与无主引用
前言 Swift 提供了两种解决循环引用的方法,弱引用和无主引用. 弱引用和无主引用可以使循环中的一个实例引用另一个实例时不使用强引用. 1.弱引用 对生命周期中会变为 nil 的实例采用弱引用,也就 ...