对象引用: reference
Object o = new Object();
其中o就是引用变量,就好比一个人的名字,别人喊你名字的时候,你就会有反应一样,比如你的上司,通过你的名字,可以对你进行发号施令。
通过操作引用变量,可以对一个对象发布命令。
引用变量和对象不是同一个概念。
基本类型转换:
比如说一个方法或者变量接受一个较小的类型作为参数,而实际传入一个较大的,在传入的时候,就必须做 “类型转换”
如:
double d =3.1415d;
int i = (int)3.1415d;
tij中称之为“窄化转换” (narrowing conversion)
以后还有遇到“类类型转换”也可以说 “造型”(Casting)
构造器:Constructor
确保了正确的初始化和清理
如果没有构造器,java中将不允许创建对象,所以你可以完全的掌控,非常安全
如果通过构造器产生了对象,那对象会再某一时刻被Garbage所回收。但是垃圾回收不需要进行手工干预,即使手工干预了,也不一定会立刻执行,可以通过调用System.gc()
来召唤垃圾回收器,garbage collector是一个低优先级的线程。
调用finalize()方法,在一个对象被垃圾回收器回收前,首先会调用对象的此方法,所有对象都有此方法,从Object中继承二来。
重写Object类中的finalize()方法,来实现一个对象回收前的清理或者检查工作。
如TIJ中的一例:(此例在原书3rd(英文版)中第187页,原书3rd (中文版)104页)
public class Book {
boolean checkedOut = false;
Book(boolean checkOut) {
checkedOut = checkOut;
}
void checkIn() {
checkedOut = false;
}
public void finalize() {
if (checkedOut)
System.out.println("Error: checked out");
}
}
class TerminationCondition {
public static void main(String[] args) {
Book novel = new Book(true);
// Proper cleanup:
novel.checkIn();
// Drop the reference, forget to clean up:
new Book(true);
// Force garbage collection & finalization:
System.gc();
}
}
输出结果为:
Error: checked out
没有引用指向
new Book(true);所以改对象被回收了,但是回收前调用了对象的finalize()方法,做了检查工作。
垃圾回收器的2种工作模式:
由VM监视,进行模式切换,是“自适应”的。
1
.“停止-复制”
模式-- 堆复制,将存活的对象从一个堆复制到灵一个堆,而且复制到新堆的时候,对象是紧凑排列的。
2
.“标记-清扫”
--
扫描当前堆中对象,并且释放掉那些垃圾对象,但是,不是连续的
关于finalize(),当没有引用指向对象时,在垃圾回收器回收该对象之前,必定要调用finalize()方法,此方法在Object中为空实现。
成员初始化的顺序
永远都无法阻止Field的自动初始化的进行!
Class Num{
int i;
int a = 6;
Num(){
i=6;
a=7;
}
…
…
}
i
一定会先被置0,然后才会变成6 。
a
也一样,即使初始了值也会先变成0,然后赋值为6,最后通过构造器变为7。
初始化顺序
1.
字段自动初始化默认值 :
基本类型: 0 ,boolean : false char :“/u
0000”
2
.静态代码块—产生一个类的对象或访问一个类的静态成员(字段和方法,虽然没有产生这个类的对象),就会触发执行,只执行一次。
static{
int i=3;
}
3.
非静态代码块 -- 产生类的对象的时候,执行,每产生一个对象,都会执行一次,有点像构造器,但是先于构造器之前执行。
{
int i=3
}
3.
构造器 --产生类的对象的时候,执行,每产生一个对象,都会执行一次。晚于非静态代码块
看一个简单的证明例子:
public class InitializationDemo {
// auto-Initialization
int i; // 1st
static String str = "load once";
//static block
static {
System.out.println(" ** static block ** ");
}
// non-static block Initialization
{
i = 6; // 2nd
System.out.println("non-static block_1 i = " + i);
i++;
System.out.println("non-static block_2 i =" + i);
}
// Constructor Initialization
public InitializationDemo() {
i++; // 3rd
}
}
class Test {
public static void main(String... args) {
// static-block loading only once
System.out.println(InitializationDemo.str);
// create two instance,so non-static block has been loaded twice
InitializationDemo id1 = new InitializationDemo();
InitializationDemo id2 = new InitializationDemo();
// serialza initialization "i"
System.out.println("main method: id1 field i = " + id1.i);
System.out.println("main method: id2 field i = " + id2.i);
}
}
输出结果:
** static block **
load once
non-static block_1 i = 6
non-static block_2 i =7
non-static block_1 i = 6
non-static block_2 i =7
main method: id1 field i = 8
main method: id2 field i = 8
从这个结果能证明上述初始化顺序。
数组的初始化:
数组是一种 相同类型的,用同一个标识名,封装在一起的对象序列。
数组通过标识名和下标操作符[ ]来操纵
基本类型数组:
数组中只能存放的是基本数据类型和引用,不能存放对象。
int[] a1=new int[5];//封装了一个大小为5个单位int类型的,标识名为a1的数组
int[] a2=new int[]{1,2,3,4}; //定义封装的同时,初始化数组的大小
a1[3]=5;//通过下标操作符复制
int i=a1[3];//通过下标操作符取值
引用数组:
Integer[] it = new Integer[]{new Integer(5),new Integer(6)};
int a=it[0];
int b=it[1];
假设有个Person类,其中有talk()方法,声明引用数组:
Person[] p2 =new Person[]{new Person(),new Person()};
p2[0].talk();
相当于
Person p = new Person();
p.talk();
这里的p2[0]相当于p,都只是堆内存中某个对象的引用变量
数组不同于集合:
集合中存放的是对象,任何事物在java中都是对象。虽然集合和数组非常相似。
集合类中有很多工具提供,可以自己扩充容量以适用需求。集合的详细内容在以后再作介绍
这是一个集合例子的代码片断:
假设有个Person类,其中有talk()方法,声明引用数组:
Person person1 = new Person("javier", 24, "male");
Person person2 = new Person("Michale", 23, "female");
ArrayList<Person> list = new ArrayList<Person>();
list.add(person1);
list.add(person2);
// 方法一,通过集合下标取第一个元素,并调用对象的方法
list.get(0).talk();
// 方法二,通过迭代器,只遍历第一个元素,并调用对象的方法
list.iterator().next().talk();
// 方法三 通过迭代器遍历所有元素,并调用对象的方法
Iterator<Person> iter = list.iterator();
while (iter.hasNext()) {
iter.next().talk();
}