反射

来源:互联网 发布:淘宝店铺介绍填写 编辑:程序博客网 时间:2024/05/22 01:43

Java反射机制

微信文章


目标:

  • 了解反射的基本原理
  • 掌握Class类的使用
  • 使用Class类并结合其他类取得一个类的完整结构
  • 通过反射机制动态地调用类中的指定方法,并能向这些方法中传递参数

正常情况下如果有一个类,则肯定可以通过类创建对象;那么如果现在要求通过一个对象找到一个类的名称,此时就需要反射机制。
在反射操作的学习中,我会一直体会”一切的操作都将使用Object完成,类、数组的引用都可以使用Object进行接收”


认识Class类

Class类的功能:允许通过一个实例化对象找到一个类的完整信息

package classTest;
// 通过一个对象得到完整的”包.类”名称
public class Person {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
Person base = new Person( );
System.out.println(base.getClass().getName());
// 输出结果:classTest.Person
}

}

通过结果发现,通过一个对象得到了对象所在的完整的”包.类”名称,getClass是Object类中的方法( public final Class getClass() )
该方法的返回值是Class类,此类是Java反射的源头,即可以通过对象反射求出类的名称

在定义Class类时使用了泛型声明。Class类本身表示一个类的本身,通过Class可以完整地得到一个类中的完整结构,包括此类中的方法定义、属性定义等。

方法 描述 public static Class forName(String className) 传入完整的”包.类”名称实例化Class对象 public Constructor[] getConstructors() throws SecurityException 得到一个类中的全部构造方法 public Field[] getDeclaredFields() throws SecurityException 得到本类中单独定义的全部属性 public Field[] getFields() throws SecurityException 得到本类继承而来的全部属性 public Method[] getMethods() throws SecurityException 得到一个类中的全部方法 public Method getMethod(String name, Class… parameterTypes) throws NoSuchMethodException,SecurityException 返回一个Method对象,并设置一个方法中的所有参数类型 public Class[] getInterfaces() 得到一个类中所实现的所有接口 public String getName() 得到一个完整的”包.类”名称 public Package getPackage() 得到一个类的包 public Class getSuperclass() 得到一个类的父类 public Object newInstance() throws InstantiationException,IllegalAccessException 根据Class定义的类实例化对象 public Class getConponentType() 返回表示数组类型的Class public boolean isArray() 判断此Class是否是一个数组

package classTest;
// 实例化Class类对象

public class Person {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
Class

基本原理

Class类的使用

上面说了Class类的实例化过程,那么到底该怎么用Class类呢?实际上Class类在开发中最常见的用法就是实例化对象的操作,即通过一个给定的字符串来实例化一个类的对象。

通过无参构造器实例化对象

通过Class类本身实例化其他类的对象,可以使用newInstance()方法,但是必须保证被实例化的类中存在一个无参构造方法

package classTest;
// 通过Class类实例化对象

public Class Person {
private String name;
private int age;
// getter、setter方法
// 重写toString方法
public static void main(String[] args) {
Class

通过有参构造器实例化对象

如果一定要通过有参构造器实例化对象,Java也提供了实现
1. 通过Class类中的getConstructors()取得本类中的全部构造方法
2. 向构造方法中传递一个对象数组进去,里面包含了构造方法中所需要的各个参数
3. 之后通过Constructor实例化对象
使用了Constructor类,表示构造方法

方法 描述 public int getModifiers() 得到构造方法的修饰符 public String getName() 得到构造方法的名称 public Class[] getParameterTypes() 得到构造方法中参数的类型 public String toString() 返回此构造方法中的信息 public T newInstance(Object… initargs) throws XXXException 向构造方法中传递参数,实例化对象
  1. 得到本类中的所有构造器
  2. 选择第N个构造器,调用newInstance方法并传入M个参数
  3. 注意: 需要知道构造器的顺序。而且编码较使用forName复杂。不建议使用

反射的应用–取得一个类的完整结构

可以通过反射得到一个类的完整结构,需要java.lang.reflect包中几个类(Constructor、Field、Method),它们都是AccessibleObject类的子类

建筑材料

取得所实现的全部接口

public Class[] getInterfaces()
1. 实例化对象
2. 取得本类实现的所有接口(数组)
3. 进行遍历


取得父类

public Class

取得全部构造方法

public Constructor[] getConstructors() throws SecurityException
1. 实例化对象
2. 取得全部的构造器(数组)
3. 遍历
4. 可以得到(构造方法的修饰符–权限、名称、参数的类型)

> 另:权限是数字,要还原为关键字,需要Modifier类(Modifier.toString(权限数字))

取得全部方法

方法 描述 public int getMmodifiers() 取得本方法的访问修饰符 public String getName() 取得方法的名称 public Class[] getParameterTypes() 得到方法的全部参数类型 public Class[] getReturnType() 得到方法的返回值类型 public Class[] getExceptionTypes() 得到一个方法的全部抛出异常 public Object invoke(Object obj, Object… args) throws 一堆Exception 通过反射调用类中的方法

取得全部属性

public Field[] getFields() throws SecurityException // 得到实现的接口或父类中的公共属性
public Field[] getDeclaredFields() throws SecurityException // 得到本类中的全部属性

方法 描述 public Object get(Object obj) throws 某Exception 得到一个对象中属性的具体内容 public void set(Object obj, Oeject value) throws 某Exception 设置指定对象中属性的具体内容 public int getModifiers() 得到属性的修饰符 public String getName() 得到属性的名称 public boolean isAccessible() 判断此属性是否可被外部访问 public void setAccessible(boolean flag) throws 某Exception 设置一个属性是否可被外部访问(打开访问权限) public static void setAccessible(AccessibleObject[] array, boolean flag) throws 某Exception 设置一组属性是否可被外部访问 public String toString() 得到此Field类的信息

反射的应用–通过反射完整对数组的操作

代码片

通过反射调用类中的方法

  1. 通过Class类的getMethod(String name, Class… parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型
  2. 使用invoke进行调用,并向方法中传递要设置的参数

调用setter或getter方法


通过反射操作属性(不推荐)


通过反射操作数组


1 0