Java核心篇是Java語言學習的重點,需要充分理解面向對象的思想。入門階段要達到的要求是會“用”,就是能用Java編寫代碼實現需求所要的基本功能,之后隨着對Java編程思想的學習深入,慢慢理解為什么要這么寫,或者說應該怎么寫。

一、類的繼承和多態
繼承和多態是面向對象語言中非常重要的特性,使用得當的話,會使整個程序的架構變得非常有彈性,減少冗余度。在開發的過程中,要多思考如何設計才能使得達到這個要求。
- 子類繼承父類的構造方法,非private成員變量和方法,同時可以定義自己的變量,以及重寫方法(包括構造方法),重寫時方法修飾權限只能向范圍大變化;
- 實例化子類對象時,子類構造方法會自動調用父類無參構造方法,先實例化父類對象,再實例化子類對象,有參構造方法不能被自動調用;
- 區別重寫和重載:重寫override,只有實現內容不同,體現的是父與子之間的多態性;重載overload,體現的是類的多態性,可以是參數類型/順序/個數不同;
- 向上轉型一般沒問題,平行四邊形也是四邊形;向下轉型須得用顯示類型轉化,不能說四邊形是平行四邊形,但可以定義一個“平行四邊形”的四邊形;
- 在父類的方法draw()中將子類對象作為參數(利用向上轉型),根據不同子類對象實現不同的邏輯,可避免每個子類單獨重寫draw()方法,解決代碼冗余問題,也易於維護,這是多態的一個應用;
- 頂層父類往往定義成抽象類(例如:圖形類,並無明確的幾條邊,幾個頂點,可能有抽象的方法——繪圖,面積等),繼承該類的子類必須重寫其中的抽象方法;
- 未必每個子類都心甘情願重寫抽象父類的某個抽象方法,可以考慮放在接口中,實現該接口的類(必須)重寫該方法,因為類不能同時繼承多個父類,但是可以實現多個接口。
/**********繼承/多態**********/ package com.kplayer.graph; //抽象類-圖形類 public abstract class Graph { abstract void init(); //提供一個抽象init()方法,繼承該抽象類的需重寫 } //接口-計算面積 //類不能同時繼承多個父類,但可實現多個接口 public interface Area { public void area(); //提供一個area()接口,實現該接口的需重寫 } //父類-四邊形類 public class Quadrangle extends Graph implements Area{ public double area; //成員變量:面積 public static void draw(Quadrangle q){ //成員方法:繪圖 if(q instanceof Parallelogram){ System.out.println("Draw image of Parallelogram!"); }else if(q instanceof Square){ System.out.println("Draw image of Square!"); }else{ System.out.println("Draw image of Quadrangle!"); } } public void init(){ //繼承抽象類,需重寫init()方法 System.out.println("Initialize Quadrangle..."); } public void area(){ //實現接口,需重寫area()方法 System.out.println("Compute area of Quadrangle!"); } public Quadrangle(){ //構造方法 System.out.println("Construct Quadrangle Success!"); } } //子類-平行四邊形 public class Parallelogram extends Quadrangle{ public double width; //子類新增成員變量:長 public double height; //子類新增成員變量:高 public double angle; //子類新增成員變量:角 public double area; //子類新增成員變量:面積 public void area(){ System.out.println("Overloading method area!"); this.area = this.width*this.height; } //重寫(重構:只方法實現內容不同),父與子之間的多態性,權限修正只能變大 public void init(){ System.out.println("Initialize Parallelogram(Overriding)..."); } //重載,類中多態性,參數類型/順序/個數不同 public void area(double w, double h){ System.out.println("Overloading method area!"); this.area = w*h; } public Parallelogram(){ //無參構造函數 System.out.println("Construct Parallelogram Success!"); } public Parallelogram(double w, double h, double a){ //有參構造函數 this.width = w; this.height = h; this.angle = a; System.out.println("Construct Parallelogram Success!"); } public static void main(String[] args) { //實例化子類對象,自動調用父類無參構造函數,父類有參構造函數需用super() Parallelogram p = new Parallelogram(4,5,30); //Construct Quadrangle Success! //Construct Parallelogram Success! p.area(4,5); //Overloading method area! System.out.println("area of p = " + p.area); //area of p = 20.0 //向上轉型,將子類對象(平行四邊形)看作父類對象(四邊形) Quadrangle.draw(p); //調用父類方法,多態的應用 //Draw image of Parallelogram! //向下轉型,必須顯式轉換 Quadrangle q = new Parallelogram(); //Construct Quadrangle Success! //Construct Parallelogram Success! Parallelogram p2 = (Parallelogram) q; if(p2 instanceof Parallelogram){ System.out.println("q is Parallelogram!"); //q is Parallelogram! } } } //子類-正方形 public class Square extends Quadrangle { public double length; //子類新增成員變量:邊長 public double area; //子類新增成員變量:面積 //計算面積 public void area(){ this.area = this.length*this.length; } public void area(double l){ this.area = l*l; } public Square(){ //無參構造函數 System.out.println("Construct Square Success!"); } public Square(double length){ //有參構造函數 this.length = length; System.out.println("Construct Square Success!"); } }
二、類高級特性
類中配合包與權限修飾符使用,可以控制他人對類成員的訪問。
- Final變量必須在聲明時賦值,設定后不能再改變。但這並不意味着恆定不變,要看該變量是裝載時初始化,還是實例化對象時初始化,所以通常全局變量使用public static final修飾;
- Final方法不能被重寫(private final方法似乎可以);
- Final類不能被繼承,如果一個類被設置為final,則類中所有方法隱式設置為final形式。
更為有效的隱藏實現細節的技巧是使用內部類,可以向上轉型為被內部類實現的公共接口。
- 內部類的對象實例化必須在外部類或外部類的非靜態方法中實現:outclass.new innerClass() / public innerClass doit();其實內部類地位就和成員變量/方法差不多;
- 內部類向上轉型為接口:a) 定義一個內部類,實現OutInterface接口,權限符為private,只有OuterClass可以訪問;b) 定義一個方法,返回值類型為OutInterface接口,權限符為public,其它類都可以訪問;c) 子類不能繼承InnerClass,也不能訪問f()方法,隱藏了實現細節。但是可以訪問doit()方法,返回OutInterface接口,通過返回的接口可以訪問InnerClass的f()方法。
/**********Final**********/ //Final變量 package com.kplayer.finals; import java.util.Random; import static java.lang.System.out; public class KPFinalV { //final類,不能被繼承,所有方法隱式設置為final private static Random rand = new Random(); // 實例化一個Random類對象 private final int a1 = rand.nextInt(10); //產生0~10之間隨機數 private static final int a2 = rand.nextInt(10); //產生0~10之間隨機數 public static void main(String[] args) { KPFinalV fdata = new KPFinalV(); // 實例化一個對象 out.println("a1:" + fdata.a1); //0 out.println("a2:" + fdata.a2); //3 KPFinalV fdata2 = new KPFinalV(); // 實例化另外一個對象 out.println("重新實例化后a1:" + fdata2.a1); //1,每次實例化重新賦值 out.println("重新實例化后a2:" + fdata2.a2); //3,裝載時初始化 } } //Final方法/類 package com.kplayer.finals; class KPFinalMpar { private final void doit() { //可以被重寫 System.out.println("Parent.doit()"); } final void doit2() { //不能被重寫 System.out.println("Parent.doit2()"); } public void doit3() { System.out.println("Parent.doit3()"); } } final class KPFinalMsub extends KPFinalMpar{ //不能被繼承,所有方法隱式設為final形式 public final void doit() { //override System.out.println("Sub.doit()"); } // final void doit2(){ //Cannot override the final method from KPFinalMpar // System.out.println("Sub.doit2()"); // } public void doit3() { System.out.println("Sub.doit3()"); } } public class KPFinalM { public static void main(String[] args) { KPFinalMsub s = new KPFinalMsub(); s.doit(); //Sub.doit() KPFinalMpar p = s; //向上轉型 // p.doit(); //The method doit() from the type KPFinalMpar is not visible p.doit2(); //Parent.doit2() p.doit3(); //Sub.doit3() } }
/**********內部類**********/ //成員內部類 package com.kplayer.innerclass; public class KPOuterClass { //內部類 class innerClass { int num = 5; //內部類成員變量 public void inf(int num) { //內部類成員方法 num++; //形參 this.num++; //內部類變量num KPOuterClass.this.num++; //外部類變量num } innerClass() { // 內部類構造方法 } } int num; //外部類成員變量 innerClass in = new innerClass(); // 在外部類實例化內部類對象引用 public void ouf() { in.inf(num); // 在外部類方法中調用內部類方法 } public innerClass doit() { // 外部類方法,返回值為內部類引用 // num=4; //外部類不可以直接訪問內部類成員變量 in.num = 4; return new innerClass(); // 返回內部類引用 } public static void main(String args[]) { KPOuterClass out = new KPOuterClass(); // 內部類的對象實例化操作必須在外部類或外部類中的非靜態方法中實現 KPOuterClass.innerClass in = out.doit(); KPOuterClass.innerClass in2 = out.new innerClass(); } } //內部類向上轉型為接口 package com.kplayer.innerclass; interface OutInterface { //定義一個接口 public void f(); } class OuterClass { //定義一個內部類,實現OutInterface接口 //權限符為private,只有OuterClass可以訪問 private class InnerClass implements OutInterface { InnerClass(String s) { //內部類構造方法 System.out.println(s); } public void f() { // 實現接口中的f方法 System.out.println("訪問內部類中的f()方法"); } } //定義一個方法,返回值類型為OutInterface接口 //權限符為public,其它類都可以訪問 public OutInterface doit() { return new InnerClass("訪問內部類構造方法"); } } class OuterClassSub extends OuterClass{ //不能繼承InnerClass,也不能訪問f()方法,隱藏了實現細節 //可以訪問doit()方法,返回OutInterface接口(向上轉型) //通過返回的接口可以訪問InnerClass的f()方法,卻看不到細節 //編寫子類的人員只有一個接口和外部類 } public class KPInterfaceInner { public static void main(String args[]) { OuterClassSub outsub = new OuterClassSub(); //實例化子類對象 OutInterface outinter = outsub.doit();//調用doit()方法,返回OutInterface接口 outinter.f(); //通過返回的接口可以訪問InnerClass的f()方法 } } //局部內部類 package com.kplayer.innerclass; interface OutInterface2 { // 定義一個接口 } class KPOuterClass2 { //成員方法doit() public OutInterface2 doit(final String x) { //參數為final類型 //在方法中定義一個內部類 class InnerClass2 implements OutInterface2 { InnerClass2(String s) { s = x; System.out.println(s); } } return new InnerClass2("doit"); } public static void main(String args[]) { KPOuterClass2 out2 = new KPOuterClass2(); //實例化對象 OutInterface2 outi = out2.doit("訪問內部類"); } } //匿名內部類 package com.kplayer.innerclass; interface OutInterface3 { //定義一個接口 } class KPOuterClass3{ //成員方法doit() public OutInterface3 doit(final String s){ return new OutInterface3(){ //聲明匿名內部類 private int i=0; public int getValue(){ System.out.println(s); return i; } public void f(){ System.out.println("f()"); } }; } } //靜態內部類 package com.kplayer.innerclass; public class KPOuterClass4 { int x=100; static class Inner{ //靜態內部類 void doitInner(){ //System.out.println("外部類"+x); } public static void main(String args[]){ System.out.println("a"); } } }
三、集合類
Java提供了不同的集合類,具有不同的存儲對象的方式,需掌握對集合進行遍歷、添加、刪除以及查找制定的對象。
/**********集合類**********/ package com.kplayer.collection; import java.util.*; public class KPCollection implements Comparable<Object>{ /*For Set Begin*/ String name; long id; public KPCollection(String name, long id) { //構造方法 this.id = id; this.name = name; } public int compareTo(Object o) { //重寫接口方法 KPCollection sets = (KPCollection) o; int result = id > sets.id ? 1 : (id == sets.id ? 0 : -1); return result; } /*For Set end*/ public static void main(String args[]) { //Collection Collection<String> coll = new ArrayList<>(); coll.add("a"); //添加數據 coll.add("b"); coll.add("c"); Iterator<String> it = coll.iterator(); //創建迭代器 while (it.hasNext()) { String str = (String) it.next(); //獲取集合中元素 System.out.println(str); } //List List<String> list = new ArrayList<>(); list.add("a"); //添加元素 list.add("b"); list.add("c"); list.add("d"); list.remove(2); //移除元素 list.set(0, "h"); for (int j = 0; j < list.size(); j++) { System.out.println(list.get(j)); //h b d } //Set KPCollection sets1 = new KPCollection("Li", 004); KPCollection sets2 = new KPCollection("Chen", 002); KPCollection sets3 = new KPCollection("Wang", 003); KPCollection sets4 = new KPCollection("Ma", 001); TreeSet<KPCollection> tree = new TreeSet<>(); tree.add(sets1); tree.add(sets2); tree.add(sets3); tree.add(sets4); Iterator<KPCollection> its = tree.iterator(); its = tree.headSet(sets2).iterator(); //its = tree.subSet(sets2, sets3).iterator(); //its = tree.tailSet(sets3).iterator(); while (its.hasNext()) { KPCollection sets = (KPCollection) its.next(); System.out.println(sets.id + " " + sets.name); } //Map Map<String,String> map = new HashMap<>(); map.put("01", "Li"); map.put("02", "Wei"); Set<String> setm = map.keySet(); //key Iterator<String> itmk = setm.iterator(); while (itmk.hasNext()) { String str1 = (String) itmk.next(); String str2 = (String) map.get(str1); System.out.println(str1+" "+str2); } Collection<String> collm = map.values(); //value Iterator<String> itmv = collm.iterator(); while (itmv.hasNext()) { System.out.println(itmv.next()); } } }
四、枚舉和泛型
枚舉可以取代常量的定義方式,本質上還是以類的形式存在;泛型主要的作用是解決類型安全問題,可以提供編譯時的安全檢查。
/**********枚舉**********/ package com.kplayer.enums; public class KPEnums { enum FRUITS { APPLE("10"), ORANGE("20"), GRAPE("30"); private String price; public String getPrice(){ return price; } private FRUITS(){ //默認構造方法 } private FRUITS(String price){ //帶參構造方法 this.price = price; } } public static void compare(FRUITS f) { for (int i = 0; i < FRUITS.values().length; i++) { System.out.println(FRUITS.values()[i].ordinal() + "." + f + " compare to " + FRUITS.values()[i] + ":" + f.compareTo(FRUITS.values()[i])); //比較 System.out.println(FRUITS.values()[i] + " " + FRUITS.values()[i].getPrice()); } } //主方法 public static void main(String[] args) { compare(FRUITS.valueOf("ORANGE")); } }
/**********泛型**********/ package com.kpalyer.generic; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; //定義泛型時聲明數組類型 class ArrayClass<T> { private T[] array; //定義泛型數組 public void SetT(T[] array) { //SetT this.array = array; } public T[] getT() { //getT() return array; } } //集合類聲明容器的元素 class MutiOverClass<K, V> { public Map<K, V> m = new HashMap<K, V>(); //ArrayList<E>, HashSet<E>, Vector<E> public void put(K k, V v) { //put m.put(k, v); } public V get(K k) { //get() return m.get(k); } } //限制泛型可用類型 class LimitClass<T extends List> { //默認構造函數 } public class KPGeneric { public static void main(String[] args) { //定義泛型時聲明數組類型 ArrayClass<String> a = new ArrayClass<String>(); String[] array = { "mem1", "mem2", "mem3", "mem4", "mem5" }; a.SetT(array); //調用SetT()方法 for (int i = 0; i < a.getT().length; i++) { System.out.println(a.getT()[i]); //調用getT()方法 } //集合類聲明容器的元素 MutiOverClass<Integer, String> mu = new MutiOverClass<Integer, String>(); for (int i = 0; i < 5; i++) { mu.put(i, "mem" + i); //調用put()方法 } for (int i = 0; i < mu.m.size(); i++) { System.out.println(mu.get(i)); //調用getT()方法 } //限制泛型可用類型 LimitClass<ArrayList> l1 = new LimitClass<ArrayList>(); LimitClass<LinkedList> l2 = new LimitClass<LinkedList>(); //LimitClass<HashMap> l3 = new LimitClass<HashMap>(); //Bound mismatch } }
五、異常處理
/**********異常處理**********/ package com.kplayer.exceptions; //自定義異常 class MyException extends Exception { public MyException(String ErrorMessagr) { //構造方法 super(ErrorMessagr); //父類構造方法 } } public class KPException { //定義方法,拋出異常 static int avg(int number1, int number2) throws MyException { if (number1 < 0 || number2 < 0) { throw new MyException("Negative!"); } if (number1 > 100 || number2 > 100) { throw new MyException("Too Large!"); } return (number1 + number2) / 2; } public static void main(String[] args) { try { //預定義異常 int age = Integer.parseInt("20L"); // 數據類型轉換出錯 System.out.println(age); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("Exception Test 1 over"); } try { //自定義異常 int result = avg(102, 150); System.out.println(result); } catch (MyException e) { System.out.println(e); } finally { System.out.println("Exception Test 2 over"); } } }
六、反射
學會通過反射訪問構造方法/成員變量/成員方法,以及Annotation的定義和訪問。
/**********反射**********/ package com.kplayer.reflect; import java.lang.annotation.*; @Target(ElementType.CONSTRUCTOR) @Retention(RetentionPolicy.RUNTIME) public @interface Constructor_Annotation { String value() default "默認構造方法"; } package com.kplayer.reflect; import java.lang.annotation.*; @Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) public @interface Field_Method_Parameter_Annotation { String describe(); Class type() default void.class; } package com.kplayer.reflect; public class Record { @Field_Method_Parameter_Annotation(describe = "編號", type = int.class) int id; @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name; @Constructor_Annotation() public Record() { } @Constructor_Annotation("立即初始化構造方法") public Record( @Field_Method_Parameter_Annotation(describe = "編號", type = int.class) int id, @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name) { this.id = id; this.name = name; } @Field_Method_Parameter_Annotation(describe = "獲得編號", type = int.class) public int getId() { return id; } @Field_Method_Parameter_Annotation(describe = "設置編號") public void setId( @Field_Method_Parameter_Annotation(describe = "編號", type = int.class) int id) { this.id = id; } @Field_Method_Parameter_Annotation(describe = "獲得姓名", type = String.class) public String getName() { return name; } @Field_Method_Parameter_Annotation(describe = "設置姓名") public void setName( @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name) { this.name = name; } } package com.kplayer.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.annotation.*; class SimpleClass { private String s; protected int i, i2, i3; public double count; //構造方法 private SimpleClass() { } protected SimpleClass(String s, int i) { this.s = s; this.i = i; } public SimpleClass(String... strings) throws NumberFormatException { if (0 < strings.length) i = Integer.valueOf(strings[0]); if (1 < strings.length) i2 = Integer.valueOf(strings[1]); if (2 < strings.length) i3 = Integer.valueOf(strings[2]); } //成員方法 public double count(int count) { System.out.println("s=" + s + " i=" + i + " i2=" + i2 + " i3=" + i3); try{ this.count = i*0.1 + i2*0.2 + i3*0.3 + count; } catch(Exception e){ e.printStackTrace(); } return this.count; } } public class KPReflect { public static void main(String[] args) { SimpleClass example = new SimpleClass("10", "20", "30"); Class<? extends SimpleClass> exampleC = example.getClass(); //訪問構造方法 Constructor[] declaredConstructors = exampleC.getDeclaredConstructors(); for (int i = 0; i < declaredConstructors.length; i++) { Constructor<?> constructor = declaredConstructors[i]; //遍歷構造方法 //是否參數數量可變 System.out.println("isVarArgs=" + constructor.isVarArgs()); //參數類型 System.out.println("getParameterTypes="); Class[] parameterTypes = constructor.getParameterTypes(); for (int j = 0; j < parameterTypes.length; j++) { System.out.println(" " + parameterTypes[j]); } //異常類型 System.out.println("getExceptionTypes="); Class[] exceptionTypes = constructor.getExceptionTypes(); for (int j = 0; j < exceptionTypes.length; j++) { System.out.println(" " + exceptionTypes[j]); } System.out.println(); } //訪問成員變量 Field[] declaredFields = exampleC.getDeclaredFields(); for (int i = 0; i < declaredFields.length; i++) { Field field = declaredFields[i]; //遍歷成員變量 //變量名稱 System.out.println("varName=" + field.getName()); //變量類型 Class fieldType = field.getType(); System.out.println("varType=" + fieldType); } System.out.println(); //訪問成員方法 Method[] declaredMethods = exampleC.getDeclaredMethods(); for (int i = 0; i < declaredMethods.length; i++) { Method method = declaredMethods[i]; // 遍歷方法 System.out.println("methodName" + method.getName()); // 獲得方法名稱 //方法是否參數數量可變 System.out.println("method.isVarArgs=" + method.isVarArgs()); //獲得方法所有參數類型 System.out.println("method.getParameterTypes="); Class[] parameterTypes = method.getParameterTypes(); for (int j = 0; j < parameterTypes.length; j++) { System.out.println(" " + parameterTypes[j]); } //獲得方法返回值類型 System.out.println("method.getReturnType=" + method.getReturnType()); //獲得方法可能拋出的所有異常類型 System.out.println("method.getExceptionTypes="); Class[] exceptionTypes = method.getExceptionTypes(); for (int j = 0; j < exceptionTypes.length; j++) { System.out.println(" " + exceptionTypes[j]); } } /**********Annotation**********/ Class recordC = null; try { recordC = Class.forName("com.kplayer.reflect.Record"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println("------ 構造方法的描述如下 ------"); Constructor[] declaredConstructors2 = recordC .getDeclaredConstructors(); // 獲得所有構造方法 for (int i = 0; i < declaredConstructors2.length; i++) { Constructor constructor = declaredConstructors2[i]; // 遍歷構造方法 // 查看是否具有指定類型的注釋 if (constructor .isAnnotationPresent(Constructor_Annotation.class)) { // 獲得指定類型的注釋 Constructor_Annotation ca = (Constructor_Annotation) constructor .getAnnotation(Constructor_Annotation.class); System.out.println(ca.value()); // 獲得注釋信息 } Annotation[][] parameterAnnotations = constructor .getParameterAnnotations(); // 獲得參數的注釋 for (int j = 0; j < parameterAnnotations.length; j++) { // 獲得指定參數注釋的長度 int length = parameterAnnotations[j].length; if (length == 0) // 如果長度為0則表示沒有為該參數添加注釋 System.out.println(" 未添加Annotation的參數"); else for (int k = 0; k < length; k++) { // 獲得參數的注釋 Field_Method_Parameter_Annotation pa = (Field_Method_Parameter_Annotation) parameterAnnotations[j][k]; System.out.print(" " + pa.describe()); // 獲得參數描述 System.out.println(" " + pa.type()); // 獲得參數類型 } } System.out.println(); } System.out.println(); System.out.println("-------- 字段的描述如下 --------"); Field[] declaredFields2 = recordC.getDeclaredFields(); // 獲得所有字段 for (int i = 0; i < declaredFields2.length; i++) { Field field = declaredFields2[i]; // 遍歷字段 // 查看是否具有指定類型的注釋 if (field .isAnnotationPresent(Field_Method_Parameter_Annotation.class)) { // 獲得指定類型的注釋 Field_Method_Parameter_Annotation fa = field .getAnnotation(Field_Method_Parameter_Annotation.class); System.out.print(" " + fa.describe()); // 獲得字段的描述 System.out.println(" " + fa.type()); // 獲得字段的類型 } } System.out.println(); System.out.println("-------- 方法的描述如下 --------"); Method[] methods = recordC.getDeclaredMethods(); // 獲得所有方法 for (int i = 0; i < methods.length; i++) { Method method = methods[i]; // 遍歷方法 // 查看是否具有指定類型的注釋 if (method .isAnnotationPresent(Field_Method_Parameter_Annotation.class)) { // 獲得指定類型的注釋 Field_Method_Parameter_Annotation ma = method .getAnnotation(Field_Method_Parameter_Annotation.class); System.out.println(ma.describe()); // 獲得方法的描述 System.out.println(ma.type()); // 獲得方法的返回值類型 } Annotation[][] parameterAnnotations = method .getParameterAnnotations(); // 獲得參數的注釋 for (int j = 0; j < parameterAnnotations.length; j++) { int length = parameterAnnotations[j].length; // 獲得指定參數注釋的長度 if (length == 0) // 如果長度為0表示沒有為該參數添加注釋 System.out.println(" 未添加Annotation的參數"); else for (int k = 0; k < length; k++) { // 獲得指定類型的注釋 Field_Method_Parameter_Annotation pa = (Field_Method_Parameter_Annotation) parameterAnnotations[j][k]; System.out.print(" " + pa.describe()); // 獲得參數的描述 System.out.println(" " + pa.type()); // 獲得參數的類型 } } System.out.println(); } } }
七、多線程
掌握實現線程的兩種方式,以及線程的生命周期,優先級,及同步機制。
/**********多線程**********/ package com.kplayer.thread; class KPThread extends Thread { //繼承Thread類 private int count = 10; public synchronized void doit(){ //同步方法 if(count > 0){ try { Thread.sleep(100); //線程休眠 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("count" + count--); } } public void run() { //重寫 while (true) { doit(); } } } class KPRunnable implements Runnable{ //實現Runnable接口 int count = 10; public void run() { //重寫 while (true) { synchronized(""){ //同步塊 if(count > 0){ try { Thread.sleep(100); //線程休眠 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("count" + count--); } } } } } public class KPMultiThread{ private Thread t1; private Thread t2; //匿名內部類 public KPMultiThread(){ t1 = new Thread(new Runnable() { int count = 21; public void run() { while (true) { try { Thread.sleep(1000); //線程休眠 t2.join(); //線程加入 } catch (InterruptedException e) { e.printStackTrace(); } System.out.print(count+" "); if (++count == 30) { System.out.print(count+"\n"); return; } } } }); t1.start(); t2 = new Thread(new Runnable() { int count = 31; public void run() { while (true) { try { Thread.sleep(1000); //線程休眠 } catch (InterruptedException e) { e.printStackTrace(); } System.out.print(count+" "); if (++count == 40) { System.out.print(count+"\n"); return; } } } }); t2.start(); } public static void main(String[] args) { //繼承Thread類 KPThread tt = new KPThread(); tt.start(); //實現Runnable接口 Thread tr1 = new Thread(new KPRunnable()); Thread tr2 = new Thread(new KPRunnable()); Thread tr3 = new Thread(new KPRunnable()); tr1.setPriority(3); //線程優先級 tr2.setPriority(2); tr3.setPriority(1); tr1.start(); tr2.start(); tr3.start(); //線程安全 KPRunnable tr = new KPRunnable(); Thread tr4 = new Thread(tr); Thread tr5 = new Thread(tr); Thread tr6 = new Thread(tr); tr4.start(); tr5.start(); tr6.start(); //線程休眠/加入 KPMultiThread mt = new KPMultiThread(); } }
注:部分代碼來源於《Java從入門到精通(第3版)》——清華大學出版社
