反射
概述:
反射不需要程序員自己實現,都是底層框架或者JVM去使用的一個技術.
專門用來解析 .class文件里 的所有數據 (公開的,私有的)
2,原理
把解析 到的 .class里的數據 封裝成了Class工具類
3,怎么獲取Class對象
Class對象是 封裝了.class文件里的數據 ,,可以通過Class對象提供的種方法解析數據
static Class<?> forName(String className)
類名.class
對象.getClass()

反射
測試獲取Class對象
public class C1 {
public static void main(String[] args) throws ClassNotFoundException {
method();//獲取Class對象
}
//獲取Class對象--用來解析.class文件里的所有數據
public static void method() throws ClassNotFoundException {
//參數是類的全路徑 -- 包名.類名
Class c = Class.forName("java.lang.String");
Class c2 = String.class;
Class c3 = new String().getClass();
System.out.println(c);
System.out.println(c2);
System.out.println(c3);
}
}
反射Student類里的所有信息
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class C1_Student {
public static void main(String[] args) throws Exception {
//1,獲取Student類的Class對象
Class s = Student.class;
//method(s);//解析 構造方法
//method2(s);//解析 成員變量
//method3(s);//解析 成員方法
//method4(s);//用反射 創建對象
//method5(s);//用反射 設置變量的值
method6(s);//用反射 執行方法
}
//用反射 執行方法
public static void method6(Class s) throws Exception {
//獲取指定的方法 public void test(int a)
Method m = s.getMethod("test", int.class);
Object o = s.newInstance();
//invoke(m,n)--m是對象--n是要給方法傳入的參
m.invoke(o,50);//執行方法
}
//用反射 設置變量的值
public static void method5(Class s) throws Exception {
//TODO public String name ;
Field f = s.getField("name");
Object o = s.newInstance();
//set(m,n)--m是對象--n是想要設置啥值
f.set(o,"jack");//設置值
System.out.println( f.get(o) );//獲取值
}
//用反射 創建對象
public static void method4(Class s) throws Exception{
//用反射new --自動調用無參構造
Object o = s.newInstance();
Student s2 = (Student) o ;//向下轉型,目的是使用子類的特有功能
s2.show();//使用了Student類里功能
}
//解析Student.class文件中的 成員方法
//getMethods() getMethod() -- 獲取自己和父類的所有 公開的方法
public static void method3(Class s) throws NoSuchMethodException {
//獲取 所有方法
Method[] ms = s.getMethods();
//遍歷數組,獲取每個方法m
for (Method m : ms) {
System.out.println( m.getName() );//獲取方法名
Class[] c = m.getParameterTypes();//獲取參數類型
System.out.println( Arrays.toString(c) );
}
//TODO 獲取 特定的方法 public void test(int a)
Method m = s.getMethod("test", int.class);
System.out.println( m.getName() );
}
//解析Student.class文件中的 成員變量
//getFields() getField() --獲取公開的
public static void method2(Class s) throws Exception {
//獲取所有 成員變量們~~~~
Field[] fs = s.getFields();
//遍歷,得到每個成員變量f
for (Field f : fs){
//獲取變量名
System.out.println(f.getName());
//獲取變量類型
System.out.println(f.getType().getName());
}
//根據屬性名獲取屬性
Field f = s.getField("name");
//獲取屬性類型
System.out.println(f.getType().getName());
}
//解析Student.class文件中的構造方法
//getConstructors() getConstructor()--獲取公開的
public static void method(Class s) throws NoSuchMethodException {
//獲取 所有的構造方法 存入Constructor[]
Constructor[] cs = s.getConstructors();
//遍歷數組,得到每個構造方法c
for (Constructor c: cs
) {
//獲取構造方法的 名稱
System.out.println(c.getName());
//TODO 解析構造方法的 參數的類型
Class[] cc =c.getParameterTypes();
System.out.println(cc);
}
//TODO 獲取指定的構造方法 --public Student(int age)
//getConstructor()的參數是 構造方法的參數類型 的Class對象
Constructor con = s.getConstructor(int.class);
System.out.println(con.getName()+"--");
}
}
暴力反射
--1,概述
專門用來 反射 類中的 公開數據 和 私有數據
--2,新的API
--普通反射 -- 只能獲取public的
getMethod()
getMethods()
getField()
getFields()
getConstructor()
getConstructors()
--暴力反射 --除了public的甚至連private都可以獲取
getDeclaredMethod()
getDeclaredMethods()
getDeclaredField()
getDeclaredFields()
getDeclaredConstructor()
getDeclaredConstructors()
--創建Person類
public class Person {
private String name;
int age;
public char sex;
private void show(){
System.out.println("show..");
}
void test(int a){
System.out.println("test.."+a);
}
}
--創建測試類
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test3_Person {
public static void main(String[] args) throws Exception {
// method();//暴力反射 成員變量
method2();//暴力反射 成員方法
}
//TODO 暴力反射成員方法
public static void method2() throws Exception {
Class c = Person.class;
//暴力反射--獲取所有方法
Method[] ms = c.getDeclaredMethods();
//遍歷數組,獲取每個方法m
for (Method m : ms) {
//獲取方法名
System.out.println(m.getName());
}
//TODO 獲取指定的方法
Method m = c.getDeclaredMethod("show");
Object oo = c.newInstance();
m.setAccessible(true);//開啟 私有資源的 訪問權限
m.invoke(oo);
}
//TODO 暴力反射成員變量
public static void method() throws Exception {
Class c = Person.class;
//暴力反射--獲取所有屬性,包括 public的private的default的
Field[] fs = c.getDeclaredFields();
//遍歷數組,得到每個屬性f
for (Field f : fs) {
//獲取屬性名
System.out.println( f.getName() );
}
//只獲取一個私有的屬性
Field f = c.getDeclaredField("name");
Object o = c.newInstance();
//對私有的屬性操作拋出異常:IllegalAccessException
f.setAccessible(true);//開啟私有的訪問權限
f.set(o,"jack");//設置值
System.out.println( f.get(o) );//獲取值
}
}
反射和暴力反射的區別
總結:
1, 普通反射 和 暴力反射 的區別 ?
暴力反射是可以獲取public的甚至private
普通反射只能獲取public的
2, 怎么使用暴力反射?
用對API ( getDeclaredXxx() )
設置訪問權限( setAccessible(true) )
3, getDeclaredXxx() 和 getXxx() 的區別??
getXxx() 獲取public資源 -- 獲取自己的方法和父類的方法
getDeclaredXxx() 獲取所有資源 --只獲取自己的方法