1.简介
java的反射机制是java的特性之一,反射技术是构建框架技术的基础所在。
java的反射机制,是指在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意属性和方法,这种动态获取信息以及动态调用对象方法的功能叫做java的反射机制。
基础知识补充:要想java程序能够运行,java类必须被java虚拟机加载。运行的程序都是在编译时就已经加载了所需要的类。java反射机制在编译时并不确定是哪个类被加载了,而是在程序运行时才加载,探知,使用。
java反射机制能够知道类的基本结构,这种对java类结构探知的能力,称为java类的“自审”。
2.作用
通过java反射,可以实现以下功能:
在运行时判断任意一个对象所属的类; 在运行时构造任意一个类的对象 ; 在运行时判断任意一个类所具有的方法和属性;在运行时调用任意一个对象的方法;
3.java中使用反射的基本步骤如下:
3.1 导入java.lang.reflect.*
3.2 获得需要操作的类的java.lang.Class对象
3.3 调用Class的方法获取Field,Method等对象
3.4 使用反射API进行操作。
4. 获取Class类对象的方式
4.1 根据类名 类名.class
4.2 根据对象 对象.getClass()
4.3 根据全限定类名 Class.forName(全限定类名)
5. 由Class对象来生成对象实例
5.1 使用Class对象的newInstance()方法来创建Class对象对应类的实例
5.2 先通过Class对象获取指定的Constructor对象,再调用Constructor对象的 newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例
6. 由Class对象获取方法
6.1 getDeclaredMethods
方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法
6.2 getMethods
方法返回某个类的所有公用(public)方法,包括其继承类的公用方法
6.3 getMethod
方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象
7. 获取类的成员变量信息
getFiled
:访问公有的成员变量
getDeclaredField
:所有已声明的成员变量,但不能得到其父类的成员变量
8.注意
不能乱用反射,反射创建对象性能要低一些。
实际上,只有当程序需要动态创建某个类的对象时才考虑使用反射,例如通用性比较广的框架,因为很多java框架需要根据配置文件信息来创建java对象,从配置文件读取的只是某个类的字符串类名,程序要根据字符串来创建对应的实例,就必须使用反射。
package com.fang.search.service.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class InvokeTest {
private String name;
public int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public InvokeTest(){}
public InvokeTest(String name) {
this.name = name;
}
public int add(int param1, int param2) {
return param1 + param2;
}
public String echo(String message) {
return "Hello: " + message;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
// 原始方法
InvokeTest invokeTest = new InvokeTest();
System.out.println(invokeTest.add(1, 2));
System.out.println(invokeTest.echo("北京"));
System.out.println("---------------------");
// 使用反射的的方式
// 1.获取Class对象的三种方式 (一切皆对象,类也是对象)
// Class<?> classType = InvokeTest.class;
Class<?> classType = Class.forName("com.fang.search.service.reflect.InvokeTest");
// Class<?> classType3 = invokeTest.getClass();
// 2.Class对象的常用方法 eg
String className = classType.getName(); // 获取类名
System.out.println("className:" + className);
Method[] methods = classType.getMethods(); // 获取类中的所有方法
for (Method method : methods) {
System.out.println(method);
}
// 3.1 通过Class对象生成对象实例
Object invokeTest2 = classType.newInstance();
System.out.println(invokeTest2 instanceof InvokeTest);
// 3.2 通过Class对象,先生成构造器,再通过构造器生成对象实例
Constructor<?> constructor = classType.getConstructor(String.class);
InvokeTest invokeTest3 = (InvokeTest)constructor.newInstance("张三");
System.out.println(invokeTest3.getName());
// 4.通过反射调用方法 第一个参数是方法名,第二个参数是方法的参数类型
Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});
System.out.println(addMethod);
Method echoMethod = classType.getMethod("echo", new Class[]{String.class});
System.out.println(echoMethod);
// 5.调用目标方法
Object result = addMethod.invoke(invokeTest2, new Object[]{3, 8});
System.out.println(result);
Object result2 = echoMethod.invoke(invokeTest2, new Object[]{"Tom"});
System.out.println(result2);
// 6.通过反射获取成员变量
// 通过反射获取:public成员变量和私有成员变量
Field[] fields = classType.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
// 7.给对象的成员变量设置值
Field age = classType.getField("age");
age.set(invokeTest3, 30);
System.out.println("age:"+invokeTest3.getAge());
Field name = classType.getDeclaredField("name");
name.set(invokeTest3, "李斯特");
System.out.println("name:"+invokeTest3.getName() + " age:"+invokeTest3.getAge());
}
}