Java高新技术笔记:反射、多线程、泛型、枚举、javaBean、代理
1、IDE: Integrated Development Environment
2、集成開發(fā)環(huán)境兩個主流:Eclipse和netBeans
3、preference: 偏愛
4、Compiler: 編譯器;
5.Switcha javaspace:切換Java工作間
6.Perspective:透視圖
7.雖然我一直用Eclipse的alt加反斜杠,但是不知道它的英文名字,在preference中的key-contentAssist內(nèi)容協(xié)助選項來設(shè)置一下快捷鍵
8、Myeclipse中的調(diào)試debug,可以使用step up 進(jìn)行下一行,要查看變量的話右擊變量選中watch,下一行就會看到變量的變化了。
9、Java模版template:定義自己的快捷鍵:
10、jdk1.6新特性,可變參數(shù)
11、ariableParameter :可變參數(shù)
這個是JDK5.0以上的版本新加的功能。那個for循環(huán)也是新加的功能。那個可變參數(shù)的就是個數(shù)組,你傳多少個參數(shù)都被放到那個數(shù)組里面。 這樣方便了程序員,因為如果不確定要傳的參數(shù)的個數(shù)的話,我們要寫帶1個參數(shù)的,帶2個參數(shù),帶3個參數(shù)的,這樣很麻煩。? 該進(jìn)后的這個方法,我們只要寫一個函數(shù)就好,可以傳任意個參數(shù)可變參數(shù)的數(shù)組args,是不包含第一個參數(shù)的哦,這個要記住。
package com.jianjian;
//jdk1.5 新特性,可變參數(shù)
public class Test2
{
?? public static void main(String[] args)
?? {
????? System.out.println(method(2,3,4));
????? System.out.println(method(3,4,5,5,6));
?? }
??
?? public static int method (int a ,int...args)
?? {
????? int sum = a;
????? System.out.println(args[0]);
????? for(int i = 0; i < args.length; i ++)
????? {
??????? sum = sum + args[i];
????? }
????? return sum;
?? }
}
?
?
10.
在導(dǎo)入包的時候一定要注意統(tǒng)一編碼!以及jdk的版本統(tǒng)一
11、
享元模式:flyWeight
12、享元模式(英語:Flyweight Pattern)是一種軟件設(shè)計模式。它使用共享物件,用來盡可能減少內(nèi)存使用量以及分享資訊給盡可能多的相似物件;它適合用于當(dāng)大量物件只是重復(fù)因而導(dǎo)致無法令人接受的使用大量內(nèi)存。通常物件中的部分狀態(tài)是可以分享。常見做法是把它們放在外部數(shù)據(jù)結(jié)構(gòu),當(dāng)需要使用時再將它們傳遞給享元。
典型的享元模式的例子為文書處理器中以圖形結(jié)構(gòu)來表示字符。一個做法是,每個字形有其字型外觀, 字模 metrics, 和其它格式資訊,但這會使每個字符就耗用上千字節(jié)。取而代之的是,每個字符參照到一個共享字形物件,此物件會被其它有共同特質(zhì)的字符所分享;只有每個字符(文件中或頁面中)的位置才需要另外儲存。以下程式用來解釋上述的文件例子。這個例子用來解釋享元模式利用只載立執(zhí)行立即小任務(wù)所必需的資料,因而減少內(nèi)存使用量。
?
?
13、Java反射機(jī)制
JAVA反射機(jī)制:“程序運(yùn)行時,允許改變程序結(jié)構(gòu)或變量類型,這種語言稱為動態(tài)語言”。從這個觀點(diǎn)看,Perl,Python,Ruby是動態(tài)語言,C++,Java,C#不是動態(tài)語言。但是JAVA有著一個非常突出的動態(tài)相關(guān)機(jī)制:Reflection,用在Java身上指的是我們可以于運(yùn)行時加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運(yùn)行時才得知名稱的class,獲悉其完整構(gòu)造(但不包括methods定義),并生成其對象實體、或?qū)ζ鋐ields設(shè)值、或喚起其methods
?
14.Class對象沒有構(gòu)造方法,所以不能new出對象來
15、Class c =Person.class//這是一個字節(jié)碼,這個類的字節(jié)碼就會從內(nèi)存中加載進(jìn)來
16.Class.forName()返回一個字節(jié)碼
17、有三種方法獲得對象的字節(jié)碼
package com.jianjian;
?
public class Test3
{
?? public static void main(String[] args)throws ClassNotFoundException
?? {
????? Class c = Test3.class;
????? System.out.println(c);
????? System.out.println(c.getClass());
????? System.out.println(Class.forName("java.lang.String"));
?? }
}
?
?
18、
八中基本數(shù)據(jù)類型,加上void.class
19.
三種方法是用來返回字節(jié)碼所對應(yīng)的類,這是唯一的;
package com.jianjian;
?
public class Test3
{
?? public static void main(String[] args)throws ClassNotFoundException
?? {
????? String s = "hello";
????? Class s1 = s.getClass();
????? Class s2 = String.class ;
????? Class s3 = Class.forName("java.lang.String");
????? //這三種方法返回的字節(jié)碼對應(yīng)于同意類,所以字節(jié)碼是相同的
????? System.out.println(s3);
?????
????? System.out.println(s1== s2);
????? System.out.println(s1 == s3);
?? }
}
返回的都是同一類的字節(jié)碼
?
?
19.
Class的isPremitiv()方法,將判斷返回的字節(jié)碼是不是基本類型,包裝類型的TYPE屬性,將返對應(yīng)基本類型的字節(jié)碼:
也就是說int.Class == Integer.TYPE;
20、這個方法同樣可以驗證數(shù)組也是對象,比如說
int[].class.isPrimitive()就將返回false,說明整形數(shù)組并不是基本數(shù)據(jù)類型哦,void也是一個類型,因為有它們各自的class對象
?
23. package com.jianjian;
?
import java.lang.reflect.Constructor;
import java.util.Arrays;
?
public class Test5
{
?? public static void main(String[] args)throws ClassNotFoundException
?? {
????? Class c = Class.forName("java.lang.String");
????? System.out.println(c);
????? Constructor[] s = c.getConstructors();
????? System.out.println(Arrays.toString(s));//獲取所有的構(gòu)造方法
?
?? }
}
23/
?
24.
反射比較占用性能,導(dǎo)致程序性能嚴(yán)重下降
25、
Fileled類:反射中的成員變量
26.關(guān)于重寫和hashset的快捷鍵在Eclipse中是alt+shift+s
?
?
28.
字節(jié)碼一定要用等號比;因為都是拿同一份
29、
反射這個東西是無論如何也要弄懂啊:
反射中的Filed類,可以用于反射提取類中的成員變量:
我覺得例如Method類Constructor類都因該有類似的功能,
Class類中有兩個用來提取成員變量的方法,一個是
getField(Stringname);
一個是
getFields()
對于第一個是用來接受指定類中的一個 成員變量,傳入的字符串就是成員變量定義時的名字;但是要記住的是返回的類型是Field類,下面要用get方法傳入具體的對象才能獲得值;
比如說是這樣的:
一個類中Test有兩個成員變量
privateint a ;
publicint b;
我用getField(“a”)將獲得成員變量a對應(yīng)的Field,但這只是類的成員變量,不是對象的成員變量,你打印的話,將會輸出類名加成員變量名,在用get方法傳入Test就能得到a的值;
?
而我用getFields()方法,將返回一個Field[] 數(shù)組,其中f[0]對應(yīng)a,f[1]對應(yīng)b;
然后就能分別進(jìn)行處理;
但是 有注意到,b是私有的成員變量,這在反射中是不可見的,用getField方法將不能取得私有的成員變量,只有使用getDeclaredFiled(Sting name)getDeclaredFields()方法了;當(dāng)然得到的類的私有成員變量也不能被訪問,需要暴力反射;獲取訪問權(quán)限;使用setAccessible(true)之后,再用get方法取出:
下面是完整的代碼:
?
package com.jianjian;
?
import java.lang.reflect.Field;
import java.util.Arrays;
?
public class Test1
{
?? public static void main(String[] args)throws Exception
?
?? {
????? Test2 test = new Test2(3,5);
????? Class c = test.getClass();//獲得類對應(yīng)的字節(jié)碼,這是反射的第一步;
????? //首先使用getField()方法輸出成員變量
????? Field f1 = c.getField("a");
????? Field f2 = c.getDeclaredField("b");//因為b是私有的成員變量
????? int a = (Integer)f1.get(test);//get方法返回的是Object類型的
????? f2.setAccessible(true);//允許對私有成員變量訪問;
????? int b = (Integer)f2.get(test);
????? System.out.println(a);
????? System.out.println(b);
?????
?????
????? //下面使用getFields()方法輸出成員變量
????? Field[] f = c.getDeclaredFields();//因為有私有的成員變量,所以最好建議都是用這個方法
????? System.out.println(f[0].get(test));//省去匹配的步驟
????? f[1].setAccessible(true);
????? System.out.println(f[1].get(test));
?????
?????
?????
?????
?????
?? }
}
?
?
?
?
?
?
?
3.
package com.jianjian;
?
public class Test2
{
?? public int a ;
?? public int b;
?? public Strings1 ="basketball";//注意只有public的才可以使用getFields,其他的請用declared
?? public Strings2 ="ball";
??
?? public Test2(int a ,int b)
?? {
????? this.a = a;
????? this.b = b;
?? }
?? //打印對象就是打印對象的toSting方法,現(xiàn)在重寫一下對象的toString方法,
?? //讓它打印s1和s2
?? public String toString()
?? {
????? return s1 +";"+ s2;
?? }
??
??
}
?
?
package com.jianjian;
?
import java.lang.reflect.Field;
?
public class Test3
{
?? /*反射的高級應(yīng)用,竊取篡改信息
?? ?* 用反射來獲取Test2中的字符串變量,這就要求有篩選的步驟
?? ?* 獲取變涼后將字符串中的字符a變成字符b;在輸出字符串;
?? ?*/
??
?? public static void main(String[] args)throws Exception
?? {
????? Test2 test = new Test2(3,5);
????? Class c = test .getClass();
????? //首先篩出所有的成員變量
????? Field[] f = c.getFields();
????? for(Field? field : f)
????? {
??????? if(field.getType() == String.class)//判斷這個成員變量是不是字符串,字節(jié)碼一定要用
??????? {
?????????? String str = (String)field.get(test);//返回的對象肯定是字符串
?????????? //提取并更改字符串a換b
?????????? String newStr = str.replace('b','a');
?????????? System.out.println(newStr);
?????????? field.set(test,newStr);//將新的局部變量加入到原有的對象中
???????
??????? }
???????
???????
????? }
????? System.out.println(test);
?????
?????
?????
?????
?????
?????
?????
?????
?????
?????
?????
?????
?????
?? }
}
30.
用發(fā)射調(diào)用方法:比如說調(diào)用String中的charAt(int index)
方法,這個用反射怎么實現(xiàn):
Class類中的getMethod(Stringname, Class papameter)方法接受兩個參數(shù),一個是要反射的方法名字,第二個是方法名字所接受數(shù)據(jù)類型的字節(jié)碼,這是個可變參數(shù)(variable Parameter)
就是為了區(qū)分方法重載,確定你要調(diào)用那一個方法;
package com.jianjian;
?
import java.lang.reflect.Method;
?
public class Test4
{
?? public static void main(String[] args)throws Exception
?? {
????? String s = "helloWorld";
?
????? Class c = s.getClass();
????? Method method = c.getMethod("charAt",int.class);
????? char a = (Character) method.invoke(s, 0);//沒有人知道一個類中的某一個方法到底返回什么類型,只要你知道
????? System.out.println(a);
?
?? }
}
31、
package com.jianjian;
//普通的調(diào)用一個類的main方法
public class Test8
{
?? public static void main(String[] args)
?? {
?
????? Reflect.main(new String[] {"1","222" });
?? }
}
?
class Reflect
{
?? public static void main(String[] args)
?? {
????? for (String s : args)
????? {
??????? System.out.println(s);
????? }
?? }
?
}
?
?
32、
選中一個類然后按下F2就可以看到這個類的完整類名了;
package com.jianjian;
?
public class Test9
{
?? public static void main(String[] args)
?? {
????? for(String s :args)
????? {
??????? System.out.println(s);
????? }
?? }
}
?
package com.jianjian;
//用反射的方式來調(diào)用test9中的main方法
import java.lang.reflect.Method;
?
public class Test8
{
?? public static void main(String[] args)throws Exception
?? {
????? //首先,我要獲得Test9中的完整類路徑名;需要為args賦值的話,請用
????? //f2獲得當(dāng)前類的的完整路徑名,然后run as,運(yùn)行配置,在當(dāng)前的main方法中將類名賦予第一個參數(shù)
????? String className = args[0];//這樣就獲得了Test9的類名稱
????? Class c = Class.forName(className);
????? Method m = c.getDeclaredMethod("main", String[].class);//是一個字符串?dāng)?shù)組類的字節(jié)碼
?
????? System.out.println(m);
????? m.invoke(null, (Object)new String[] {"222","333","444" });
????? //這個Object最好記住,就是把數(shù)組當(dāng)成整體,因為實際上args本身也就是一個,如果不加Object這就相當(dāng)于是三個了
?????
?????
?? }
}
?
?
33.
/*
?* 看張老師的視屏還是收獲頗豐啊!
?* int類型是基本數(shù)據(jù)類型,不是對象類型,不繼承Object
?* 而Java中所有的數(shù)組都是對象,也就是說數(shù)組也是繼承了Object
?* 所以我可以這樣說,int[]繼承了Object
?* 下面再來看一下int[]和 Object[]的區(qū)別
?* int[]的意思是定義一個整形數(shù)組,里面存放int型的基本數(shù)據(jù)
?* 而Object[]的意思是定義一個Object類型的數(shù)組,里面存放Object類型的對象,
?* 一個放基本數(shù)據(jù)類型,一個放對象類型,你說相等不想等
?* 所以有 Object[] b == Integer[] a;而Object[] == int[]這個是絕對錯的;
?* 但是Object[] b是不是可以等于 int[][] a呢;答案是肯定的,int[][]可以這樣來理解,
?* 定義一個int類型的數(shù)組,里面用來存放int類型的數(shù)組,兩個都是Object類型的,肯定是相等的,
?* 所以以后不要再把對象類型強(qiáng)制為對象類型了!,看下面的例子!
?*/
package com.jianjian;
?
public class Test10
{
?? public static void main(String[] args)
?? {
????? int[] a1 = new int[10];
????? int[][] a2 =newint[2][3];
????? String[] s = new String[3];
????? Object[] o = new Object[10];
????? // o = a1;這行是錯的
????? o = a2;
????? o = s;
????? s = (String[]) o;
?
?? }
}
?
?
34.
?
判斷是不是數(shù)組Arrays.isArray();
?
?
35/
?
?
36/
相對路徑和絕對路徑
絕對路徑:是從盤符開始的路徑,形如 C:\windows\system32\cmd.exe 相對路徑:是從當(dāng)前路徑開始的路徑,假如當(dāng)前路徑為C:\windows 要描述上述路徑,只需輸入 system32\cmd.exe 實際上,嚴(yán)格的相對路徑寫法應(yīng)為 .\system32\cmd.exe 其中,.表示當(dāng)前路徑,在通道情況下可以省略,只有在特殊的情況下不能省略。 假如當(dāng)前路徑為c:\program files 要調(diào)用上述命令,則需要輸入 ..\windows\system32\cmd.exe 其中,..為父目錄。 當(dāng)前路徑如果為c:\program files\common files 則需要輸入 ..\..\windows\system32\cmd.exe另外,還有一種不包含盤符的特殊絕對路徑,形如 \windows\system32\cmd.exe 無論當(dāng)前路徑是什么,會自動地從當(dāng)前盤的根目錄開始查找指定的程序。introspector
37、
?
?
38、不是太理解javabean的作用
?
?
39.
來說一下我自己對javaBean的理解吧,如果說,我想從一個類中,拿取它的成員變量,當(dāng)然,我不知道這個成員變量的訪問修飾符是怎樣的,只知道里面有一個獲取該變量的方法,比如說get方法,但是我又不知道其他人是怎么定義的這個方法名字,javabean就可以從傳入的對象類中,獲取這個類似的get方法和set方法:
package com.jianjian;
?
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
?
public class Test12
{
?? public static void main(String[] args)throws Exception
?? {
????? Test11 test = new Test11(22,"zhangsan");
????? String varName = "age";//定義要獲取的變量的名稱
????? PropertyDescriptor pro1 = new PropertyDescriptor(varName, test
?????????? .getClass());
????? // 可以看到,PropertyDescriptor是bean包下的一個類,它的構(gòu)造方法,接收兩個參數(shù),一個
????? // 你要獲取的變量的名字,第二個是對象類的字節(jié)碼
?
????? Method getMethod = pro1.getReadMethod();
????? // 意思是獲取對象中的一個可以讀取變量的一個方法,同樣的有write方法
????? // 獲取方法后當(dāng)然就可以使用invoke來調(diào)用了
????? Object ob = getMethod.invoke(test);
????? System.out.println(ob);//然后你就可以看到22了
?
????? // 下面我來將原有對象中的name屬性修改,該位33
?
????? Method setMethod = pro1.getWriteMethod();//獲取set類似方法
????? setMethod.invoke(test, 33);
????? Object ob2 = getMethod.invoke(test);
????? System.out.println(ob2);
?
?? }
}
一個Eclipse小技巧:方法重構(gòu):Method
當(dāng)然,其實上面的代碼只完成了兩件事,一個是獲取一個整形的變量name,一個是set一個整形的變量name進(jìn)去,這完全也可以用兩個方法來實現(xiàn)
方法重構(gòu):Method Refactor:alt + shift + t
?
對選中的代碼重組成一個方法,最好不要出現(xiàn)基本類型,最好將變量卸載外部,能夠用來調(diào)用也就是傳遞進(jìn)方法:
package com.jianjian;
?
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
?
public class Test12
{
?? public static void main(String[] args)throws Exception
?? {
????? Test11 test = new Test11(22,"zhangsan");
????? String varName = "age";//定義要獲取的變量的名稱
????? PropertyDescriptor pro1 = new PropertyDescriptor(varName,test.getClass());
????? // 可以看到,PropertyDescriptor是bean包下的一個類,它的構(gòu)造方法,接收兩個參數(shù),一個
????? // 你要獲取的變量的名字,第二個是對象類的字節(jié)碼
?
????? Method getMethod = pro1.getReadMethod();
????? // 意思是獲取對象中的一個可以讀取變量的一個方法,同樣的有write方法
????? // 獲取方法后當(dāng)然就可以使用invoke來調(diào)用了
????? Object ob = getMethod.invoke(test);
????? System.out.println(ob);//然后你就可以看到22了
?
????? // 下面我來將原有對象中的name屬性修改,該位33
?
????? retrunSet(test, pro1, getMethod);
?
?? }
?
?? private static void retrunSet(Test11 test, PropertyDescriptor pro1,
??????? Method getMethod) throws IllegalAccessException,
??????? InvocationTargetException
?? {
????? Method setMethod = pro1.getWriteMethod();//獲取set類似方法
????? setMethod.invoke(test, 33);
????? Object ob2 = getMethod.invoke(test);
????? System.out.println(ob2);
?? }
}
?
41.
對一個類中的一個變量名進(jìn)行更改,將會牽涉到所有的變量,選中變量名后,使用重構(gòu),或者用快捷方式 alt shift R
42/
這個意思是說
package com.jianjian;
?
import java.util.ArrayList;
?
public class GenericTest1
{
?? public static void main(String[] args)
?? {
?? ArrayList<String> list1 = new ArrayList<String>();
?? ArrayList<Integer> list2 = new ArrayList<Integer>();
??
?? boolean b = (list1.getClass() == list2.getClass());
?? System.out.println(b);
?? }
}
你覺得打印的結(jié)果是true還是false呢,結(jié)果是true
?
43、
泛型是編譯期的行為,也就是說只在編譯時起作用,如果你為集合添加的數(shù)據(jù)類型不匹配,它是會提醒你出錯的,但是
反射是運(yùn)行期的,也就是說它可以繞過泛型的約束,比如你可以向一個指定Integer類型的ArrayList添加一個字符串,下面用反射的方式來實現(xiàn):
package com.jianjian;
?
import java.util.ArrayList;
?
public class GenericTest2
{
?? public static void main(String[] args)throws Exception
?? {
????? ArrayList<Integer> list1 = new ArrayList<Integer>();
?????
????? //用反射的方法調(diào)用其add方法,添加一個字符串
????? list1.getClass().getMethod("add",Object.class).invoke(list1,"name");
????? System.out.println(list1.get(0));
?????
?????
?? }
}
結(jié)果證明真的是打印了name;
43、
?
?
?
?
44.
八種基本數(shù)據(jù)類型的父類是Number,所以用泛型的時候可以這樣寫:? extends Number
45、
?
46、
為自己掙了四個技術(shù)分的題目
package com.jianjian;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;
?
public class Test {
?
?? /**
?? ?* 題目:已有字符串Str1,"sdfghellozxsdfcvwaadfafsasdfxcvdf"鍵盤輸入任意字符串,如:String
?? ?*str2="HaHahello01", 在原來字符串Str1中去掉str2中最大的交集字符串(hello)后,
?? ?* 獲取該字符串str1中的每個字母出現(xiàn)的次數(shù)。
?? ?*
?? ?* 例如:去掉hello后以這種方式打印:按次數(shù)從大到小排序,次數(shù)相同,按字母從大到小排序!
?? ?* f(出現(xiàn)6次)d(出現(xiàn)5次)s(出現(xiàn)4次)x(出現(xiàn)2次)v(出現(xiàn)2次)c(出現(xiàn)2次)w(出現(xiàn)1次)g(出現(xiàn)1次)
?? ?*
?? ?* @param args
?? ?* @throws Exception
?? ?* @author張熙韜
?? ?*/
?? public static void main(String[] args)throws Exception {
????? String str1 = "sdfg,hellozx,sdfcv-waadfa,fsasdfxcvdf";
????? BufferedReader bufr = new BufferedReader(new InputStreamReader(
??????? ?? System.in));
?
????? String str2 = bufr.readLine();
????? StringBuffer sb = new StringBuffer(str1);
?
????? // 去掉子字符串
????? int index = sb.indexOf(str2);
????? sb = sb.delete(index, index + str2.length());
?
????? String answer = sb.toString();
????? System.out.println("去掉最大子字符串之后的字符串為:" + answer);
?
????? // 統(tǒng)計每個字母出現(xiàn)的次數(shù)
????? StringBuffer answerSb = new StringBuffer(charCount(answer));
????? //System.out.println(answerSb.reverse());
????? System.out.println(answerSb);
?
?? }
?? /**
?? ?* 統(tǒng)計每個字母出現(xiàn)的次數(shù)
?? ?*
?? ?* @param str
?? ?* @return
?? ?*/
?? public static String charCount(String str) {
????? char[] chs = str.toCharArray();
????? // 傳入工具類反轉(zhuǎn)函數(shù),下面再定義EntryComparator函數(shù),最后排序結(jié)果是EntryComparator,說明自定義函數(shù)優(yōu)先權(quán)最高!
????? TreeMap<Character, Integer> tm = newTreeMap<Character, Integer>(
?????????? Collections.reverseOrder());
????? for (int i = 0; i < chs.length; i++) {
??????? if (!(chs[i] >'a' && chs[i] <'z' || chs[i] >'A' && chs[i] <'Z')) {
?????????? continue;
??????? }
??????? Integer value = tm.get(chs[i]);
??????? if (value ==null) {
?????????? tm.put(chs[i], 1);
??????? } else {
?????????? value += 1;
?????????? tm.put(chs[i], value);
??????? }
????? }
????? StringBuilder sb = new StringBuilder();
????? Set<Map.Entry<Character, Integer>> entrySet =tm.entrySet();
?
????? //使用自定義子字符串進(jìn)行排序,先要將entrySet變成list集合,才能使用Collections.sort方法
????? List<Map.Entry<Character, Integer>> entryLists = newArrayList<Map.Entry<Character, Integer>>(entrySet);
?????
????? //使用Collections.sort方法對字符出現(xiàn)次數(shù)排序
????? Collections.sort(entryLists, new EntryComparator());
?????
????? Iterator<Entry<Character, Integer>>it=entryLists.iterator();
????? while(it.hasNext()){
??????? Entry<Character, Integer> me=it.next();
??????? Character key = me.getKey();
??????? Integer value = me.getValue();
??????? sb.append(key + "(出現(xiàn)" + value +"次)");
????? }
?????
????? //這種方式要簡便一些
/*??? for (Entry<Character, Integer> entry : entryLists) {
??????? Character key = entry.getKey();
??????? Integer value = entry.getValue();
??????? sb.append(key + "(出現(xiàn)" + value + "次)");
????? }*/
?
????? return sb.toString();
?? }
?
?? /**
?? ?* 獲取最大子字符串
?? ?*/
?? public static String getMaxString(String str1, String str2) {
????? String max = str1.length() > str2.length() ? str1 : str2;
????? String min = max == str1 ? str2 : str1;
????? for (int i = 0; i < min.length(); i++) {
??????? for (int j = 0, k = min.length() - i; k != min.length() + 1; j++,k++) {
?????????? String subString = min.substring(j, k);
?????????? if (max.contains(subString)) {
????????????? return subString;
?????????? }
????? ?? }
????? }
????? return null;
?? }
?
}
?
class EntryComparatorimplementsComparator<Map.Entry<Character, Integer>> {// value列表順序的比較器
?
?? public int compare(Map.Entry<Character, Integer> map1,
??????? Map.Entry<Character, Integer> map2) {//重寫compare方法
????? return map2.getValue().compareTo(map1.getValue());//降序排列
?? }
?
}
?
?
?
47.
Entry是一個接口,是Map的一個內(nèi)部類
java.util.Map.Entry
Entry相當(dāng)于是獨(dú)立的Map,單獨(dú)的存儲key set
map的entrySet方法返回一個set類型
entrySet
public Set<Map.Entry<K,V>> entrySet()?
還記得兩種遍歷 map的方法嗎?
記住map本身并沒有實現(xiàn)Iterator接口哦!
package com.jianjian;
?
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;
?
public class GenericTest3
{
?? public static void main(String[] args)
?? {
????? HashMap<String, Integer> map = new HashMap<String,Integer>();
????? map.put("zhangsan", 33);
????? map.put("lisi", 44);
????? map.put("wangwu", 55);
????? // 用Entry方法遍歷map成員
?
????? Set<Entry<String, Integer>> set = map.entrySet();//
????? for (Entry entry : set)
????? {
??????? System.out.println(entry.getKey());//得到key
??????? System.out.println(entry.getValue());//得到value
??????? ;
????? }
?
????? // 第二種方法,使用迭代器
????? Set<String> keySet = map.keySet();
?
????? for (Iterator<String> ite = keySet.iterator();ite.hasNext();)
????? {
??????? String name = ite.next();
??????? int age = map.get(name);
??????? System.out.println(name +":" + age);
?
????? }
?
?? }
}
?
?
48、
?
?
48、
49、
類加載器:Class loader
?
package com.jianjian;
?
public class ClassLoaderTest1
{
?? public static void main(String[] args)
?? {
????? Class c = ClassLoaderTest1.class.getClassLoader().getClass();
????? String name = c.getName();
????? System.out.println(c);//除了bootstrap是虛擬機(jī)加載器,其他的加載器都是Java類,都存在字節(jié)碼
?????
????? //來看一下bootStrap類加載器,通過System返回的是null,不代表不存在,而是存在于虛擬機(jī)中,無法被調(diào)用
?????
//??? Class c2 = System.class.getClassLoader().getClass();
//??? System.out.println(c2);
//??? 這樣打印出異常了,因為getClassLoaer的返回值是null
????? System.out.println(System.class.getClassLoader());
?????
?????
?? }
}
?
50.
?
?
?
51、
52、
package com.jianjian;
/*創(chuàng)建動態(tài)類,及查看方法列表信息
?* StringBuilder和StringBuffer的功能基本一致,知識在線程方面上有所區(qū)別
?* */
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;
import java.util.Collection;
?
public class ProxyTest1
{
?? public static void main(String[] args)
?? {
????? //Proxy代理類的構(gòu)造方法接受兩個參數(shù),第一個參數(shù)是類加載器,第二個是接口的字節(jié)碼,以Collector為例
?? ?? Class clazzProxy =Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
????? //既然返回的是一個字節(jié)碼,那它肯定是一個類,下面打印它的構(gòu)造方法和方法
????? Constructor[] clazzConstructor =clazzProxy.getConstructors();
????? for(Constructor con : clazzConstructor)
????? {
??????? String name = con.getName();
??????? System.out.println(name);
??????? //這將會打印出構(gòu)造方法的名字,我想打印出構(gòu)造方法和其中的參數(shù)類型,來看一下字符串拼接
??????? StringBuilder str =new StringBuilder(name);
??????? str.append("(");
??????? //取出構(gòu)造方法中的參數(shù)
??????? Class[] clazzcon =?con.getParameterTypes();
??????? //前提是有參數(shù)
??????? if(clazzcon.length != 0)
??????? {
?????????? for(Class clazz: clazzcon)
?????????? {
????????????? str.append(clazz.getName());
????????????? str.append(",");
?????????? }
??????? }
??????? str.append(")");
??????? System.out.println(str.toString());
????????????????????????
???????
??????????
??????????
??????????
???????
???????
????? }
?????
?????
?? }
}
$Proxy0
$Proxy0(java.lang.reflect.InvocationHandler,)
?
54、
?
55、
代理類proxy的構(gòu)造方法要求接收一個InvocationHandle類型的參數(shù),而InvocationHandle是一接口,接口中只有一個方法: invoke,描述如下
| Object | invoke(Object proxy,Method method,Object[] args) |
?
要調(diào)用那個對象的那個方法的那些參數(shù)????
?
public static void main(String[] args)throws Exception
?? {
????? //Proxy代理類的構(gòu)造方法接受兩個參數(shù),第一個參數(shù)是類加載器,第二個是接口的字節(jié)碼,以Collector為例
????? Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
????? //既然返回的是一個字節(jié)碼,那它肯定是一個類,下面打印它的構(gòu)造方法和方法
????? Constructor[]clazzConstructor = clazzProxy.getConstructors();
???????
????? Constructor con2 = clazzProxy.getConstructor(InvocationHandler.class);
????? //得到構(gòu)造方法
????? //得到代理類的實例:構(gòu)造方法接受一個InvocationHandle接口類型的參數(shù),使用匿名內(nèi)部累一步搞定
????? Object obj = con2.newInstance(new InvocationHandler(){
??????? @Override
??????? public Object invoke(Object proxy, Method method, Object[]args)
????????????? throws Throwable
??????? {
?????????? // TODO Auto-generatedmethod stub
?????????? return null;
??????? }
???????
???????
????? });
????? //這樣就用反射的方法得到了一個代理烈的實例對象,打印對象的toString方法
????? System.out.println(obj.toString());//打印的結(jié)果是null
????? //因為你在匿名內(nèi)部累中,什么都沒干,返回的是null
?????
?????
?
?
?
?
56、
但是這樣做還是有些麻煩,其實在Proxy類中提供了一個方法newProxyInstance
public static Object newProxyInstance(ClassLoader loader, ???????????????????????????????? ?????Class<?>[] interfaces, ????????????????????????????????????? InvocationHandler h) ???????????????????????? ??????throws IllegalArgumentException?
這個方法將上面反射的步驟一步到位
1創(chuàng)建動態(tài)類 2 得到動態(tài)類的實例對象
可變參數(shù)只能位于參數(shù)的最后一個,中間的只能是數(shù)組
package com.jianjian;
?
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
?
//下面我寫一下完整的,用反射的方法得到實現(xiàn)了Collection接口(可以多個接口)動態(tài)類,并生成Collection動態(tài)類的實例對象
public class ProxyTest2
{
?? public static void main(String[] args)throws Exception
?? {
????? //得到Collection動態(tài)類
????? Class clazzCollection = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
????? //生成Collection動態(tài)類實例對象
????? //要接受的參數(shù)類型是InvocationHandle類型的參數(shù)
????? Constructor con = clazzCollection.getConstructor(InvocationHandler.class);
????? //生成實例對象,使用匿名內(nèi)部類
????? Object obj = con.newInstance(new InvocationHandler(){
???????
??????? @Override
??????? public Object invoke(Object proxy, Method method, Object[]args)
????????????? throws Throwable
??????? {
?????????? // TODO Auto-generatedmethod stub
?????????? return null;
??????? }
????? });
?????
????? //打印這個對象
????? System.out.println(obj.toString());
?????
?????
?????
?? }
}
?
然后是使用Proxy的newInstance()方法
public class ProxyTest3
{
?? public static void main(String[] args)
?? {
????? //注意到第二個參數(shù)的提示,是一個class[]數(shù)組,但是我只需要添加一個Collection類型的接口就可以了
????? //注意看一下怎么寫,new clss[]{Collection.class}
????? Collection collection =(Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),
?????????? ???? newClass[]{Collection.class},
?????????? ???? newInvocationHandler()
????????????? {
????????????????
???????????????? @Override
???????????????? public Object invoke(Object proxy, Method method, Object[]args)
????????????????????? throws Throwable
????????????? ?? {
??????????????????? // TODO Auto-generatedmethod stub
??????????????????? returnnull;
???????????????? }
????????????? }
????? );
?? }
}
?
?
56.
package com.jianjian;
?
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
?
public class ProxyTest3
{
?? public static void main(String[] args)
?? {
????? // 注意到第二個參數(shù)的提示,是一個class[]數(shù)組,但是我只需要添加一個Collection類型的接口就可以了
????? // 注意看一下怎么寫,new clss[]{Collection.class}
????? Collection collection = (Collection) Proxy.newProxyInstance(
?????????? Collection.class.getClassLoader(),
?????????? new Class[] { Collection.class },new InvocationHandler()
?????????? {
????????????? ArrayList list =newArrayList();//這里打印2
?
????????????? @Override
????????????? public Object invoke(Object proxy, Method method,
??????????????????? Object[] args) throws Throwable
????????????? {
???????????????? // ArrayList list= new ArrayList();
???????????????? // 把list寫到成員變量里面,就不會初始化了,這里打印0
???????????????? // TODO Auto-generatedmethod stub
???????????????? return method.invoke(list, args);
????????????? }
?????????? });
?
????? // 得到實例對象之后,就可以調(diào)用對象的方法了;
????? // 打印一下未加參數(shù)時它的size方法
????? // System.out.println(collection.size());
????? // 結(jié)果是空指針異常,這說明對象為空,因為你就沒有處理對象,返回的是null
????? // 下面,我們將對象指定為ArrayList
????? collection.add("zhangsan");//動態(tài)類每使用一次就會去調(diào)用handler對象的invoke方法,這也就是實現(xiàn)了對原方法的改動
?
????? collection.add("lisi");
????? System.out.println(collection.size());
?
?? }
}
?
?
?
?
?
?
?
?
?
57
| Object | invoke(Object proxy,Method method,Object[] args) |
這個方法接受的三個參數(shù)到底是什么呢?
代理對象,代理對象的那個方法,接受那些參數(shù)
我來演示一下代理的原理,本來,執(zhí)行collection.add()方法時,會調(diào)用handler的invoke方法,但是invoke指定的對象確實可變的,下面就是我把執(zhí)行的對象換成了ArrayList,最后返回的是ArrayList對象,這就是動態(tài)類的改變功能,在方法的什么位置寫,用什么對象,都會產(chǎn)生差異,其實add方法的返回值就是invoke返回的對象Object,你可以生成驗證
要注意到add方法已經(jīng)發(fā)生了改變了
new Class[] { Collection.class },new InvocationHandler()
?????????? {
????????????? ArrayList list =newArrayList();//這里打印2
?
????????????? @Override
????????????? public Object invoke(Object proxy, Method method,
??????????????????? Object[] args) throws Throwable
????????????? {
???????????????? Object obj = method.invoke(list,args);
????????????????
???????????????? // TODO Auto-generatedmethod stub
???????????????? return obj;
????????????? }
?????????? });
?
當(dāng)然也可以對參數(shù)進(jìn)行修改!
這也就是解釋了為什么調(diào)用 collection.add方法會出現(xiàn)異常,因為調(diào)用該方法,觸發(fā)invoke方法返回的對象是你自己指定的,我當(dāng)時返回的是null,null可不是整形啊,所以肯定會報錯的
但是但是:不是對象的所有方法都交給Handler,比如說調(diào)用Collection.getClass方法,這是因為繼承了Object的類,getClass是Object的方法,看文檔
只有這三個方法會用到Invoke方法,其他的object的方法將會有自己的調(diào)用
。
58、
?
總結(jié)
以上是生活随笔為你收集整理的Java高新技术笔记:反射、多线程、泛型、枚举、javaBean、代理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java学习笔记十五
- 下一篇: Java正则表达式:我最期望弄懂的知识,