阅读pratical java随笔
J2SE经典实例
1.import java.awt.Point; class PassByValue{
public static void modifyPoint(Point pt, int j){pt.setLocation(5,5); j=15 ; System.out.println(pt +"传值进来 ;" + j);} //进行别名覆盖
public static void main(String args[]){Point p = new Point(0,0);
int i = 10; System.out.println(p +"第一次值 " + i);
modifyPoint(p, i); //java值传递方式传递了对象的地址,一个reference
System.out.println(p +"只传了引用,本身值二进制代码没变" + i); }}//局部变量范围有限
2.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(wheel.radius());
wheel.setRadius(7.4);//final修饰对象,只能改变了值,而不能改变引用(地址),如果:wheel=new Circle(7.4)将错误;没有改变wheel的值,只是改变了wheel所指对象的值。
System.out.println("Radius of wheel is now " +wheel.radius());}}//输出7.4
3.class Base{public final void bar(){}}//应用广泛
class Derived extends Base{
// public void bar(){//Attempting to override Base.bar()}}//修饰类,方法不能重写
4.import java.awt.Button; class ArrayTest{
public static final int arraySize = 3;public static void main(String args[]){
int[] ia = new int[arraySize];for (int i=0; i<arraySize; i++)
System.out.println("int array initially " + ia[i]);// 整型初始都是0
Button[] oa = new Button[arraySize];for (int i=0; i<arraySize; i++)
System.out.println("Button array initially " + oa[i]); }}//类初始都是null
Array和Vector的区别:a.Array有大小限定,而Vector大小是可变的,Array效率高
b.Array更新是静态的,而Vector可以动态移动下标,但只能存对象
5.多态在面向对象纯度和扩展性优于instanceof,除非接口不能修改才用后者,如继承库
interface Employee{public int salary();public int bonus();}
class Manager implements Employee{private static final int mgrSal=40000,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){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(pr.calcPayroll(prg));System.out.println(pr.calcPayroll(mgr));}}
6.一旦不需要类的引用,就将设为NULL。如果有对象存在于程序运行期间的大部分时间,而它们所引用的内存在这段期间内并不需要,那么大片内存就被浪费掉了,因为JVM垃圾回收程序总是先回收新生的短期对象。但在堆的管理算法中会预先分配一些内存供你的程序使用,这样回收的结果并不会影响其他系统进程,只是提高JAVA程序自身运行效率。
class Foo{public static void main(String args[]){Customers cust=new Customers("Data");
//使用过程中..//Customers object no longer needed.cust = null;//The rest of the app.}}
7.= =和equals: class Test{public static void main(String args[]){
int a = 10;float b = 10.0f;//外附类和Object中都有equals();
System.out.println("a==b is " + (a==b));//true,不同基本型别实质的值也是相等的
Integer ia = new Integer(10);Float fa = new Float(10.0f);
System.out.println("fa.equals(ia) is " + (fa.equals(ia)));}}//false,实质内容不同
如果所使用的class并未实现equals(),请判断Object的缺省方法是否可胜任都不行就重写
8.equals()最佳实现方式就是搭配getClass(),返回运行时类,确保只有相同的class所产生的对象才有机会被视为相等,具体比较多少属性才算相同可自己根据相关属性确定。
class Golfball{private String brand;private String make;private int compression;
public Golfball (String str, String mk, int comp){brand=str;make=mk;compression=comp;}
public String brand(){return brand;} public String make(){return make;}
public int compression(){return compression;}
public boolean equals(Object obj){ if (this == obj) return true;
if ((obj != null) && (getClass() == obj.getClass())) {Golfball gb = (Golfball)obj;
if((brand.equals(gb.brand()))&&(make.equals(gb.make())){
return true;}} return false; }//...}
9.如果要从class B派生class D,要在class D中调用B的equals(),就一定要调用super.equals(),常常因为父类无法修改
10.基类与继承类的equals: class Base{public boolean equals(Object obj){
if (obj instanceof Base){}//...return true;}} class Derived extends Base{}
class test{ public static void main(String args[]) {
Base b = new Base(); Derived d = new Derived();
//if (d.equals(b)) //Potentially true if Base attributes are equal
//if (b.equals(d)) //Potentially true if Base attributes are equal//...} }
a.base class实现了equals(),而derived class没有:假设base class的equals()使用instanceof, 那么derived 和base class对象进行比较,是对称的。
b.base class和derived class 都实现了equals():如果两个class都在equals()中使用instanceof,当调用derived class equals()返回的是false,因为base对象并非derived实体;当调用base class equals()时返回的是true.
c.base class并未实现equals(),但derived class实现了:因为base对象并非derived实体,调用derived class equals()会返回false;因为base此时调用了Object中equals()进行比较两个类的引用是否相同,所以调用base class equals()返回false;
注:如果只允许同一个class所产生的对象被视为相等,通常用getClass();只有在不得不对derived classes与base class进行比较才用instanceof,如父类是库。
11.在try中慎用返回:
import java.io.*;public class Mine{public static void main(String argv[]){
Mine m = new Mine();System.out.println(m.amethod());}
public int amethod(){
try {FileInputStream dis = new FileInputStream("Hello.txt");}
catch (FileNotFoundException fne) {System.out.println("No such file found");
return -1; } //因finally一定要执行,这句话最后被执行!,return语句程序终止
catch(IOException ioe) { }
finally{System.out.println("finally");} return 0;} }//0打不出,返回一次终止本方法体
12.异常不容忽视(异常可以覆盖):class Hidden{ public static void main (String args[]){
Hidden h = new Hidden();try {h.foo(); } catch (Exception e) {
System.out.println("In main, exception: " +e.getMessage()); }}
public void foo() throws Exception {
try { throw new Exception("First Exception"); } //最先产生异常
catch (Exception e){ throw new Exception("Second Exception");} //覆盖第一个异常
finally { throw new Exception("Third Exception"); }}}//最后打印出的异常
13.将异常用vector全部收集: import java.io.*;import java.util.Vector;
class ReadFileExceptions extends Exception{ private Vector excVector;
public ReadFileExceptions(Vector v){ excVector = v; }
public Vector exceptionVector() {return excVector; } //...}
class NotHidden{public static void main(String args[]){ NotHidden nh = new NotHidden();
try {nh.readFile();}catch (ReadFileExceptions rfe) { //... } }
public void readFile() throws ReadFileExceptions{ BufferedReader br1 = null;
BufferedReader br2 = null; FileReader fr = null;
Vector excVec = new Vector(2); //Vector to store exceptions
try {fr = new FileReader("data1.fil");br1 = new BufferedReader(fr);int i = br1.read(); fr = new FileReader("data2.fil");br2 = new BufferedReader(fr); i = br2.read();
//... }//finally通常用于内存回收之外的情况,一定执行,如关闭缓存等
catch (FileNotFoundException fnfe) {excVec.add(fnfe); } //Add exception to Vector
catch (IOException ioe){excVec.add(ioe); } //Add exception to Vector
finally {if (br1!=null){try {br1.close();} catch(IOException e) {excVec.add(e);} }
if (br2 != null){try {br2.close();}catch (IOException e) { excVec.add(e);}}
if (excVec.size() != 0) throw new ReadFileExceptions(excVec);}}}
14.try/catch置于循环之外(将异常用于流程控制如强行跳出性能差)class ExcPerf{
public void method1(int size){int[] ia = new int[size];
try { for (int i=0;i<size;i++)ia[i]=i; } catch (Exception e){} }
public void method2(int size){ int[] ia = new int[size];
for (int i=0; i<size; i++){ try { ia[i] = i;} catch (Exception e){} }}
public static void main(String args[]) { int size = Integer.parseInt(args[0]);
ExcPerf ep = new ExcPerf(); long start = System.currentTimeMillis();//豪秒
ep.method1(size);long end = System.currentTimeMillis();
System.out.println("normal took" +(end-start) + " milliseconds");
start=System.currentTimeMillis();ep.method2(size);end=System.currentTimeMillis();
System.out.println("try/catch took " +(end-start) + " milliseconds"); }}
备注:java –Djava.compiler=NONE ExcPerf 777777,原始运行可以看出方法1快于方法2;
但是开启JIT后的运行时间方法1慢于方法2,优化器耗用内存达到的效果.
对于大型运算数据带上JIT效率会在内存和CPU上胜出,自身占用小于优化所得。
15.不要每逢出错时就使用异常:如果是可预料性的就使用传统错误处理方式
int data;MyInputStream in=new MyInputStream(“filename.txt”);
Data=in.getData();while(data!=0){//Do something;data=in.getData();}
可预料性错误使用异常参与流程控制降低了性能。异常用于非寻常性情况:如文件存在否
int data;MyInputStream in=new MyInputStream(“filename.txt”);while(true){
try{data=in.getData();} catch(Exception e){break;}//参与流程控制
16.避免多接口中方法的冲突:interface Bowler{ public void computeScore();}
interface Golfer{ public void computeScore();}//int出错
class Enthusiast implements Golfer, Bowler{public void computeScore(){//... }}
a.方法名和返回类型都相同编译才能通过;
b.如果接口无法更改,只有用两个类各自继承以实现期望功能,最好在命名时尽量避免。
17.immutalbe class不可变类:多个线程非同步时数据读取不可能修改,没有必要同步控制。
但是需要付出更多的代价,如额外代码。private,final,只有getter()方法而没有setter.
final class PinNumbers{ private String acctOwner; private int checkingAcctPin;
private int savingsAcctPin;PinNumbers(String owner, int cPin, int sPin) {
acctOwner = owner;checkingAcctPin = cPin; savingsAcctPin = sPin; }
public String accountOwner() {return acctOwner;}public int checkingPin(){
return checkingAcctPin;}public int savingsPin(){return savingsAcctPin; } }
18.实现不可变类时,必须对传入或传出mutable类进行clone.(如上例各成员都不可变除外)
如存在构造方法,不管构造方法是什么访问权限都可传入数据,因为是值传递方式。
final class User1{ private String userName; User1(String name) {userName = name;}
public String userName() {return userName; }
public void setUserName(String name){userName = name; } }
final class DiskDriveInfo1{private User1 driveShare;
DiskDriveInfo1(User1 share){driveShare=share;}
public User1 share( ) {return driveShare;} }
public class TestClone{ public static void main(String args[]) {
User1 share1 = new User1("Duke");//输出值为Duke,Fred
System.out.println("User is " +share1.userName());
DiskDriveInfo1 dd = new DiskDriveInfo1(share1);User1 share = dd.share();
share1.setUserName("Fred");System.out.println("User is " +share.userName());}}
高效的代码=良好的设计+明智的数据结构+精简的算法,可操作性和可移植更重要
19.如果不变类与mutable类引用交流,clone可变类:shallow clone浅层克隆,如果cloned类包含了一些类引用(已经有new产生),那么新的类将内含与该类的引用完全一致的副本。
class User implements Cloneable{ private String userName;
User(String name){ userName = name; }
public void setUserName(String name) {userName = name; }
public String userName() {return userName;}
public Object clone(){try{return super.clone();}
catch(Exception e){e.getMessage();}return userName; }}
final class DiskDriveInfo{ private User driveShare;
DiskDriveInfo(User share){driveShare = (User)share.clone(); }
public User share() {return (User)driveShare.clone();}}//输出值为Duke,Duke
public class Test{ public static void main(String args[]) {
User share1 = new User("Duke");DiskDriveInfo dd = new DiskDriveInfo(share1);
User share = dd.share();System.out.println("User is " +share.userName());
share1.setUserName("Fred"); System.out.println("User is " +share.userName()); }}
20.Clone()之中首先必须调用super.clone(),可确保java.lang.Object的clone()最终会被调用,因而使得克隆件得以被正确建构出来;任何class如果支持克隆操作,就必须实现cloneable interface,这是一个宣称支持克隆操作的标识接口。