实践1:参数以by value方式而非by reference方式传递
实践2:对不变的data和object reference使用final
实践3:缺省情况下所有non-static函数都可被重写
实践4:在array和Vectors之间慎重选择
实践5:多态(polymorphism)优于instanceof
实践6:必要时才使用instanceof
实践7:一旦不需要object reference,就将它设为null
import java.awt.Point;
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);
}
}
这段代码在//2处建立了一个Point对象并设初值为(0,0),接着将其值赋予object reference 变量p。然后对基本类型int i赋值10。//3调用static modifyPoint(),传入p和i。modifyPoint()对第一个参数pt调用了setLocation(),将其左边改为(5,5)。然后将第二个参数j赋值为15.当modifyPoint()返回的时候,main()打印出p和i的值。
程序输出如下:
Before modifyPoint p = java.awt.Point[x=0,y=0] and i = 10
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)。
Java 关键字 final 用来表示常量数据。例如:
public class Test {
static final int someInt = 10;
//
}
这段代码声明了一个 static 类变量,命名为 someInt,并设其初值为10。
任何试图修改 someInt 的代码都将无法通过编译。例如:
//
someInt = 9; // Error
//
关键字 final 可防止 classes 内的 instance 数据遭到无意间的修改。如果我们想要一个常量对象,又该如何呢?例如:
class Circle {
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 5.0
Radius of wheel is now 7.4
在上述第一个示例中,我们企图改变final 数据值时,编译器会侦测出错误。
在第二个示例中,虽然代码改变了 instance变量wheel的值,编译器还是让它通过了。我们已经明确声明wheel为final,它怎么还能被改变呢?
不,我们确实没有改变 wheel 的值,我们改变的是wheel 所指对象的值。wheel 并无变化,仍然指向(代表)同一个对象。变量wheel是一个 object reference,它指向对象所在的heap位置。有鉴如此,下面的代码会怎样?
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 = 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不能被改变,必须永远指向同一个对象,但被指的那个对象可以随意改变内部的属性值。
关键字final 在Java中有多重用途,即可被用于instance变量、static变量,也可用于classes或methods,用于类,表示该类不能有子类;用于方法,表示该方法不允许被子类覆盖。
array和Vector的比较
|
支持基本类型
|
支持对象
|
自动改变大小
|
速度快
|
array
|
Yes
|
Yes
|
No
|
Yes
|
Vector
|
No(1.5以上支持)
|
Yes
|
Yes
|
No
|
代码1:instanceof方式
interface Employee {
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));
}
}
依据这个设计,calcPayroll()必须使用instanceof操作符才能计算出正确结果。因为它使用了Employee接口,所以它必须断定Employee对象究竟实际属于哪个class。程序员有奖金而经理没有,所以你必须确定Employee对象的运行时类型。
代码2:多态方式
interface Employee {
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));
}
}
在这个设计中,我们为Employee接口增加了 bonus(),从而消除了instanceof的必要性。实现Employee接口的两个 classes:Programmer和Manager,都必须实现salary()和bonus()。这些修改显著简化了calcPayroll()。
import java.util.Vector;
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();
//
}
}
}
}
这段代码表明在 这种场合下 instanceof 操作符是必需的。当程序从Vector 取回对象,它们属于java.lang.Object。利用instanceof确定对象实际属于哪个class后,我们才能正确执行向下转型,而不至于在运行期抛出异常。
posted on 2008-02-26 17:56
CoderDream 阅读(296)
评论(0) 编辑 收藏 所属分类:
学习笔记