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.異常不容忽視(異??梢愿采w):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,這是一個宣稱支持克隆操作的標識接口。