国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

Java筆記——2017年3月3日

2019-11-06 07:37:07
字體:
供稿:網(wǎng)友

java的發(fā)展

Java1.0 Java1.1Java 1.2(Java2 將Java分為J2SE,J2EE,J2ME)Java 1.3Java 1.4Java 5.0(將分成三個(gè)版本,改名為JavaSE,JavaEE,JavaME)Java 6.0Java 7.0Java 8.0

Java數(shù)據(jù)類型

  Java數(shù)據(jù)類型有兩大種:引用數(shù)據(jù)類型原始數(shù)據(jù)類型。   引用數(shù)據(jù)類型:interface、class、Array、enum   原始數(shù)據(jù)類型:byte(字節(jié))、short(短整型)、int(整數(shù)型)、long(長(zhǎng)整型)、float(單精度浮點(diǎn)數(shù)類型)、double(雙精度浮點(diǎn)數(shù)類型)、char(字符類型)、boolean(布爾類型)總共8種。

Java Switch可接受的數(shù)據(jù)類型

  在JDK5中,switch可以接受五種數(shù)據(jù)類型:byte、short、int、char、enum。   在JDK7中,switch可以接受六種數(shù)據(jù)類型:多了一種String。

Java提高擴(kuò)展性

  將做什么(interface)和怎么做分開(實(shí)現(xiàn))。

JDK 5.0新特性

一、泛型Generic

泛型的由來

  JDK5之前,對(duì)象保存到集合中就會(huì)失去其特性,取出的時(shí)候通常需要程序猿手工進(jìn)行類型的強(qiáng)制轉(zhuǎn)化,這樣不可避免的就會(huì)引發(fā)程序的一些安全性問題。   眾所周知,Java的開發(fā)者是一批C++工程師。在C++的語法中,有一門模板技術(shù)。事實(shí)上,Java5.0的泛型本質(zhì)上就是C++的模板。

JDK5之前集合對(duì)象存在的問題

可以向集合添加任何類型對(duì)象;

從集合取出對(duì)象的時(shí)候,數(shù)據(jù)類型丟失。取出的時(shí)候,需要使用與類型相關(guān)方法,進(jìn)行強(qiáng)制類型轉(zhuǎn)換操作。

程序是存在安全隱患。

  比如下面的例子:

