以下是学习《Practical Java(重点版)》的笔记。
1. java的方法参数传的都是值,而不是引用,传的对象其实是地址的值。所谓的java传引用是错误的说法,在C#中才有传引用的说法。
2. 对不变的数据和对象引用使用final。
1)不变的原生态数据类型设置final,如:
public class Test2 {
public static final int A = 3;
public static void main(String[] args) {
Test2.A = 4;//报错,常量不能够再重新设置
}
}
2)对对象引用设置final,如:
public class Test2 {
public static final A a = new A();
public static void main(String[] args) {
a.x = 10;
System.out.println(a.x);
a.x = 12;
System.out.println(a.x);
}
}
class A {
int x;
public A() {
}
}
此时A对象中的x值是改变了。
public class Test2 {
public static final A a = new A();
public static void main(String[] args) {
a = new A();//报错,是因为a是一个常量对象,不能够在指向其他对象了。
}
}
总之,如果对对象引用加final的话,是指该引用不能够再指向其他的对象了,但是指向的对象里面的值是可以改变的。
3. 在缺省的情况下非private、非静态方法都可以被子类覆写。如果想阻止子类覆写父类方法,可以将父类的方法加final关键字。如果子类覆写了父类的final方法时,在编译会出现“不能够覆写父类的方法”异常。如果将类加final时,这该类没有子类,编译会报错。
4. 对Vectors和arrays要慎重选择
Java arrays(数组)是一个对象引用,它里面既可以放原生态类型,也可以放对象。放原生态类型时,有默认值;放对象时,并不会调用类的默认构造方法,而是放的null。Java arrays不能够超出数组的大小,否则会出现数组越界异常。
Java vector没有大小限制,当元素被增加或删除时,其内部元素会移动,以确保大小合适。Java vector只能够放对象引用,不能够放基本类型(但从jdk1.5开始有自动装箱功能,不存在放基本类型问题,因为基本类型就自动装箱了)。Vector的底层还是一个array实现。
array 和Vector 的比较
| 支持基本类型 | 支持对象引用 | 自动改变大小 | 速度 |
Array | Y | Y | N | Y |
Vector | N | Y | Y | N |
5. 多态(polymorphism)优于instanceof。在java中使用instanceof是为了在运行期间期确定[某个对象隶属哪个class]。在多数情况下,可以使用polymorphism避免使用instanceof,这样可以提供程序的面向对象纯度,使程序扩展较好。
1) 如果必须使用instanceof来判断使用哪个子类的时候,请考虑是否将其接口是否可以增加一个方法,达到通用的目的。
2) 当看到instanceof的时候,请考虑设计上的问题,尽量避免使用它。
6. 必要时才使用instanceof
为了避免转型异常,可以使用以下方法:
1.使用try/catch,处理ClassCastExceptio
2. 使用instanceof
7. 一旦不需要对象引用时,就设置为null。Java垃圾回收机制负责回收不再使用的内存。即使垃圾回收器执行起来,也并非所有[不再被引用](unreferenced)的内存都可被回收。通过[查询可用内存、调用System.gc()、再查询可用内存]的步骤,你可以推测你的JVM 所用的垃圾回收器的某些行为:
Runtime r = Runtime.getRuntime();
long freeM = r.freeMemory();
System.out.println(freeM);
System.gc();
freeM = r.freeMemory();
System.out.println(freeM);
当程序调用System.gc()时,绝大多数JVM 实现品的响应都是执行垃圾回收器。此外,如果内存可用量过低,或CPU 在一段时间内处于空闲状态时,大多数JVM 也会隐式(自动地)调用垃圾回收器。多长久的空闲才会引发垃圾回收器被调用呢?这取决于JVM 所采用的垃圾回收算法.
检阅代码时,请注意大块头对象,尤其是那些存在于完整(或大部分)程序生命中的对象。你应该仔细研究这些对象的建立和运用,以及它们可能引用多少内存。如果它们引用了大量内存,请确定是否所有那些内存在对象生命期内都真的被需要。也许某些大块头对象可以解甲归田,从而使其后执行的代码能够更高效地运行任何时刻你都可以通过system.gc()要求垃圾回收器起身行动。如果想将一个对象解除引用(unreference),则可以通过调用System.gc()要求垃圾回收器立刻运转,在代码继续执行前先回收被解除引用的那块内存。但是你应当仔细考量这种做法为你的程序性能带来的潜在影响许多垃圾回收算法会在它们运转之前先虚悬(suspend)其他所有线程 (threads)这种做法可以确保一旦垃圾回收器开始运转,就能够拥有heap 的完整访问权,可以安全完成任务而不受其他线程的威胁。一旦垃圾回收器完成了任务,便恢复(resume)此前被虚悬的所有线程。因此,通过System.gc()显示调用,要求垃圾回收器起而运行,你得冒[因执行回收工作而带来延迟]的风险,延迟程序取决于JVM 所采用的垃圾回收算法。