1.
反射技術(shù):動態(tài)的獲取類以及類中的成員贴彼,并可以調(diào)用該成員
* 以前是有什么類爆阶,就new什么對象;沒有類缭黔,給什么類就new什么對象
*
* 無論new什么對象,都需要先獲取字節(jié)碼文件蒂破。
* 如何獲取呢馏谨?發(fā)現(xiàn)java已經(jīng)對字節(jié)碼文件進行了描述用的Class類完成的。
image.png
2.*
反射技術(shù):動態(tài)的獲取類以及類中的成員附迷,并可以調(diào)用該成員
* 以前是有什么類惧互,就new什么對象;沒有類喇伯,給什么類就new什么對象
*
* 無論new什么對象喊儡,都需要先獲取字節(jié)碼文件。
* 如何獲取呢稻据?發(fā)現(xiàn)java已經(jīng)對字節(jié)碼文件進行了描述用的Class類完成的艾猜。
*
* 如何獲取一個字節(jié)碼文件的對象呢?
* 方式一:Object getClass();
* 如 new Person().getClass().
* 弊端:方法一演示完發(fā)現(xiàn)在反射技術(shù)里該方法不合適,應(yīng)為反射技術(shù)不明確具體類的匆赃。
*
* 方式二:所有的數(shù)據(jù)類型都有自己的Class對象淤毛,表示方法很簡單。
* 每一個數(shù)據(jù)類型都有一個默認的靜態(tài)屬性—— .class算柳,用該屬性就可以獲取到字節(jié)碼文件對象
* Class clazz=Person.class;
* int.class;
* 每一種類型都具備
* 弊端:雖然不用對象調(diào)用了低淡,但還是要用具體的得調(diào)用靜態(tài)屬性
*
重點:
方式三:反射技術(shù)中最常用的方法:在Class類中找到了forName方法,通過名稱就可以獲取對性的字節(jié)碼文件對象瞬项。
* public static void methodDemo_3( ) throws ClassNotFoundException{
* String className = "cn.itcast.domain.person";//一定要把包名+類名寫全2榕啤!滥壕!
* Class clazz=Class.forName(className);
* System.out.println(clazz);
3.
newInstance( ) : 創(chuàng)建此Class對象所表示的類的一個實例纸颜。 如同使用一個帶有空參數(shù)列表的new表達式實例化對象,如果該類尚未初始化绎橘,則初始化這個類胁孙。
實例:
public class Person {
private int age;
private String name;
public Person() {
super();
}
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
}
package cn.itcast.reflect;
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
/*
* 演示如何根據(jù)給定名稱獲取到指定Class對象后建立該類的對象呢?
*/
getObject();
}
//空參數(shù)構(gòu)造函數(shù)
private static void getObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//1.根據(jù)給定的類名獲取Class對象
String name="cn.itcast.domain.Person";
Class clazz=Class.forName(name);//通過名稱就可以獲取對性的字節(jié)碼文件對象
Object obj=clazz.newInstance();//創(chuàng)建一個Person類對象称鳞,默認調(diào)用該類的空參數(shù)構(gòu)造函數(shù)
// java.lang.InstantiationException:沒有調(diào)用到與之對應(yīng)的構(gòu)造函數(shù)
//記住涮较,一般被反射得的類都帶有空參數(shù)構(gòu)造函數(shù)。
//Person p=new Person()冈止;
}
}
new對象的另外一種方式狂票,通過指定構(gòu)造器完成:
private static void getObject2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String name="cn.itcast.domain.Person";
Class clazz=Class.forName(name);//通過名稱就可以獲取對性的字節(jié)碼文件對象
/*
* 萬一給定類中沒有空參數(shù)呢?
* 可以先獲取指定的構(gòu)造函數(shù)熙暴,再通過該構(gòu)造函數(shù)進行實例化闺属。
*/
//1.通過Class獲取指定構(gòu)造函數(shù),比如兩個參數(shù)
Constructor cons=clazz.getConstructor(String.class,int.class);//類型對象
Object obj=cons.newInstance("aaa",23);
}
5.字節(jié)碼文件對象的其他方法:
:getxxx():獲取公有的
getDeclaredXXX():可以獲取私有的
String className="cn.itcast.domain.Person";
Class clazz=Class.forName(className);
//獲取指定age字段
//Field field =clazz.getField("age");//該方法只能獲取公有的
Field field=clazz.getDeclaredField("age");//該方法可以獲取私有的
System.out.println(field);
暴力訪問字節(jié)碼對象值:
//要對非靜態(tài)的字段必須有對象
Object obj=clazz.newInstance();
//需要使用父類的方法將權(quán)限檢查能力取消周霉。
field.setAccessible(true);//如果沒有這一步會報錯掂器,因為age是私有的,不能直接獲取
field.set(obj, 40);
System.out.println(field.get(obj) );
代碼如下:
package cn.itcast.reflect.field;
import java.lang.reflect.Field;
public class ReflectFieldDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
getFieldDemo();
}
private static void getFieldDemo() throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
String className="cn.itcast.domain.Person";
Class clazz=Class.forName(className);
//獲取指定age字段
//Field field =clazz.getField("age");//該方法只能獲取公有的
Field field=clazz.getDeclaredField("age");//該方法可以獲取私有的
System.out.println(field);
//要對非靜態(tài)的字段必須有對象
Object obj=clazz.newInstance();
//需要使用父類的方法將權(quán)限檢查能力取消俱箱。
field.setAccessible(true);//如果沒有這一步會報錯国瓮,因為age是私有的,不能直接獲取
field.set(obj, 40);
System.out.println(field.get(obj) );
}
}
6.動態(tài)地獲取方法 類中的字段構(gòu)造函數(shù)方法
person類:
package cn.itcast.domain;
public class Person {
private int age;
private String name;
public Person() {
super();
}
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
public void show(){
System.out.println("Person show run");
}
public static void staticShow(){
System.out.println("Person static show run");
}
public void paramShow(String name,int age){
System.out.println("show"+name+"----"+age);
}
}
package cn.itcast.reflect.method;
import java.lang.reflect.Method;
public class ReflectMethodDemo {
public static void main(String[] args) throws Exception {
getMethodDemo();
getMethodDemo2();
getMethodDemo3();
}
//反射方法狞谱,非靜態(tài)乃摹,無參數(shù)的show方法。
private static void getMethodDemo() throws Exception {
String className="cn.itcast.domain.Person";
Class clazz=Class.forName(className);
//反射方法跟衅,非靜態(tài)孵睬,無參數(shù)的show方法。
Method method=clazz.getMethod("show", null);
Object obj=clazz.newInstance();
//方法的調(diào)用運行
method.invoke(obj, null);
}
//反射方法与斤,靜態(tài)肪康,無參數(shù)的show方法。
private static void getMethodDemo2() throws Exception {
String className="cn.itcast.domain.Person";
Class clazz=Class.forName(className);
//反射方法撩穿,靜態(tài)磷支,無參數(shù)的show方法。
Method method=clazz.getMethod("staticShow", null);
//這里不需要創(chuàng)建實例對象 因為靜態(tài)
//方法的調(diào)用運行
method.invoke(null,null);
}
//反射方法食寡,非靜態(tài)雾狈,帶參數(shù)的show方法。
private static void getMethodDemo3() throws Exception {
String className="cn.itcast.domain.Person";
Class clazz=Class.forName(className);
//反射方法抵皱,靜態(tài)善榛,帶參數(shù)的show方法。
Method method=clazz.getMethod("paramShow",String.class,int.class);
Object obj=clazz.newInstance();
method.invoke(obj, "hhaha",20);
}
}
結(jié)果:
7.反射技術(shù)--應(yīng)用場景
希望后期出現(xiàn)了設(shè)備后呻畸,可以不修改NoteBookMain的代碼移盆,還可以不斷加入新設(shè)備,就是反射技術(shù)
筆記本類 class NoteBook:
package 反射技術(shù);
public class NoteBook {
public void run(){
System.out.println("notebook run");
}
/*
* 使用USB設(shè)備
*/
public void useUSB(USB usb){
if(usb!=null){
usb.open();
usb.close();
}
}
}
USB接口:
package 反射技術(shù);
public interface USB {
void open();
void close();
}
實現(xiàn)USB接口的鼠標類:
package 反射技術(shù);
public class MouseByUSB implements USB {
public void open() {
System.out.println("mouse close");
}
@Override
public void close() {
System.out.println("mouse open");
}
}
配置文件:
NoteBookMain筆記本實類:
package 反射技術(shù);
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class NoteBookMain {
public static void main(String[] args) throws IOException, Exception {
NoteBook book=new NoteBook();
book.run();
book.useUSB(null);
//因為有了鼠標,所以在需要的源程序中伤为,創(chuàng)建鼠標對象并傳到筆記本
//希望后期出現(xiàn)了設(shè)備后咒循,可以不修改NoteBookMain的代碼,還可以不斷加入新設(shè)備,就是反射技術(shù)
//book.useUSB(new MouseByUSB());通過反射來解決問題
//對外提供配置文件
File configFile=new File("usb.properties");
if(!configFile.exists()){
configFile.createNewFile();
}
//讀取流和配置文件關(guān)聯(lián)
FileInputStream fis=new FileInputStream(configFile);
Properties prop=new Properties();
//將流中的數(shù)據(jù)加載到prop
prop.load(fis);
for(int x=1;x<=prop.size();x++){
String classname=prop.getProperty("usb"+x);
//根據(jù)設(shè)備名字找到設(shè)備的類
Class clazz=Class.forName(classname);
//把類new成對象绞愚,把對象強轉(zhuǎn)換為USB類型
USB usb=(USB)clazz.newInstance();
book.useUSB(usb);
}
fis.close();
}
}
反射技術(shù)完結(jié)叙甸,撒花!