转载

java 反射机制

JAVA反射机制是在 运行状态中 ,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

注意:反射是在 运行的时候 进行的,不是在编译的时候运行的。

反射的功能

Java反射机制 主要 提供了以下 功能

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;生成动态代理。

API简介

在这里先看一下 sun 为我们提供了那些反射机制中的类:

— java.lang.Class;        代表一个类

— java.lang.reflect.Constructor; 代表类的构造方法

— java.lang.reflect.Field;        代表类的成员变量(成员变量也称为类的属性)

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

— java.lang.reflect.Array; 提供了动态创建数组,以及访问数组的元素的静态方法

注意:java中无论生成某个类的多少对象, 这些对象都会对应于同一个Class对象。

方法介绍

方法关键字

含义

getDeclaredMethods ()

获取所有的方法

getReturnType ()

获得方法的放回类型

getParameterTypes ()

获得方法的传入参数类型

getDeclaredMethod("方法名",参数类型.class,……)

获得特定的方法

构造方法关键字

含义

getDeclaredConstructors ()

获取所有的构造方法

getDeclaredConstructor(参数类型.class,……)

获取特定的构造方法

父类和父接口

含义

getSuperclass ()

获取某类的父类

getInterfaces ()

获取某类实现的接口

获取Class的三种方式

1)、使用 Class类 的forName(String className)静态方法。改方法需要传入字符串参数,改字符串参数的值是某个类的全限定类名(必须添加完整的包名)。

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

2)、调用某个 的class属性来获取该类对应的class对象,如

String.class

3)、调用某个 对象 的getClass方法。

String s = "aa"; Class<?> clazz = s.getClass();

生成对象

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;  }   }

相对复杂的例子

import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectTester {    //方法实现对Customer对象的拷贝操作  public Object copy(Object object) throws Exception  {   Class<?> classType = object.getClass();    Object ObjectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});     //获得成员变量     Field[] fields = classType.getDeclaredFields();   for(Field field : fields)   {    String name = field.getName();        String firstLetter = name.substring(0,1).toUpperCase(); //将属性的首字母转换为大写        String getMethodName = "get" + firstLetter + name.substring(1);        String setMethodName = "set" + firstLetter + name.substring(1);        Method getMethod = classType.getMethod(getMethodName, new Class[]{});        Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()});        Object value = getMethod.invoke(object, new Object[]{});        setMethod.invoke(ObjectCopy, new Object[]{value});       }       return ObjectCopy;  }    public static void main(String[] args) throws Exception {   Customer customer = new Customer("tom",20);     customer.setId(1L);     ReflectTester test = new ReflectTester();     Customer cus = (Customer)test.copy(customer);     System.out.println(cus.getAge()+","+cus.getName()+","+cus.getId());  }   } 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;  }   }

注意:Integer. TYPE 返回的是int,而Integer. class 返回的是Integer类所对应的Class对象。

反射生成多维数组

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());  }   }

致谢:感谢您的阅读!

正文到此结束
Loading...