反射就是把Java類中各種成分,映射成相應的java類。
關鍵字:Class 代表一類事物。點擊打開鏈接 點擊打開鏈接 點擊打開鏈接 點擊打開鏈接 點擊打開鏈接
getName();getPackage(); getMethod() getInterfaces() .....
語法:Class cls1 = 字節碼;
三種方式得到字節碼:
(1)類名.class 例如 System.class
(2)對象.getClass 例如 new Date().getClass
(3)Class.forName("類名") ; 例子 Class.forName(" java.util.Date");
九個預定義對象: 八個基本類型+ void
方法:isPrimitive()來判斷是否是基本類型。
int.class ==Integer.TYPE true
數組類型Class實例對象 isArray()判斷是否是數組。
在源程序中出現的類型都有各自的Class實例對象,例如 int[ ] ...
Filed, Method,constructor package
constructor 代表某個類中的一個構造方法
getConstructors 得到所有的構造方法
getConstructor 得到一個構造方法
例子:
Constructor constructors[ ] = ClassforName("java.lang.String").getConstructors();
Constructor constructor = ClassforName("java.lang.String").getConstructor(StringBuffer.class);
簡單的描述來區分new關鍵字和newInstance()方法的區別:
newInstance: 弱類型。低效率。只能調用無參構造。
new: 強類型。相對高效。能調用任何public構造。
創建實例對象:
通常方式:
String str = new String (new StringBuffer("abc"));
反射方式:
String str = (String)constructor.newInstance(new StringBuffer("abc"));
(1) //先獲得構造方法
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
//注意類型的強轉
(2) String str2 =(String) constructor1.newInstance(new StringBuffer("abc"));
調用獲得的方法時,要用到上面相同類型的實例對象。
Class.newInstance()方法
例子:
String obj = (String) Class.forName("java.lang.String").newInstance();
該方法內部先得到默認的構造函數,然後用該構造方法創建實例對象。
package cn.itcast.day1;
publicclass ReflectPoint {
privateintx;
publicinty;
public ReflectPoint(int x,int y) {
super();
this.x = x;
this.y = y;
}
}
Filed 代表某個類中的成員變量,
字節碼.getField("str");
打印成員變量具體的值,getField("str").get("對象");
獲取聲明的變量
getDeclaredField
暴利反射
fieldx.setAccessible(true);
//得到所有的成員變量
Field[] fields = obj.getClass().getFields();
字節碼的比較用“==”
ReflectPoint rp1 = new ReflectPoint(3,5);
//獲得成員變量對應的類
Field fieldy = rp1.getClass().getField("y");
//打印具體對象的值
System.out.println(fieldy.get(rp1));
//x是私有的方法變爲getDeclaredField();
Field fieldx = rp1.getClass().getDeclaredField("x");
//暴力反射
fieldx.setAccessible(true);
System.out.println(fieldx.get(rp1));
privatestaticvoid changeStringValue(Object obj)throws Exception{
//得到所有的成員變量
Field[] fields = obj.getClass().getFields();
//遍歷找到
for(Field field :fields){
//如果類型是String類型
if(field.getType()==String.class){
//得到值,
String oldValue = (String)field.get(obj);
//進行替換
String newValue = oldValue.replace('b','a');
//設置新的值
field.set(obj, newValue);
}
}
}
Method類:
Method類代表某個類的方法成員。
得到類中的某一個方法:
Method chaAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
字節碼.getMethod(name, parameterTypes)
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
invoke();
public Object invoke (Object obj, Object . . . args)
obj 調用底層方法的對象,
args用於方法調用的參數。
返回使用參數args 在obj上使用該對象所表示方法的結果
調用方式:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke( str, 1 ));
如果傳遞給Method對象的invoke()方法一個參數爲null,這說明該Method對象對應一個靜態方法。
mainMethod().invoke(null , new Object [ ] { new String [ ] { " "," ". . . } });
mainMethod( ).invoke(null , (Object) new String [ ] { " "," ". . . });
用反射的方式執行某個類中的main方法。
String startingClassName = args[0];
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
//main接收一個字符串數組,一個參數。需要進行處理。兩種方式:
mainMethod.invoke(new TestArguments(),new Object[] {new String[ ]{"111","222","333"}});
//強轉成一個對象
mainMethod.invoke(null, (Object)new String[ ] {"1","2","3"});
Arrays工具類用於完成對數組的反射操作。
具有相同的維數和元素類型的數組屬於同一個類型,即具有相同的Class實例對象。
代表數組的Class實例對象的getSuperClass( )方法返回的父類爲Object類對應的Class
基本類型的以爲數組可以被當做Object類型使用,不能當做Object [ ]使用
非基本類型的一維數組,既可以當做Object類型使用,又可以當做Object[ ]類型使用。
Arrays.asList( )方法處理 int[ ]和String [ ]時的差異。
先將數組轉成List對象
String [ ] a4 = new String[ ]{"a","b","c"};
System.out.println(Arrays.asList(a4));
printObject(a4); a b c
printObject("xyz"); xyz
構造方法printObject打印數組。
private static voidprintObject(Object obj) {
Class cla1 = obj.getClass();
if(cla1.isArray()){
int len = Array.getLength(obj);
for(int i =0;i<len;i++){
System.out.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}
hashCode()是用來產生哈希碼的,而哈希碼是用來在散列存儲結構中確定對象的存儲地址的,
hashCode()方法使用來提高Map裏面的搜索效率的,Map會根據不同的hashCode()來放在不同的
區域段裏面,Map在搜索一個對象的時候先通過hashCode()找到相應的區域段,然手再根據
equals()方法找到相應的對象。
兩個相等對象的equals方法一定爲true,但兩個hashcode相等的對象不一定是相等的對象。
所以hashcode相等只能保證兩個對象在一個Hash表裏的同一條hash鏈上,繼而通過equals方法才能確定
是不是同一個對象,如果結果爲true,則認爲是同一對象不再插入,否則認爲是不同對象
繼續插入。
只有類的實例對象要被採用哈希算法進行存儲和檢索是,這個類才需要按要求覆蓋hashCode
方法。即使程序可能暫時不會用到當前類的hashCode方法,但是爲它提供一個hashCode
方法也不會有什麼不好,只是未雨綢繆。所以,通常要求hashCode方法和equals方法一併被
同時覆蓋。
提示
(1)通常來說,一個類的兩個實例對象用equals( )方法比較的結果相等時,他們的哈希碼也
必須相等,但反之則不成立,即equals方法比較不相等的對象可以有相同的哈希碼,或者說哈希
碼相同的兩個對象的equals方法比較的結果可以不等,例如,“BB”和“AA”的equals
方法比較結果肯定不相等,但他們的hashCode方法返回值卻相等。
(2)當一個對象被存儲進HashSet集合以後,就不能修改這個對象中那些參與計算哈希值的字段了
,否則,對象修改後的哈希值與最初存儲進HashSet集合中時的哈希值就不同了,在這種情況下
即使在contains方法使用該對象的當前引用作爲的參數去HashSet集合中檢索對象,也將返回
找不到對象的結果,這也會導致無法從HashSet集合中單獨刪除當前對象,從而造成內存泄露。
反射的作用:實現框架功能。
房子 門 鎖
(框架) (客戶) (工具類)
工具類被用戶的類調用,
框架則是調用用戶提供的類。
例子:
(1)設置一個 . properties文件
(2)讀取配置文件中類的名字
(3)利用上一步結果,創建新的實例,這樣整個程序中不會有new()
//讀取配置文件
//InputStream is = new FileInputStream("config.properties");
類加載器,加載資源
//InputStream is = ReflectTest2.class.getClassLoader().getResourceAsStream("cn\\itcast\\day1\\config.properties");
//InputStream is = ReflectTest2.class.getResourceAsStream("Resourse\\config.properties");
InputStream is = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/Resourse/config.properties");
//問:" \ " 和 " / " 在路徑表示的時候有什麼區別
//創建Properties對象
Properties prop = new Properties();
//加載配置文件
prop.load(is);
is.close();
//指定字符串classname爲類名
String classname = prop.getProperty("classname");
//創建實例對象。無參構造方法,創建實例對象。
Collection collections =(Collection) Class.forName(classname).newInstance();
在MyEclipse中如果源文件目錄中有非. java文件 那麼會自動複製到classpath下
未來學習的框架:配置文件都是放在classpath路徑下
config.properties
name value
classname java.util.HashSet
---------------------- android培訓、java培訓、期待與您交流! ----------------------詳細請查看:http://edu.csdn.net/heima