黑馬程序員---Java中使用反射
1. 反射概念
反射就是將一個類的class文件,封裝成一個對象
從class中獲取(解剖)類中的成員,並且運行起來
反射有關係的類
java.langClass 封裝class文件的
java.lang.reflect.Constructor 封裝構造方法的
java.lang.reflect.Field 封裝成員變量的
java.lang.reflect.Method 封裝成員方法的
//以下所有代碼的演示都會使用此類
/*
*
* 用於反射演示的Person類
*
*/
public class Person {
private String name;
private int age;
public String email;
public Person(){System.out.println("空參賽構造");}
public Person(String name,int age){
this.age = age;
this.name = name;
System.out.println("兩個參數構造");
}
public Person(String name)
{
this.name = name;
System.out.println("私有構造");
}
//定義多個普通方法
public void speak()
{
System.out.println("say");
}
public void show(int x)
{
System.out.println("一個人的x"+x);
}
public String toString()
{
return "Person " +name+"......"+age+"..."+email;
}
// {
// System.out.println("構造代碼要建對象,才運行");
// }
//
// static{
// System.out.println("靜態代碼塊,加載類的時候運行");
// }
}
//==================================================
2.獲取反射的三種方式
編譯後的class文件,對象的方式
描述類是Class,三種方式的返回值類型也是Class類型
A. 對象.getClass()
B. 類名.class
C. Class.forName()獲取
推薦使用:Class.forName方式獲取一個類的字節碼文件對象 靈活方便,你的類名可以通過字符串參數傳遞的
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//第一種,通過對象獲取 Object類的方法 class<?> getClass()
Person p = new Person();
Class c1 = p.getClass();
System.out.println(c1);
//第二種,通過類,直接獲取,多線程中,任何一個數據類型,都有一個靜態成員變量class
//靜態成員變量,返回這個累的class的文件對象
Class c2 = Person.class;
System.out.println(c2);
System.out.println(c1==c2);//t
System.out.println(c1.equals(c2));//t
//以上結果都是T,因爲你的Person.class 對象只有一份
//第三種,通過forName(String className)
Class c3 = Class.forName("cn.itcast.reflects.Person");
System.out.println(c3);
// method("cn.itcast.reflects.Person") //推薦這種方式
}
private static void method(String className) throws ClassNotFoundException
{
Class c = Class.forName(className);
System.out.println(c);
}
}
//==================================================
3. 通過class文件對象,獲取構造方法並運行構造方法
Class類的方法Constructor<?>[] getConstructors() 公共權限的
獲取構造方法,返回數組
Constructor返回值類型,是描述構造方法的類
Class類的方法獲取一個構造方法
Constructor getConstructor(Class...c)傳遞參數,傳遞和構造方法一致的參數,就可以獲取到構造方法了
獲取到了構造方法,如何運行呢
Constructor類方法 Object newInstance(Object... initargs) 創建類的對象,構造方法就運行了
//反射獲取構造方法並運行
import java.lang.reflect.*;
public class ReflectDemo1 {
public static void main(String[] args) throws Exception {
//獲取Person字節碼文件對象
Class clazz = Class.forName("cn.itcast.reflects.Person");
//通過字節碼文件對象獲取構造方法getConstructors方法,返回構造方法數組
Constructor[] cons = clazz.getConstructors();
for(Constructor c : cons){
System.out.println(c);
}
//獲取一個構造方法,並運行
Constructor con = clazz.getConstructor();
System.out.println(con);
Object obj = con.newInstance();
System.out.println(obj);
//獲取一個有參數的構造方法,並運行‘
Constructor con2 = clazz.getConstructor(String.class,int.class); //
System.out.println(con2);
obj = con2.newInstance("張三",23);
System.out.println(obj);
}
}
//===================
獲取私有構造方法,並運行,單例模式無效了
Class類的getDeclaredConstructor()獲取私有的構造方法
void setAccessible(boolean flag) 方法是Constructor父類AccessibleObject類的方法
運行時期,取消Java檢查(權限)
,暴力訪問
//獲取私有構造方法運行
import java.lang.reflect.*;
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("cn.itcast.reflects.Person");
//獲取私有構造
/* Constructor[] cons = clazz.getDeclaredConstructors();
for(Constructor c : cons){
System.out.println(c);
}*/
Constructor con = clazz.getDeclaredConstructor(String.class);
con.setAccessible(true);
Object obj = con.newInstance("haha");
System.out.println(obj);
}
}
//=====
/*
* 反射打破單例模式
*/
import java.lang.reflect.Constructor;
class Single{
private Single (){}
private static final Single s = new Single();
public static Single getInstance(){
return s;
}
}
public class ReflectDemo4 {
public static void main(String[] args) throws Exception{
Class clazz = Class.forName("cn.itcast.reflects.Single");
Constructor con = clazz.getDeclaredConstructor();
con.setAccessible(true);
Object obj = con.newInstance();
System.out.println(obj);
obj = con.newInstance();
System.out.println(obj);
}
}
//==================================================
4. 通過class文件對象,獲取成員變量,並修改值
Class類的方法Field[] getFields()類中的成員變量,公共的
Class類的方法 Field getField(String name) 獲取指定的成員變量,公共的
傳遞一個變量名
Field類的方法set(obj,修改後的新值)修改值
/*
* 獲取成員變量,並運行
*/
import java.lang.reflect.*;
public class ReflectDemo5 {
public static void main(String[] args)throws Exception {
Class clazz = Class.forName("cn.itcast.reflects.Person");
//利用Class類的方法getFields()獲取成員變量
/*Field[] fields = clazz.getFields();
for(Field f : fields){
System.out.println(f);
}*/
Object obj = clazz.newInstance();
//獲取一個成員變量email
Field field = clazz.getField("email");
field.set(obj, "[email protected]");
System.out.println(obj);
//獲取私有成員變量age修改值
Object obj2 = clazz.newInstance();
Field field2 = clazz.getDeclaredField("age");
field2.setAccessible(true); //暴力訪問
field2.set(obj2, 333);
System.out.println(obj2);
}
}
//==================================================
5. 通過class文件對象,獲取成員方法,並運行
Class類的方法 Method[] getMethods()獲取類中,所有的公共的成員方法,包括繼承的
Class類的方法,Method getMethod(字符串的方法名,要獲取的方法的參數列表)獲取一個方法
Method類中有一個方法,可以運行獲取到的方法,名字invoke(對象,運行方法時傳遞的實際參數列表...)
運行方法的方法
Class類的方法Method[] getDeclaredMethods() 公共的,私有的,受保護,但是不包括繼承的
//反射獲取成員方法,並運行
import java.lang.reflect.*;
public class ReflectDemo6 {
public static void main(String[] args) throws Exception{
Class clazz = Class.forName("cn.itcast.reflects.Person");
//通過Class類的方法getMethods()
/* Method[] method = clazz.getMethods();
for(Method m : method)
{
System.out.println(m);
}*/
Object obj = clazz.newInstance();
//獲取一個成員方法
Method method1 = clazz.getMethod("speak");
//
//使用Method類的invoke方法,運行獲取到的方法
method1.invoke(obj);
//獲取一個參數的 int show方法運行
Method method2 = clazz.getMethod("show", int.class);
method2.invoke(obj, 123);
}
}
//================
/*
* 獲取私有的成員方法運行
*/
import java.lang.reflect.*;
public class ReflectDemo7 {
public static void main(String[] args)throws Exception {
Class clazz = Class.forName("cn.itcast.reflects.Person");
Method[] methods = clazz.getDeclaredMethods();
for(Method m : methods){
System.out.println(m);
}
Object obj = clazz.newInstance();
//獲取私有的run方法
Method method = clazz.getDeclaredMethod("run");
method.setAccessible(true);
method.invoke(obj);
}
}
//=====================================
反射繞過編譯器檢查,將不同的數據類型,存儲到帶有泛型的集合(泛型的擦除)
import java.lang.reflect.*;
import java.util.*;
public class GenericReflect {
public static void main(String[] args)throws Exception {
ArrayList<String> array = new ArrayList<String>();
array.add("123");
//Class clazz =Class.forName("cn.itcast.reflects.GenericReflect");
Class clazz = array.getClass();
//Class clazz = GenericReflect.class;
Method method = clazz.getMethod("add", Object.class);//改成了Object類型的
method.invoke(array, 123);
method.invoke(array,false);
System.out.println(array);
Iterator it = array.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.