/** * 泛型測(cè)試 * */public class GenericTest { @Test public void demo1() { // JDK5之前集合對(duì)象 List list = new ArrayList(); // 因?yàn)镴DK5之前沒有泛型的類型檢查,添加的對(duì)象可以是任意類型 list.add("abc"); list.add(123); // 操作集合中對(duì)象,遍歷集合將數(shù)據(jù)取出來通過size()方法和get(index)方法 // 進(jìn)行類型的判斷處理 for (int i = 0; i < list.size(); i++) { // 提取對(duì)象的時(shí)候,數(shù)據(jù)類型丟失了 Object obj = list.get(i); // 操作String方法 -- 強(qiáng)制將數(shù)據(jù)轉(zhuǎn)換成響應(yīng)類型 String s = (String) obj; System.out.PRintln(s.toUpperCase()); } }}

  Java會(huì)報(bào)錯(cuò):

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String(Integer 類型不能轉(zhuǎn)化為String類型)

  在這里,我們將上述代碼放在main函數(shù)中進(jìn)行javac編譯

public class GenericTest { public static void main(String[] args) { // JDK5之前集合對(duì)象 List list = new ArrayList(); // 因?yàn)镴DK5之前沒有泛型的類型檢查,添加的對(duì)象可以是任意類型 list.add("abc"); list.add(123); // 操作集合中對(duì)象,遍歷集合將數(shù)據(jù)取出來通過size()方法和get(index)方法 // 進(jìn)行類型的判斷處理 for (int i = 0; i < list.size(); i++) { // 提取對(duì)象的時(shí)候,數(shù)據(jù)類型丟失了 Object obj = list.get(i); // 操作String方法 -- 強(qiáng)制將數(shù)據(jù)轉(zhuǎn)換成響應(yīng)類型 String s = (String) obj; System.out.println(s.toUpperCase()); } }}

  在cmd中javac編譯會(huì)出現(xiàn)以下錯(cuò)誤提示:

D:/Java/Workspaces/MyEclipse 2015/day03/src/cn/idcast/jdk5>javac -Xlint:unchecked GenericTest.javaGenericTest.java:53: 警告: [unchecked] 對(duì)作為原始類型List的成員的add(E)的調(diào)用未經(jīng)過檢查 list.add("abc"); ^ 其中, E是類型變量: E擴(kuò)展已在接口 List中聲明的ObjectGenericTest.java:54: 警告: [unchecked] 對(duì)作為原始類型List的成員的add(E)的調(diào)用未經(jīng)過檢查 list.add(123); ^ 其中, E是類型變量: E擴(kuò)展已在接口 List中聲明的Object2 個(gè)警告

泛型的作用

類型安全檢查編寫通用的Java程序(Java框架)

  JDK5中的泛型允許程序猿使用泛型技術(shù)限制集合的處理類型。

List list = new ArrayList<String>();

  注意:泛型是提供給javac編譯器使用的,他用于限定集合的輸入類型,讓編譯器在源代碼級(jí)別上,即擋住喜愛那個(gè)集合中插入非法數(shù)據(jù)。但編譯器編譯完帶有泛型的java程序之后,生成的class文件中將不在帶有泛型信息,以此使程序運(yùn)行效率不受到影響,這個(gè)過程稱之為“擦除”。   泛型技術(shù),其實(shí)只是編譯器階段技術(shù),為javac命令起到了類型安全檢查的作用,生成.class文件后,泛型信息將會(huì)被擦除。   泛型的基本術(shù)語,以ArrayList< E >為例:<> 念著typeof

ArrayList< E >中的E稱為類型參數(shù)變量ArrayList< Interger >中的Integer稱為實(shí)際類型參數(shù)整個(gè)ArrayList< Interger >稱為參數(shù)化類型ParameterizedTypeList< String >稱為參數(shù)化類型

泛型語法

  List < 泛型類型> 規(guī)定了List集合中的元素類型,取出集合中的元素的時(shí)候,獲得具體數(shù)據(jù)類型元素(不需要進(jìn)行類型強(qiáng)制轉(zhuǎn)換)。

使用類型安全的List

  使用類型安全的List并將List中的元素用三種不同的方式輸出。

@Testpublic void demo3() { // 使用類型的List List<String> list = new LinkedList<String>(); list.add("abc"); list.add("qwe"); list.add("asd"); // 因?yàn)槭褂梅盒?,只能將list添加String類型元素 // 遍歷List --三種方案 // 第一種是因?yàn)長(zhǎng)ist是有序的(存入順序和取出順序是一樣的),通過size和get方法進(jìn)行遍歷 for (int i = 0; i < list.size(); i++) { String str = list.get(i); System.out.println(str); } System.out.println("--------------------------"); // 第二種因?yàn)長(zhǎng)ist繼承了Collection接口通過Collection的iterator進(jìn)行遍歷 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String str = iterator.next(); System.out.println(str); } System.out.println("--------------------------"); // 第三種 JDK5引入了foreach循環(huán)結(jié)構(gòu),通過foreach結(jié)構(gòu)遍歷list for (String str : list) { System.out.println(str); } System.out.println("--------------------------");}

  輸出結(jié)果:

abcqweasd--------------------------abcqweasd--------------------------abcqweasd--------------------------

使用類型安全的Set

  使用類型安全的Set并將Set中的元素用兩種不同的方式輸出。

@Testpublic void demo4() { // 使用類型安全的Set Set<String> set = new TreeSet<String>(); set.add("qwe"); set.add("asd"); set.add("zxc"); // 因?yàn)槭褂梅盒?,只能添加String類型元素 // 取出Set元素 -- 因?yàn)镾et是無序的,所以比List少一種遍歷方法 // 第一種,繼承Collection 所以使用Iterator遍歷 Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { String str = iterator.next(); System.out.println(str); } System.out.println("--------------------------"); // 第二種,由于JDK5引入了foreach 可以使用foreach遍歷set for (String str : set) { System.out.println(str); }}

  輸出結(jié)果:

asdqwezxc--------------------------asdqwezxc

使用類型安全的Map

  使用類型安全的Map并將Map中的元素用兩種不同的方式輸出。

@Testpublic void demo5() { // 使用類型安全的Map,因?yàn)镸ap是一個(gè)鍵值對(duì)結(jié)構(gòu),執(zhí)行兩個(gè)類型泛型 Map<String,String> map = new HashMap<String, String>(); map.put("aaa","111"); map.put("sss", "222"); map.put("ddd", "333"); // 因?yàn)槭褂昧朔盒?,所以key和value類型必須是String // 取出map元素 -- 兩種方法 // 第一種 通過map中的keySet進(jìn)行遍歷 Set<String> keys = map.keySet(); for (String key : keys) { System.out.println(key + ":" + map.get(key)); } System.out.println("--------------------------"); // 第二種 通過map的entrySet ---- 獲得每一個(gè)鍵值對(duì) Set<Map.Entry<String, String>> entrySet = map.entrySet(); // 就是一個(gè)鍵值對(duì) for (Entry<String, String> entry : entrySet) { // 通過entry的getkey和getValue獲得每一個(gè)鍵和值 System.out.println(entry.getKey() + ":" + entry.getValue()); }}

  輸出結(jié)果:

aaa:111ddd:333sss:222--------------------------aaa:111ddd:333sss:222

自定義范型

1.定義泛型方法,必須在方法的返回值之前進(jìn)行泛型類型聲明 < 泛型類型 >

@Testpublic void demo6() { Integer[] arr1 = new Integer[] { 1, 2, 3, 4, 5 }; changePostion(arr1, 0, 2); System.out.println(Arrays.toString(arr1));}// 使用泛型技術(shù)編寫通用的數(shù)組位置交換代碼public <T> void changePostion(T[] arr, int index1, int index2) { T temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp;}

2.自定義泛型類,如果一個(gè)類多處要用到同一個(gè)泛型,這時(shí)可以把泛型定義在類上(即類級(jí)別的泛型),語法格式如下:

public class GenericDao<T> { private T field1; public void save (T obj) {} public T getId(int id) {}}

  當(dāng)類的泛型使用后,該類中所有方法都可以直接使用泛型。   對(duì)應(yīng)泛型類型參數(shù)的起名可以是任何大寫字母,但是建議使用有意義的字母來命名。   注意:類的泛型不對(duì)static起作用。

泛型高級(jí)應(yīng)用之通配符

泛型:代表了任意類型; ?:任意泛型類型。

泛型通配符?的使用:

@Testpublic void demo7() { // 使用類型的List List<String> list = new LinkedList<String>(); list.add("abc"); list.add("qwe"); list.add("asd"); print(list); System.out.println("---------------------"); // 使用類型的List List<Integer> list1 = new LinkedList<Integer>(); list1.add(123); list1.add(234); list1.add(345); print(list1);}// 泛型通配符——? 代表任意類型// 泛型類型可以是任何類型的private void print(List<?> list) { for (Object str : list) { System.out.println(str); }}當(dāng)使用了通配符了后,不要使用和類型相關(guān)方法。

上下邊界

  通過上下邊界,限制通配符類型范圍:

  ? extends Number :表示Number(包含Number)的任意子類型。   ?super String :表示String(包含String)的任意父類型。


注意: 上下邊界不能同時(shí)使用。 即不存在 :?extends Object super Integer
@Testpublic void demo8() { List<?> list = new ArrayList<String>(); // list.add("qwer"); // list.add(123); // 報(bào)錯(cuò),當(dāng)使用了通配符了后,不要使用和類型相關(guān)方法。 List<? extends Number> list1 = new ArrayList<Integer>(); List<? super String> list2 = new ArrayList<String>();}

上下邊界的應(yīng)用

范例一   比如在Set中的addAll(Collection< ? extends E > c) 方法。   Set中addAll(Collection< ? extends E > c) 表示將目標(biāo)集合c的內(nèi)容添加到當(dāng)前set中,? extends E表示目標(biāo)集合是E的子類型。

Set< Number > set = new HashSet< Number >();List< Integer > list = new ArrayList< Integer >();set.addAll(list); // list 中 Integer 自動(dòng)轉(zhuǎn)換為 Number

范例二

  比如在TreeSet中的構(gòu)造方法:TreeSet(Comparator< ? super E > comparator)

// 默認(rèn)需要蘋果比較器排序,但是我們?nèi)鄙貯pple比較器,所以我們需要自定義一個(gè)Set< Apple > set = new TreeSet< Apple >(); class FruitComparator implements Comparator< Fruit > { ......}// 需要Apple比較器 ,傳入 Fruit比較器。// 因?yàn)槟鼙容^水果的比較器,那么也能比較AppleSet< Apple > set = new TreeSet< Apple >(new FruitComparator());

總結(jié)

泛型用來在編譯階段對(duì)集合對(duì)象進(jìn)行類型安全檢查 需要掌握類型安全的遍歷List、Set、Map中元素泛型技術(shù)集合反射編寫通用Java程序 定義通過數(shù)組交換位置方法泛型的通配符和上下邊界 在Java API中有很多應(yīng)用,了解即可

二、枚舉

為什么需要枚舉?

  因?yàn)橐恍┓椒ㄔ谶\(yùn)行的時(shí)候,他需要的數(shù)據(jù)不能是任意的,而必須是一定范圍內(nèi)的值,此類問題在JDK5以前采用自定義帶有枚舉功能的類解決,Java5之后可以直接使用枚舉予以解決。   JDK5新增的enum關(guān)鍵字用于定義一個(gè)枚舉類。   創(chuàng)建枚舉格式:   enum 枚舉類型名稱 {     枚舉對(duì)象名稱1,     枚舉對(duì)象名稱2,     ……     枚舉對(duì)象名稱n;  ?。?  作用:可讀性良好,阻止非法數(shù)據(jù)。

枚舉的由來

  最初Java是沒有枚舉的。   1.第一個(gè)版本之String類型

employee.role1 = "BOSS";employee.role1 = "MANAGE";// 因?yàn)榻巧且粋€(gè)String// 如果經(jīng)理字符拼錯(cuò)了,程序就會(huì)出現(xiàn)問題employee.role1 = "WORKER";

  這個(gè)版本的確定就是字符可能輸錯(cuò),到時(shí)程序出錯(cuò)。當(dāng)變量過于大的時(shí)候,管理難度大,出錯(cuò)率高。   2.第一個(gè)版本之int類型

employee.role2 = 1;// 可讀性太差了employee.role2 = 4;// 非法數(shù)據(jù)

  比如上述形式的變量,這種方法具有可讀性差,無法阻止非法數(shù)據(jù)的缺點(diǎn)。   3.第二個(gè)版本之自定義類實(shí)現(xiàn)枚舉

class Role3 { public static final Role3 BOSS = new Role3(); public static final Role3 MANAGER = new Role3(); public static final Role3 WORKER = new Role3(); // 私有構(gòu)造方法,組織非法數(shù)據(jù) private Role3() { }}

  提高了可讀性,阻止了非法的初始化。   4.JDK5引入了enum

enum Role4 { // JDK5 以后引用枚舉技術(shù) 簡(jiǎn)化對(duì)象創(chuàng)建 ---- 功能等價(jià)于 Role3 BOSS, MANAGER, WORKER;}

  事實(shí)上,enum類是于構(gòu)造Role3。Enum主要的作用是簡(jiǎn)化了對(duì)象的創(chuàng)建……   注意:枚舉類構(gòu)造器,必須是私有的(private)。

package cn.idcast.jdk5;public class EnumTest {}  全部代碼:/** * 假如我們需要定義一個(gè)角色屬性(公司內(nèi)角色只有三種:BOSS,MANAGER,WORKER) 定義員工角色, * 在三個(gè)值中取一個(gè) * 1 BOSS 2 MANAGE 3 WORKER * */class Employee { private String role1; private int role2; // 在JDK5之前,沒有枚舉,只能通過自定義類,實(shí)現(xiàn)枚舉功能 private Role3 role3; // 在JDK5之后,引入了枚舉,使用枚舉表示多個(gè)角色 private Role4 role4; public static void main(String[] args) { Employee employee = new Employee(); employee.role1 = "BOSS"; employee.role1 = "MANAGE"; // 因?yàn)榻巧且粋€(gè)String // 如果經(jīng)理字符拼錯(cuò)了,程序就會(huì)出現(xiàn)問題 employee.role1 = "WORKER"; // --------------------------- employee.role2 = 1;// 可讀性太差了 employee.role2 = 4;// 非法數(shù)據(jù) // --------------------------- // 定義Role2類,定義一組int常量,用來表示角色 employee.role2 = Role2.BOSS; // 可讀性大大提高了 employee.role2 = -1; // 非法數(shù)據(jù) // --------------------------- // 通過自定義Role3實(shí)現(xiàn)枚舉功能 employee.role3 = Role3.BOSS; // employee.role3 = new Role3(); // 數(shù)據(jù) 非法 // 使用枚舉之后 employee.role4 = Role4.BOSS;// 可讀性良好,阻止非法數(shù)據(jù)、 // employee.role4 = new Role4(); // 私有構(gòu)造方法,從這里可以看出在enum中的構(gòu)造方法也是private的 }}class Role2 { public static final int BOSS = 1; public static final int MANAGER = 2; public static final int WORKER = 3;}class Role3 { public static final Role3 BOSS = new Role3(); public static final Role3 MANAGER = new Role3(); public static final Role3 WORKER = new Role3(); // 私有構(gòu)造方法,組織非法數(shù)據(jù) private Role3() { }}enum Role4 { // JDK5 以后引用枚舉技術(shù) 簡(jiǎn)化對(duì)象創(chuàng)建 ---- 功能等價(jià)于 Role3 BOSS, MANAGER, WORKER;}

枚舉類的特性

枚舉類也是一種特殊形式的Java類枚舉類中聲明的每一個(gè)枚舉值代表枚舉類的一個(gè)實(shí)例對(duì)象,也就是說每一個(gè)枚舉值,在編譯為.class文件的時(shí)候,都會(huì)成為枚舉成員對(duì)象(常量)與Java中的普通類一樣,在聲明枚舉類的時(shí)候,也可以聲明屬性、方法和構(gòu)造函數(shù),但是枚舉類的構(gòu)造函數(shù)必須是私有的枚舉類也可以實(shí)現(xiàn)接口,或者繼承抽象類JDK5中擴(kuò)展switch語句,它除了可以接收int,byte,char,short外,還可以接收一個(gè)枚舉類型若枚舉類只有一個(gè)枚舉值,則可以當(dāng)作單態(tài)設(shè)計(jì)模式使用

單例設(shè)計(jì)模式的寫法

  單例設(shè)計(jì)模式須包含以下內(nèi)容:   1、私有構(gòu)造器   2、private static成員對(duì)象   3、public static獲得成員對(duì)象的方法

/** * 單例設(shè)計(jì)模式,強(qiáng)調(diào)一個(gè)類只能有一個(gè)示例 * */public class SingletonTest {}enum A { Test; // 該枚舉中只有TRST實(shí)例,相當(dāng)于**單例**。}class B { // 1. 私有構(gòu)造器 private B() { } // 2.private static 成員對(duì)象 private static B b = new B(); // 3.提供public static 獲得成員方法,獲得唯一的成員對(duì)象 public static B getInstance() { return b; }}

餓漢式

定義:   在創(chuàng)建對(duì)象的時(shí)候,直接進(jìn)行初始化。   如上面的單例設(shè)計(jì)模式的例子,就是餓漢式。

class B { // 1. 私有構(gòu)造器 private B() { } // 2.private static 成員對(duì)象 private static B b = new B(); // 3.提供public static 獲得成員方法,獲得唯一的成員對(duì)象 public static B getInstance() { return b; }}

懶漢式

定義:   在獲取對(duì)象的時(shí)候,進(jìn)行初始化。

// 懶漢式class C { // 1. 私有構(gòu)造器 private C() { } // 2.private static 成員對(duì)象 private static C c; // 3.提供public static 獲得成員方法,獲得唯一的成員對(duì)象 public static C getInstance() { if (c == null) { c = new C();// 標(biāo)準(zhǔn)的懶漢式 } return c; }}

枚舉高級(jí)應(yīng)用

  在枚舉實(shí)例定義過程中,向枚舉構(gòu)造器傳入?yún)?shù),通過匿名內(nèi)部類實(shí)現(xiàn)枚舉中抽象方法。

/** * 定義特殊結(jié)構(gòu)的枚舉 * */public enum EnumConstructorTest { // 創(chuàng)建枚舉值的時(shí)候,傳入構(gòu)造方法參數(shù) A(20) { @Override public void show() { // TODO Auto-generated method stub } }, B(30) { @Override public void show() { // TODO Auto-generated method stub } }; // 構(gòu)造方法,帶有參數(shù) private EnumConstructorTest(int a) { } public String toSting() { return super.toString(); } public void print() { System.out.println("Test"); } // 抽象方法 public abstract void show();}

  應(yīng)用舉例(包含兩種寫法):

public class WeekDayTest { public static void main(String[] args) { Weekday day = Weekday.Wed; day.show(); Weekdayabs dayabs = Weekdayabs.Fri; dayabs.show(); }}enum Weekday { Mon, Tue, Wed, Thu, Fri, Sat, Sun; // 編寫方法show public void show() { // 根據(jù)枚舉對(duì)象名字返回中文的的星期數(shù) if (this.name().equals("Mon")) { System.out.println("星期一"); } else if (this.name().equals("Tue")) { System.out.println("星期二"); } else if (this.name().equals("Wed")) { System.out.println("星期三"); } else if (this.name().equals("Thu")) { System.out.println("星期四"); } else if (this.name().equals("Fri")) { System.out.println("星期五"); } else if (this.name().equals("Sat")) { System.out.println("星期六"); } else if (this.name().equals("Sun")) { System.out.println("星期日"); } }}enum Weekdayabs { Mon{ @Override public void show() { // TODO Auto-generated method stub System.out.println("星期一"); } }, Tue { @Override public void show() { // TODO Auto-generated method stub System.out.println("星期二"); } }, Wed { @Override public void show() { // TODO Auto-generated method stub System.out.println("星期三"); } }, Thu { @Override public void show() { // TODO Auto-generated method stub System.out.println("星期四"); } }, Fri { @Override public void show() { // TODO Auto-generated method stub System.out.println("星期五"); } }, Sat { @Override public void show() { // TODO Auto-generated method stub System.out.println("星期六"); } }, Sun { @Override public void show() { // TODO Auto-generated method stub System.out.println("星期日"); } }; // 編寫方法show public abstract void show();}

枚舉類API

Java中聲明的枚舉類,均是java.lang.Enum類的孩子,它繼承了Enum類的所有方法。常用方法: name():返回枚舉對(duì)象名稱ordinal():返回枚舉對(duì)象下標(biāo)valueof(Class enumClass,String name):轉(zhuǎn)換枚舉對(duì)象(將String類型枚舉對(duì)象名稱,轉(zhuǎn)換為對(duì)應(yīng)Class類型對(duì)象)自定義的枚舉類,在Javac編譯階段自動(dòng)生成下面兩個(gè)新的方法 valueof(String name):轉(zhuǎn)換枚舉對(duì)象(將String類型枚舉名稱轉(zhuǎn)換為枚舉對(duì)象)values():獲得所有枚舉對(duì)象數(shù)組public class EnumAPITest { @Test // 枚舉對(duì)象,枚舉對(duì)象下標(biāo)、枚舉對(duì)象名稱表示之間的轉(zhuǎn)換 public void demo2() { // 第一種:已知枚舉對(duì)象,獲得下標(biāo)和名稱 Color blue = Color.BLUE; // 獲得下標(biāo) System.out.println(blue.ordinal()); // 獲得名稱 System.out.println(blue.name()); System.out.println("------------------"); // 第二種,已知枚舉對(duì)象下標(biāo),獲得枚舉對(duì)象實(shí)例和名稱 int index = 1; // 獲得枚舉對(duì)象 Color red = Color.values()[index]; System.out.println(red.name()); System.out.println("------------------"); // 第三種,已知枚舉對(duì)象名稱,獲得枚舉對(duì)象實(shí)例和下標(biāo) String name = "YELLOW"; // 獲得實(shí)例 Color c1 = Enum.valueOf(Color.class, name); Color c2 = Color.valueOf(name); // 獲得下標(biāo) System.out.println(c1.ordinal()); System.out.println(c2.ordinal()); } @Test public void demo1() { // 任何enum定義枚舉類都是默認(rèn)繼承Enum類,使用Enum中方法 // 枚舉對(duì)象不能使用new獲得,使用已經(jīng)創(chuàng)建好的對(duì)象 Color color = Color.RED; // name 方法返回枚舉實(shí)例名稱 System.out.println(color.name()); // ordinal 方法返回枚舉對(duì)象下標(biāo) System.out.println(color.ordinal()); // valueOf 將String類型枚舉對(duì)象名稱 --轉(zhuǎn)換為相應(yīng)枚舉對(duì)象 String name = "YELLOW"; Color yellow = Enum.valueOf(Color.class, name);// 將name 轉(zhuǎn)換成響應(yīng)枚舉對(duì)象 System.out.println(yellow.ordinal()); // 使用枚舉類編譯后生成兩個(gè)方法 // values 獲得所有枚舉對(duì)象數(shù)組 Color[] colors = Color.values(); System.out.println(Arrays.toString(colors)); // 生成valuOf,只接受String類型枚舉名稱,將名稱轉(zhuǎn)換成當(dāng)前枚舉類對(duì)象 String name2 = "BLUE"; Color blue = Color.valueOf(name2); System.out.println(blue.ordinal()); }}

三、靜態(tài)導(dǎo)入

  JDK1.5增加的靜態(tài)導(dǎo)入語法用于導(dǎo)入類的某個(gè)靜態(tài)屬性或方法。   使用靜態(tài)導(dǎo)入(staitc import)可以簡(jiǎn)化程序?qū)︻愳o態(tài)屬性和方法的調(diào)用。   語法:     Import staic 包名,類名,靜態(tài)屬性|靜態(tài)方法|*   例如:     Import static java.lang.System.out;     Import static java.util.Arrays.sort;     Import static java.lang.Math.*;   缺點(diǎn):     雖然靜態(tài)導(dǎo)入可以簡(jiǎn)化編程,但是靜態(tài)導(dǎo)入后的代碼的可讀性差。并且當(dāng)導(dǎo)入了沖突方法的時(shí)候,靜態(tài)導(dǎo)入將不可用(報(bào)錯(cuò))。

import java.util.Arrays;import static java.util.Arrays.sort;/** * 靜態(tài)導(dǎo)入 * */public class StaticImportTest { public static void main(String[] args) { int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; // 對(duì)數(shù)據(jù)進(jìn)行排序 /** * 因?yàn)樵陬惿戏酵ㄟ^靜態(tài)導(dǎo)入引用Arrays.sort,所以可以直接sort * */ sort(arr);// 這里的sort是Arrays的靜態(tài)方法 // 注意:靜態(tài)導(dǎo)入Arrays.toString是會(huì)報(bào)錯(cuò)的,因?yàn)楹捅镜氐膖oString發(fā)生了沖突了 System.out.println(Arrays.toString(arr)); } @Override public String toString() { // TODO Auto-generated method stub return super.toString(); }}

四、自動(dòng)裝箱/拆箱

  JDK5.0的語法允許開發(fā)人員把一個(gè)基本數(shù)據(jù)類型直接賦給對(duì)應(yīng)的包裝類變量,或者賦給Object類型的變量,這個(gè)過程稱之為自動(dòng)裝箱。   自動(dòng)拆箱和自動(dòng)裝箱與之相法,即把包裝類對(duì)象直接賦給一個(gè)對(duì)應(yīng)的基本類型變量。   典型應(yīng)用:

import org.junit.Test;/** * 自動(dòng)裝箱和拆箱 * */public class AutoBoxingTest { @Test public void demo1() { // 在JDK5之后將原始數(shù)據(jù)類型轉(zhuǎn)換為包裝類類型稱之為自動(dòng)裝箱。 Integer i = 10;// 編譯器將int轉(zhuǎn)換成Integer // 在JDK5之后將封裝類類型轉(zhuǎn)換為原始數(shù)據(jù)類型稱之為自動(dòng)拆箱。 int n = i;// 編譯器自動(dòng)將Integer轉(zhuǎn)換為int。 // 測(cè)試方法,將編譯的JDK版本調(diào)為JDK1.5以下版本即可。將會(huì)報(bào)錯(cuò): // Type mismatch:cannot convert from Integer to int } @Test public void demo2() { // JDK5之前如何進(jìn)行原始數(shù)據(jù)類型和包裝類類型轉(zhuǎn)換? int m = 10; // 如何將int轉(zhuǎn)換為Integer Integer i = new Integer(m); // 如何將Integer轉(zhuǎn)換為int int n = i.intValue(); }}

典型案例   看下列代碼,思考代碼結(jié)果:

@Testpublic void demo3() { int i = 10; doSomething(i);}public void doSomething(double d) { System.out.println("double 參數(shù)");}public void doSomething(Integer d) { System.out.println("Integer 參數(shù)");}

說明:

/*** 注意:這個(gè)方法將會(huì)執(zhí)行double參數(shù)的方法* 原因:因?yàn)橐嫒軯DK1.4的執(zhí)行效果,所以將會(huì)調(diào)用double的方法* */

五、for/in語句(foreach)

引入增強(qiáng)for循環(huán)的原因

  替換Iterator的復(fù)雜寫法,本質(zhì)就是Iterator。

foreach語句的主要作用

遍歷數(shù)組遍歷Collection集合對(duì)象import java.util.Iterator;import java.util.List;import java.util.ArrayList;import org.junit.Test;/** * for in語句 * */public class ForInTest { @Test public void demo1() { List<String> list = new ArrayList<String>(); list.add("qwer"); list.add("asdf"); list.add("zxcv"); // 在JDK5之前有兩種遍歷方式:通過下標(biāo)遍歷,通過iterator Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println("----------------"); for (Iterator<String> iterator2 = list.iterator(); iterator2.hasNext();) { String str = (String) iterator2.next(); System.out.println(str); } System.out.println("----------------"); // for in 主要作用就是為了簡(jiǎn)化Iterator,事實(shí)上for in就是Iterator for (String s : list) {// String s表示list中的每一個(gè)字符串 System.out.println(s); } }}

自定義對(duì)象使用for/in語句

  如果一個(gè)對(duì)象,使用for/in語句中,該對(duì)象必須滿足兩個(gè)條件:   1、這個(gè)類必須實(shí)現(xiàn)Iterator接口   2、這個(gè)類必須重寫Iterator方法

import java.util.Iterator;import org.junit.Test;/** * for in語句 * */public class ForInTest { @Test public void demo2() { // Car用于for/in語句 Dota dota = new Dota(); for (String str : dota) { System.out.println(str); } }}// 實(shí)現(xiàn)讓自定義了類Car可以用于for/in語句class Dota implements Iterable<String> { String[] names = {"敵法師","龍騎士","黑暗游俠","圣堂武士"}; @Override public Iterator<String> iterator() { // TODO Auto-generated method stub // 自定義迭代器 return new MyIterator(); } class MyIterator implements Iterator<String> { int index = 0; // 當(dāng)前遍歷數(shù)組下標(biāo) @Override public boolean hasNext() { if (index >= names.length) { // 證明下標(biāo)無法獲取 return false; } return true; } @Override public String next() { String name = names[index]; index++; return name; } @Override public void remove() { // TODO Auto-generated method stub } }}

for/in刪除導(dǎo)致的并發(fā)異常處理

  在使用迭代器和for/in語句進(jìn)行l(wèi)ist循環(huán)的時(shí)候,刪除元素就會(huì)出現(xiàn)java.util.ConcurrentModificationException(并發(fā)異常)。   解決方案:   1、 使用Iterator自帶的remove方法(以下的demo3)。   2、如果只是刪除一個(gè)元素的時(shí)候,可以使用for/in語句刪除元素后,直接break跳出循環(huán)(以下的demo5)。   3、使用解決這類異常線程安全集合CopyOnWriteArrayList< E >。(以下的demo6)

import java.util.Iterator;import java.util.List;import java.util.ArrayList;import org.junit.Test;/** * for in語句 * */public class ForInTest { @Test public void demo6() { // 使用線程安全的集合對(duì)象,在for/in循環(huán)中刪除 List<String> list = new CopyOnWriteArrayList<String>(); list.add("qwer"); list.add("asd"); list.add("zxc"); list.add("123"); list.add("apple"); // 刪除apple // 如果只是刪除一個(gè)的話可以試以下方法 for (String str : list) { if (str.equals("apple")) { list.remove(str); } } System.out.println(list); } /** * 如果for/in語句中只是刪除一個(gè)元素,還可以使用break在刪除后跳出循環(huán),這是不會(huì)執(zhí)行下一次next----就不會(huì)出現(xiàn)并發(fā)異常了 * */ @Test public void demo5() { List<String> list = new ArrayList<String>(); list.add("qwer"); list.add("asd"); list.add("zxc"); list.add("123"); list.add("apple"); // 刪除apple // 如果只是刪除一個(gè)的話可以試以下方法 for (String str : list) { if (str.equals("apple")) { list.remove(str); break; } } System.out.println(list); } @Test public void demo4() { List<String> list = new ArrayList<String>(); list.add("qwer"); list.add("asd"); list.add("zxc"); list.add("123"); list.add("apple"); // 遍歷集合移除所有包含字母“a”的字符串 // 遍歷list 三種寫法 // 下標(biāo),Iterator,for/in // 下標(biāo) for (int i = 0; i < list.size(); i++) { String s = list.get(i); if (s.contains("a")) { // 需要將s從list移除 list.remove(s); // 防止元素被跳過 i--; } } System.out.println(list); } /** * List移除練習(xí) * */ @Test public void demo3() { List<String> list = new ArrayList<String>(); list.add("qwer"); list.add("asd"); list.add("zxc"); list.add("123"); list.add("apple"); // 通過for/in for (String s : list) { if (s.contains("a")) { // 以下方法會(huì)產(chǎn)生并發(fā)異常 // list.remove(s);// // error,java.util.ConcurrentModificationException // 第一種解決方法 -- 使用迭代器自身的remove } } // 第一種解決方法 -- 使用迭代器自身的remove // 使用Iterator進(jìn)行List遍歷 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String s = iterator.next(); if (s.contains("a")) { iterator.remove(); } } System.out.println(list); } @Test public void demo1() { List<String> list = new ArrayList<String>(); list.add("qwer"); list.add("asdf"); list.add("zxcv"); // 在JDK5之前有兩種遍歷方式:通過下標(biāo)遍歷,通過iterator Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println("----------------"); for (Iterator<String> iterator2 = list.iterator(); iterator2.hasNext();) { String str = (String) iterator2.next(); System.out.println(str); } System.out.println("----------------"); // for in 主要作用就是為了簡(jiǎn)化Iterator,事實(shí)上for in就是Iterator for (String s : list) {// String s表示list中的每一個(gè)字符串 System.out.println(s); } }}

六、可變參數(shù)

  可變參數(shù)主要是用來編寫框架。   原理:int… args相當(dāng)于int[] args,調(diào)用可變參數(shù)方法的時(shí)候,傳入任意個(gè)數(shù)參數(shù)。任意個(gè)數(shù)參數(shù)都會(huì)被保存在參數(shù)數(shù)組中,   例如:add(int… args)   add(10,20)相當(dāng)于add(new int[]{10,20});   add(20,30,40)相當(dāng)于add(new int[]{20,30,40});   add()相當(dāng)于add(new int[]{});

測(cè)試Arrays.asList()方法

import java.util.Arrays;import java.util.List;import org.junit.Test;public class VariableTest { @Test public void demo1() { int[] arr = {10,20,30}; // 使用Arrays.asList將數(shù)組轉(zhuǎn)換為L(zhǎng)ist List<int[]> list = Arrays.asList(arr); System.out.println(list.size()); Integer[] arr2 = {10,20,30}; List<Integer> list2 = Arrays.asList(arr2); System.out.println(list2.size()); // 注意 -- 同時(shí)傳遞數(shù)組和整數(shù)的時(shí)候,程序會(huì)將數(shù)組和整數(shù)作為獨(dú)立的對(duì)象使用 List list3 = Arrays.asList(arr2,200,300); System.out.println(list3.size()); List<Integer> list4 = Arrays.asList(100,200,300); System.out.println(list4.size()); // list3是不是ArrayList? // 注意:這個(gè)不是我們所知道的ArrayList,該ArrayList不能改變長(zhǎng)度 list4.remove(100); // 會(huì)報(bào)以下錯(cuò)誤,java.lang.UnsupportedOperationException }}

  從JDK5開始,Java允許為方法定義長(zhǎng)度可變的參數(shù),語法為:

public void foo(int... args) {}

  注意事項(xiàng):   1、調(diào)用可變參數(shù)的方法的時(shí)候,編譯器將自動(dòng)創(chuàng)建一個(gè)數(shù)組保存?zhèn)鬟f給方法的可變參數(shù),因此,程序猿可以在方法體中以數(shù)組的形式訪問可變參數(shù)。   2、可變參數(shù)只能處于參數(shù)列表的最后,所以一個(gè)方法最多只能有一個(gè)長(zhǎng)度可變的參數(shù)。

import java.util.Arrays;import java.util.List;import org.junit.Test;public class VariableTest { @Test public void demo2() { // 數(shù)據(jù)求和 System.out.println(add(10,20,30)); System.out.println(add()); System.out.println(add(new int[]{10,20,30,40})); } // 多個(gè)int類型參數(shù)求和,int... 表示任意個(gè)數(shù)int類型參數(shù) public int add(int ... args) { int sum = 0; for (int i : args) { sum += i; } return sum; }}

七、反射API的使用

  如果你想要編寫高效、功能強(qiáng)大的Java程序,必須使用發(fā)射技術(shù)。

什么是反射?

  JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為java語言的反射機(jī)制。

  JAVA反射(放射)機(jī)制:“程序運(yùn)行時(shí),允許改變程序結(jié)構(gòu)或變量類型,這種語言稱為動(dòng)態(tài)語言”。從這個(gè)觀點(diǎn)看,Perl,Python,Ruby是動(dòng)態(tài)語言,C++,Java,C#不是動(dòng)態(tài)語言。但是JAVA有著一個(gè)非常突出的動(dòng)態(tài)相關(guān)機(jī)制:Reflection,用在Java身上指的是我們可以于運(yùn)行時(shí)加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個(gè)運(yùn)行時(shí)才得知名稱的class,獲悉其完整構(gòu)造(但不包括methods定義),并生成其對(duì)象實(shí)體、或?qū)ζ鋐ields設(shè)值、或喚起其methods。      總結(jié)部分:   1、剖析Java類的各個(gè)組成部分映射成一個(gè)個(gè)Java對(duì)象   2、類java.lang.Class   3、java.lang.reflect   4、構(gòu)造方法Constructor   5、成員變量Field   6、方法Method

反射用在哪里?

  多用于框架和組件,寫出復(fù)用性高的通用程序。

反射流程

  .java文件(源代碼)——(編譯)——>.class字節(jié)碼(java類名)——(運(yùn)行)——>< JVM中 >【 類加載器(字節(jié)碼由類加載器加載)——(生成)——>Class類對(duì)象(位于java.lang包中)】

  在.class字節(jié)碼中,被加載器加載之后,整個(gè)字節(jié)碼生成對(duì)象Class對(duì)象,字節(jié)碼中的成員變量生成Field對(duì)象,字節(jié)碼成員方法生成Method對(duì)象,構(gòu)造器則生成Constructor對(duì)象。

public class A { // 成為內(nèi)存Class對(duì)象 int n = 10; // Field public void show() {} // Method public static void init() {} // Method public A() {} // Constructor}

獲得Class對(duì)象的三種方法

  1、已知類——可以通過類名.class獲得   2、已知對(duì)象——對(duì)象.getClass獲得   3、完整類名String格式——Class.forName(完整類名)——第三種方法是最常用的方法。

import org.junit.Test;/** * 編寫反射API使用 * */public class ReflfectTest { @Test public void demo1() { // 獲得class對(duì)象的三種方式 // 第一種 已知類 Class c1 = Readable.class; // 第二種 已知對(duì)象 Object obj = new ReflfectTest(); Class c2 = obj.getClass(); // 第三種 未知類和對(duì)象,知道完整類名 String className = "cn.idcast.jdk5.ReflfectTest"; try { Class c3 = Class.forName(className); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } // --------第三種方式是最常用的方法 }}

獲得Class構(gòu)造器的兩種方法

  通過類字節(jié)碼對(duì)象獲得構(gòu)造器、成員變量、方法有兩種方法:   1、獲得所有g(shù)etConstructors();   2、獲得指定的構(gòu)造器,可以使用getConstructor(class

import java.lang.reflect.Constructor;import org.junit.Test;/** * 編寫反射API使用 * */public class ReflfectTest { @Test public void demo2() throws ClassNotFoundException, SecurityException, NoSuchMethodException { // 獲得字節(jié)碼對(duì)象 String className = "cn.idcast.jdk5.ReflfectTest"; Class c = Class.forName(className); // 通過字節(jié)碼獲得一個(gè)類構(gòu)造器 Constructor<String>[] constructors = c.getConstructors(); System.out.println(constructors.length); // 獲得指定構(gòu)造器 // 帶有String參數(shù)的構(gòu)造器 Constructor constructors1 = c.getConstructor(String.class); System.out.println(constructors.length); } public ReflfectTest() { } public ReflfectTest(String str) { }}

使用獲取到的構(gòu)造器新建對(duì)象

package cn.idcast.jdk5;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import org.junit.Test;/** * 編寫反射API使用 * */public class ReflfectTest { @Test public void demo3() throws IllegalArgumentException, InstantiationException, IllegalaccessException, InvocationTargetException, SecurityException, NoSuchMethodException, ClassNotFoundException { String className = "cn.idcast.jdk5.ReflfectTest"; Class c = Class.forName(className); Constructor constructors = c.getConstructor(); Constructor constructors1 = c.getConstructor(String.class); // 調(diào)用無參數(shù)構(gòu)造器的寫法 ReflfectTest reflfectTest = new ReflfectTest(); // 使用反射實(shí)現(xiàn)相同的功能 Object obj = constructors.newInstance();// 調(diào)用無參數(shù)的構(gòu)造器,構(gòu)造對(duì)象 // 還有一種寫法 Object obj_1 = c.newInstance(); // 通過Class對(duì)象newInstance,調(diào)用目標(biāo)類無參數(shù)構(gòu)造器 // 調(diào)用無參數(shù)構(gòu)造器的寫法 ReflfectTest reflfectTest1 = new ReflfectTest("abcd"); // 使用反射實(shí)現(xiàn)相同的功能 Object obj1 = constructors1.newInstance("abcd");// 調(diào)用String類型的構(gòu)造器,構(gòu)造對(duì)象 }}

獲得Class獲取Field類

  Field類代表某個(gè)類中的一個(gè)成員變量,并提供動(dòng)態(tài)的訪問權(quán)限。   Field對(duì)象的獲得方法如下所示,   1、得到所有的成員變量:

Field[] fields = c.getFields(); // 獲得所有的public成員變量,包括父類繼承的。Field[] fields = c.getDeclaredFields();// 取得所有聲明的屬性,包括private屬性的成員變量

  2、得到指定的Field成員變量

Field fields = c.getDeclaredField(name); // 獲得當(dāng)前類中指定名稱name的成員變量

  設(shè)置Field變量是否可以訪問

// 設(shè)置private變量可以訪問的Field.setAccessible(true);

  Field變量值的讀取和設(shè)置

// 獲得對(duì)象指定name屬性值Field.get(name);// 修改Object的value的屬性值pnField.set(Object, value);

  總的代碼:

package cn.idcast.jdk5;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import org.junit.Test;/** * 編寫反射API使用 * */public class ReflfectTest { public String name; private String priname; public static void main(String[] args) { try { demo4(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 反射可以對(duì)內(nèi)存中任何字節(jié)碼進(jìn)行操作 @Test public static void demo4() throws ClassNotFoundException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { ReflfectTest reflfectTest = new ReflfectTest("Notzuonotdied"); // 使用反射操作類成員變量——Field類 // 1、必須獲得目標(biāo)類,字節(jié)碼對(duì)象 Class c = Class.forName("cn.idcast.jdk5.ReflfectTest"); // 2.操作成員實(shí)例變量name Field[] fields = c.getFields(); // 獲得所有的public 成員變量,包括父類繼承的 System.out.println("這里變量的數(shù)量為1,是因?yàn)椴话接校? + fields.length); Field[] fields2 = c.getDeclaredFields();// 獲取當(dāng)前類定義的所有成員,包括了private // 當(dāng)前Field是private的(名稱為"priname"的變量是private),我們是沒有操作不了的,因此我們需要設(shè)置Field的變量操作權(quán)限 Field pnField = c.getDeclaredField("priname"); System.out.println("這里變量的數(shù)量為2,是因?yàn)楣屑铀接幸还矁蓚€(gè):" + fields2.length); System.out.println(pnField); // 設(shè)置private變量可以訪問的 pnField.setAccessible(true); // 獲得reflfectTest對(duì)象指定name屬性值 Object pnobj = pnField.get(reflfectTest); System.out.println(pnobj); // 修改reflfectTest的name的屬性值 pnField.set(reflfectTest, "I am Notzuonotdied"); System.out.println(pnField.get(reflfectTest)); /* 輸出結(jié)果: * * 這里變量的數(shù)量為1,是因?yàn)椴话接校? * 這里變量的數(shù)量為2,是因?yàn)楣屑铀接幸还矁蓚€(gè):2 * private java.lang.String cn.idcast.jdk5.ReflfectTest.priname * Notzuonotdied * I am Notzuonotdied */ }}

獲得Class操作Method

  Method類代表某個(gè)類中的一個(gè)成員方法   Method對(duì)象的獲得,可以通過以下方法,   1、獲得所有方法

getDeclareMethods() //獲得當(dāng)前類聲明的方法 getMethods()

  2、獲得指定的方法

getDeclaredMethod(String name,Class<?>... parameterTypes)// 獲得指定方法getMethod(String name,Class<?>... parameterTypes)

  通過反射執(zhí)行方法

invoke(Object obj,Object... args)

  如果執(zhí)行static方法,第一個(gè)參數(shù)obj傳入null。   

package cn.idcast.jdk5;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import org.junit.Test;/** * 編寫反射API使用 * */public class ReflfectTest { public String name; private String priname; public void setName(String name) { this.name = name; } public String getName() { return name; } @Test public void demo5() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { ReflfectTest reflfectTest = new ReflfectTest(); // 調(diào)用reflfectTest對(duì)象中setName方法設(shè)置name的值 // 1、獲得字節(jié)碼對(duì)象 Class c = Class.forName("cn.idcast.jdk5.ReflfectTest"); // String類型參數(shù)setName方法 Method setName = c.getDeclaredMethod("setName", String.class); // String類型參數(shù)的setName方法 // 調(diào)用reflfectTest對(duì)象中的setName setName.invoke(reflfectTest, "this is a test demo"); // 等價(jià)于reflfectTest.setName("this is a test demo"); // String類型參數(shù)getName方法 Method getName = c.getDeclaredMethod("setName", String.class); // String類型參數(shù)的setName方法 // 調(diào)用reflfectTest對(duì)象中的setName getName.invoke(reflfectTest, "this is a test demo"); // 等價(jià)于reflfectTest.setName("this is a test demo"); }}

反射小案例——晚會(huì)案例

  1、編寫晚會(huì)程序,測(cè)試程序;   2、為了程序更好維護(hù)和擴(kuò)展,需要將做什么(interface)和怎么做(實(shí)現(xiàn)interface中的方法)分離;   問題:在晚會(huì)類中,要維護(hù)所有出演演員,但是不想修改晚會(huì)類,可以怎么寫?   答:可以采用工廠結(jié)構(gòu)(中介)來確定那一個(gè)對(duì)象將會(huì)被運(yùn)行。   3、用工廠將做什么和怎么做進(jìn)行解耦合;   4、將演員實(shí)例類寫入配置文件。(寫入配置文件之后,可以在不修改源代碼的情況下修改程序)      工廠+反射+配置文件模式的作用:編寫便于擴(kuò)展、便于維護(hù)的程序。

主程序EveningParty.java

package cn.idcast.jdk5.demo;/** * 晚會(huì) * * @author seawind * */public class EveningParty { public static void main(String[] args) { new EveningParty().proccess(); // 晚會(huì)舉行了 } /** * 這里僅僅定義了程序怎么做,但是沒有定義要做什么,由哪個(gè)對(duì)象來做。 * */ public void proccess() { // 定義晚會(huì)流程 // 演出 歌曲、舞蹈、表演 ---- 程序做什么? System.out.println("晚會(huì)正式開始!"); // 這里是晚會(huì)的流程(執(zhí)行邏輯部分),這里全部使用了接口,具體怎么做由實(shí)現(xiàn)接口的類來完成 // 接口的實(shí)現(xiàn)類由配置文件party.properties進(jìn)行控制 Factory.getSingable().sing();// 準(zhǔn)備 歌曲節(jié)目 Factory.getDanceable().dance(); // 準(zhǔn)備舞蹈 Factory.getPerformable().perform(); // 準(zhǔn)備表演類節(jié)目 System.out.println("晚會(huì)圓滿結(jié)束!"); }}

工廠類Factory.java:

  工廠類主要通過獲取配置文件party.properties中的定義來獲得類名,

ResourceBundle.getBundle("party").getString( "Singable");

  并通過類名來創(chuàng)建對(duì)應(yīng)的對(duì)象。

Class.forName(className).newInstance();

  下面是工廠類完整代碼:

package cn.idcast.jdk5.demo;import java.util.ResourceBundle;import cn.idcast.jdk5.demo.interfaces.Danceable;import cn.idcast.jdk5.demo.interfaces.Performable;import cn.idcast.jdk5.demo.interfaces.Singable;/** * 中介類, * */public class Factory { // 提供準(zhǔn)備 歌手方法 public static Singable getSingable() { // 讀取配置文件 src/party.properties String className = ResourceBundle.getBundle("party").getString( "Singable"); // 已知完整類名 獲得對(duì)象 try { Object obj = Class.forName(className).newInstance(); return (Singable) obj;// 類型轉(zhuǎn)換 } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("中介出問題了!"); } } // 提供準(zhǔn)備 舞蹈方法 public static Danceable getDanceable() { // 讀取配置文件 src/party.properties String className = ResourceBundle.getBundle("party").getString( "Danceable"); // 已知完整類名 獲得對(duì)象 try { Object obj = Class.forName(className).newInstance();// 通過反射新建對(duì)象 return (Danceable) obj; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("中介出問題了!"); } } // 提供準(zhǔn)備 演員方法 public static Performable getPerformable() { // 讀取配置文件 src/party.properties String className = ResourceBundle.getBundle("party").getString( "Performable"); // 已知完整類名 獲得對(duì)象 try { Object obj = Class.forName(className).newInstance(); return (Performable) obj; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("中介出問題了!"); } }}

party.properties部分:

Singable = cn.idcast.jdk5.demo.singer.ZhangxueyouDanceable = cn.idcast.jdk5.demo.dancer.YanglipingPerformable = cn.idcast.jdk5.demo.performer.Liuqian

接口類Danceable:

package cn.idcast.jdk5.demo.interfaces;/** * 舞蹈的接口類 * */public interface Danceable { public void dance();}

接口類Performable:

package cn.idcast.jdk5.demo.interfaces;/** * 表演的接口類 * */public interface Performable { public void perform();}

接口類Singable:

package cn.idcast.jdk5.demo.interfaces;/** * 歌曲的接口類 * */public interface Singable { public void sing();}

接口的實(shí)現(xiàn)類Zhangxueyou.java :

package cn.idcast.jdk5.demo.singer;import cn.idcast.jdk5.demo.interfaces.Singable;public class Zhangxueyou implements Singable { @Override public void sing() { System.out.println("張學(xué)友 演唱吻別!"); }}

接口實(shí)現(xiàn)類Yangliping.java:

package cn.idcast.jdk5.demo.dancer;import cn.idcast.jdk5.demo.interfaces.Danceable;public class Yangliping implements Danceable { @Override public void dance() { System.out.println("楊麗萍 跳 孔雀舞!"); }}

接口實(shí)現(xiàn)類Liuqian.java:

package cn.idcast.jdk5.demo.performer;import cn.idcast.jdk5.demo.interfaces.Performable;public class Liuqian implements Performable { @Override public void perform() { System.out.println("劉謙表演 魔術(shù)!"); }}

八、注解

九、字符串格式化

十、Java5線程并發(fā)庫(kù)

源碼地址

Java筆記——2017年3月3日源碼下載
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南漳县| 合阳县| 宁津县| 兰坪| 浦北县| 南澳县| 大宁县| 宝清县| 安国市| 新津县| 商城县| 陆良县| 龙里县| 广宁县| 铜梁县| 湘潭市| 巩义市| 扶余县| 东乡族自治县| 迭部县| 潼南县| 天祝| 于都县| 合阳县| 芮城县| 慈溪市| 吴川市| 察隅县| 屏边| 霍城县| 高雄县| 阿图什市| 漾濞| 上高县| 扶余县| 巫溪县| 都匀市| 斗六市| 房产| 榆树市| 宣武区|