黑馬程序員_Java反射機制

------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! -------


    JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。

注意:反射是在運行的時候進行的,不是在編譯的時候運行的。

1 反射的功能

    Java反射機制主要提供了以下功能:
          在運行時判斷任意一個對象所屬的類;
          在運行時構造任意一個類的對象;
          在運行時判斷任意一個類所具有的成員變量和方法;
          在運行時調用任意一個對象的方法;生成動態代理。


2 API簡介

    在這裏先看一下sun爲我們提供了那些反射機制中的類:

  — java.lang.Class;        代表一個類

  — java.lang.reflect.Constructor; 代表類的構造方法 

  — java.lang.reflect.Field;        代表類的成員變量(成員變量也稱爲類的屬性)

  — java.lang.reflect.Method;  代表類的方法

  — java.lang.reflect.Array;  提供了動態創建數組,以及訪問數組的元素的靜態方法



注意:java中無論生成某個類的多少對象, 這些對象都會對應於同一個Class對象。

3 方法介紹

方法關鍵字

含義

getDeclaredMethods()

獲取所有的方法

getReturnType()

獲得方法的放回類型

getParameterTypes()

獲得方法的傳入參數類型

getDeclaredMethod("方法名",參數類型.class,……)

獲得特定的方法

 

 

構造方法關鍵字

含義

getDeclaredConstructors()

獲取所有的構造方法

getDeclaredConstructor(參數類型.class,……)

獲取特定的構造方法

 

 

父類和父接口

含義

getSuperclass()

獲取某類的父類

getInterfaces()

獲取某類實現的接口


4 獲取Class的三種方式

1)、使用Class類的forName(String className)靜態方法。改方法需要傳入字符串參數,改字符串參數的值是某個類的全限定類名(必須添加完整的包名)。
Class.forName("java.lang.String");

2)、調用某個類的class屬性來獲取該類對應的class對象,如

Class.forName("java.lang.String");

3)、調用某個對象的getClass方法。
String s = "aa";
Class<?> clazz = s.getClass();

5 生成對象

1)、通過不帶參數的構造方法生成對象有兩種方法
     a)、先獲得Class對象,然後通過該Class對象的newInstance()方法直接生成即可:
  newInstance()方法可以返回一個實例,但是構造方法要是沒有參數列表的,它相當於調用某個類的不帶參數的構造方法,但是如果在初始化對象的時候要傳參數,就要使用Constructor

Class<?> classType = String.class;
Object obj = classType.newInstance();
       
       b)、先獲得Class對象,然後通過該對象獲得相應的Constructor對象,再通過該Constructor對象的newInstance()方法生成:
Class<?> classType = object.getClass();
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});

2)、若想通過類的帶參數的構造方法生成對象,只能使用下面一種方式:
   Class<?> classType = object.getClass();
   Constructor cons = classType.getConstructor(new Class[]{String.class,int.class});
   Object obj = cons.newInstance(new Object[]{"hello",3});

    例子:
public class ReflectTester
{
 
 //方法實現對Customer對象的拷貝操作
 public Object copy(Object object) throws Exception
 {
  Class<?> classType = object.getClass();
  /*Constructor cons = classType.getConstructor(new Class[]{});
 
  Object obj = cons.newInstance(new Object[]{});
  System.out.println(obj);
  System.out.println("-----------");*/
 
  //以上的兩行代碼等價於下面一行
  //Object obj2 = classType.newInstance();
  Constructor cons2 = classType.getConstructor(new Class[]{String.class, int.class});
  Object obj2 = cons2.newInstance(new Object[]{"hello",3});
  System.out.println(obj2);
 
  return null;
 }
 
 public static void main(String[] args) throws Exception {
  ReflectTester test = new ReflectTester();
  test.copy(new Customer());
 }
 
}
class Customer
{
 private Long id;
 
 private int age;
 
 private String name;
 
 public Customer()
 {
 
 }
 
 public Customer(String name,int age)
 {
  this.name = name;
  this.age= age;
 }
 public Long getId() {
  return id;
 }
 public void setId(Long id) {
  this.id = id;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 
}

6 反射生成多維數組

import java.lang.reflect.Array;
/**
 *
 * 用反射構造一個多維數組
 *
 */
public class ArrayTester2 {
 public static void main(String[] args) {
  int[] dims = new int[]{5,10,15};
 
  //newInstance()方法的第二個參數是代表生成數組的維度,所以生成的數組維度爲5,10,15,長寬高
  Object array = Array.newInstance(Integer.TYPE,dims);
 
  //arrayObj是一個二維的數組
  Object arrayObj = Array.get(array,3);
 
  Class<?> classType = arrayObj.getClass().getComponentType();
 
  //arrayObj是一個一維的數組
  arrayObj = Array.get(arrayObj, 5);
 
  Array.setInt(arrayObj, 10, 37);
 
  int[][][] arrayCast = (int[][][])array;
 
  System.out.println(arrayCast[3][5][10]);
 }
}


反射訪問私有(private)的方法
    private 限制的方法沒有辦法在另外的類中使用,但可以使用反射進行使用。而getMethod()方法只能獲取public的方法。如果要使用private的方法就要使用           getDeclaredMethod()方法。

例子1、獲取privete方法、
public class PrivateTest {
 private String sayHello(String name)
 {
    return "hello" + name;
 }
}
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestPrivate {
 public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
  PrivateTest p = new PrivateTest();
 
  Class<?> classType = p.getClass();
 
  Method method = classType.getDeclaredMethod("sayHello", new Class[]{String.class});
 
  method.setAccessible(true); //壓制java的訪問控制檢查
 
  String str = (String)method.invoke(p, new Object[]{"aaa"});
 
  System.out.println(str);
 
 }
 
}

例子2、改變private的屬性
public class Private2 {
 private String name = "zhangsan";
 
 public String getName()
 {
  return name;
 }
}
/**
 *
 * 將Private2中的private屬性name的值變爲李四
 *
 */
public class TestPrivate2{
 
 public static void main(String[] args) throws Exception
 {
  Private2 p = new Private2();
 
  Class<?> classType = p.getClass();
 
  Field field = classType.getDeclaredField("name");
 
  field.setAccessible(true);
 
  field.set(p, "lisi");
 
  System.out.println(p.getName());
 }
 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章