黑馬程序員---Java中使用反射

                                                   關於Java中的反射
                 --------- android培訓java培訓、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());
  }
 }
}

                          --------- android培訓java培訓、java學習型技術博客、期待與您交流! ------------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章