实践2:对不变的data和object reference使用final
实践3:缺省情况下所有non-static函数都可被重写
实践4:在array和Vectors之间慎重选择
实践5:多态(polymorphism)优于instanceof
实践6:必要时才使用instanceof
实践7:一旦不需要object reference,就将它设为null
实践1:参数以by value方式而非by reference方式传递
class PassByValue {
public static void modifyPoint(Point pt, int j) {
pt.setLocation( 5 , 5 ); // 1
j = 15 ;
System.out.println( " During modifyPoint " + " pt = " + pt + " and j = " + j);
}
public static void main(String args[]) {
Point p = new Point( 0 , 0 ); // 2
int i = 10 ;
System.out.println( " Before modifyPoint " + " p = " + p + " and i = " + i);
modifyPoint(p, i); // 3
System.out.println( " After modifyPoint " + " p = " + p + " and i = " + i);
}
}
程序输出如下:
During modifyPoint pt = java.awt.Point [ x=5,y=5 ] and j = 15
After modifyPoint p = java.awt.Point [ x=5,y=5 ] and i = 10
这显示modifyPoint()改变了//2 所建立的Point对象,却没有改变int i。在main()之中,i被赋值10.由于参数通过by value方式传递,所以modifyPoint()收到i的一个副本,然后它将这个副本改为15并返回。main()内的原值i并没有受到影响。
对比之下,事实上modifyPoint() 是在与“Point 对象的 reference 的复件”打交道,而不是与“Point对象的复件”打交道。当p从main()被传入modifyPoint()时,传递的是p(也就是一个reference)的复件。所以modifyPoint()是在与同一个对象打交道,只不过通过别名pt罢了。在进入modifyPoint()之后和执行 //1 之前,这个对象看起来是这样:
所以//1 执行以后,这个Point对象已经改变为(5,5)。
实践2:对不变的data和object reference使用final
Java 关键字 final 用来表示常量数据。例如:
static final int someInt = 10 ;
//
}
这段代码声明了一个 static 类变量,命名为 someInt,并设其初值为10。
任何试图修改 someInt 的代码都将无法通过编译。例如:
someInt = 9 ; // Error
//
关键字 final 可防止 classes 内的 instance 数据遭到无意间的修改。如果我们想要一个常量对象,又该如何呢?例如:
private double rad;
public Circle( double r) {
rad = r;
}
public void setRadius( double r) {
rad = r;
}
public double radius() {
return rad;
}
}
public class FinalTest {
private static final Circle wheel = new Circle( 5.0 );
public static void main(String args[]) {
System.out.println( " Radius of wheel is " + wheel.radius());
wheel.setRadius( 7.4 );
System.out.println( " Radius of wheel is now " + wheel.radius());
}
}
这段代码的输出是:
Radius of wheel is now 7.4
在上述第一个示例中,我们企图改变final 数据值时,编译器会侦测出错误。
在第二个示例中,虽然代码改变了 instance变量wheel的值,编译器还是让它通过了。我们已经明确声明wheel为final,它怎么还能被改变呢?
不,我们确实没有改变 wheel 的值,我们改变的是wheel 所指对象的值。wheel 并无变化,仍然指向(代表)同一个对象。变量wheel是一个 object reference,它指向对象所在的heap位置。有鉴如此,下面的代码会怎样?
private static final Circle wheel = new Circle( 5.0 );
public static void main(String args[]) {
System.out.println( " Radius of wheel is " + wheel.radius());
wheel = new Circle( 7.4 ); // 1
System.out.println( " Radius of wheel is now " + wheel.radius());
}
}
编译代码,// 1 处出错。由于我们企图改变 final 型变量 wheel 的值,所以这个示例将产生编译错误。换言之,代码企图令wheel指向其他对象。变量wheel是final,因此也是不可变的。它必须永远指向同一个对象。然而wheel所指向的对象并不受关键字final的影响,因此是可变的。
关键字 final 只能防止变量值的改变。如果被声明为 final 的变量是个 object reference,那么该reference不能被改变,必须永远指向同一个对象,但被指的那个对象可以随意改变内部的属性值。
实践3:缺省情况下所有non-static函数都可以被覆盖重写
关键字final 在Java中有多重用途,即可被用于instance变量、static变量,也可用于classes或methods,用于类,表示该类不能有子类;用于方法,表示该方法不允许被子类覆盖。实践4:在array和vectors之间慎重选择
array和Vector的比较
|
支持基本类型 |
支持对象 |
自动改变大小 |
速度快 |
array |
Yes |
Yes |
No |
Yes |
Vector |
No(1.5以上支持) |
Yes |
Yes |
No |
实践5:多态(polymorphism)优于instanceof
代码1:instanceof方式
public int salary();
}
class Manager implements Employee {
private static final int mgrSal = 40000 ;
public int salary() {
return mgrSal;
}
}
class Programmer implements Employee {
private static final int prgSal = 50000 ;
private static final int prgBonus = 10000 ;
public int salary() {
return prgSal;
}
public int bonus() {
return prgBonus;
}
}
class Payroll {
public int calcPayroll(Employee emp) {
int money = emp.salary();
if (emp instanceof Programmer)
money += ((Programmer) emp).bonus(); // Calculate the bonus
return money;
}
public static void main(String args[]) {
Payroll pr = new Payroll();
Programmer prg = new Programmer();
Manager mgr = new Manager();
System.out.println( " Payroll for Programmer is " + pr.calcPayroll(prg));
System.out.println( " payroll for Manager is " + pr.calcPayroll(mgr));
}
}
代码2:多态方式
public int salary();
public int bonus();
}
class Manager implements Employee {
private static final int mgrSal = 40000 ;
private static final int mgrBonus = 0 ;
public int salary() {
return mgrSal;
}
public int bonus() {
return mgrBonus;
}
}
class Programmer implements Employee {
private static final int prgSal = 50000 ;
private static final int prgBonus = 10000 ;
public int salary() {
return prgSal;
}
public int bonus() {
return prgBonus;
}
}
class Payroll {
public int calcPayroll(Employee emp) {
// Calculate the bonus. No instanceof check needed.
return emp.salary() + emp.bonus();
}
public static void main(String args[]) {
Payroll pr = new Payroll();
Programmer prg = new Programmer();
Manager mgr = new Manager();
System.out.println( " Payroll for Programmer is " + pr.calcPayroll(prg));
System.out.println( " Payroll for Manager is " + pr.calcPayroll(mgr));
}
}
实践6:必要时才使用instanceof
class Shape {
}
class Circle extends Shape {
public double radius() {
return 5.7 ;
}
//
}
class Triangle extends Shape {
public boolean isRightTriangle() {
// Code to determine if triangle is right
return true ;
}
//
}
class StoreShapes {
public static void main(String args[]) {
Vector shapeVector = new Vector( 10 );
shapeVector.add( new Triangle());
shapeVector.add( new Triangle());
shapeVector.add( new Circle());
//
// Assume many Triangles and Circles are added and removed
//
int size = shapeVector.size();
for ( int i = 0 ; i < size; i ++ ) {
Object o = shapeVector.get(i);
if (o instanceof Triangle) {
if (((Triangle) o).isRightTriangle()) {
//
}
} else if (o instanceof Circle) {
double rad = ((Circle) o).radius();
//
}
}
}
}