1、什么是反射
能够分析类能力的程序称为反射
2、获取类对应的Class类三种方法
每一个类对应的只有一个Class类,当然注解、接口、数组、数据类型都有对应的Class类,那怎么获取对应的Class类
这个要用到的User类
class User {
private String name;
private int age;
private String passworld;
public String address;
public User() {
}
public User(String name, int age, String passworld) {
this.name = name;
this.age = age;
this.passworld = passworld;
}
private User(String name) {
this.name = name;
}
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 String getPassworld() {
return passworld;
}
public void setPassworld(String passworld) {
this.passworld = passworld;
}
private void test(){
System.out.println("this is a test!");
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", passworld='" + passworld + '\'' +
'}';
}
}
//1、通过调用Class类中的静态方法forName
Class c1 = Class.forName("reflective.User");
//2、通过对象后加.class
Class c2 = User.class;
//3、通过实例对象的getClass方法,该方法继承自Object类
User user = new User();
Class c3 = user.getClass();
因为每个类对应的生成的只有一个Class类,所以上面的c1、c2、c3都是相等的
3、通过反射创建实例
//通过Class对象创建对应的实例
User u1 = (User)c1.newInstance();
System.out.println(u1.toString());
//通过Class对象的构造器创建对应的实例(推荐)
User u2 = (User)c1.getConstructor().newInstance();
System.out.println(u2.toString());
这个步骤中的c1为第二步中c1
4、通过反射获取类的结构
反射可以获取类的属性、方法、构造器
代码如下:
//通过Class返回对应类的属性
//Field[] fields = c1.getFields(); //返回公有域属性(包括继承的)
Field[] fields = c1.getDeclaredFields(); //返回所有域属性(包括继承的)
for (Field field : fields) {
System.out.println(field);
}
System.out.println("------------------");
//Method[] methods = c1.getMethods(); //返回所有公有域方法(包括继承的)
Method[] methods = c1.getDeclaredMethods(); //返回所有域方法(包括继承的)
for(Method method : methods) {
System.out.println(method);
}
System.out.println("---------------");
//Constructor[] constructors = c1.getConstructors();//返回所有公有域构造器
Constructor[] constructors = c1.getDeclaredConstructors();//返回所有构造器
for(Constructor constructor : constructors) {
System.out.println(constructor);
}
5、通过反射获取具体的值
一般来说被private修饰的属性,方法、构造器都不能被直接访问,但是反射可以,setAccessible方法默认值是false,是用来安全检测,当该方法参数设置为true,就可以访问
User user2 = new User("小明", 11, "123456");
Class c4 = user2.getClass();
Field f = c4.getDeclaredField("name");
f.setAccessible(true);
System.out.println(f.get(user2));
//反射不仅可以访问到值,还可以设置值
f.set(user2,"小红");
System.out.println(f.get(user2));
Method m = c4.getDeclaredMethod("test");
m.setAccessible(true);
//这是通过反射调用方法
m.invoke(user2);
System.out.println(m);
6、反射耗性能
package com.wgr.reflective;
import java.lang.reflect.Method;
/**
* @author weiguorong
* @date 2021/8/13 0:04
*/
public class Test {
public static void main(String[] args) throws Exception {
Test test = new Test();
System.out.println(test.test01());
System.out.println(test.test02());
System.out.println(test.test03());
}
//普通调用
public long test01() {
User user = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
user.getName();
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
//反射调用
public long test02() throws Exception {
User user = new User();
Class c1 = user.getClass();
Method method = c1.getMethod("getName");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
method.invoke(user, null);
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
//取消安全检测的反射调用
public long test03() throws Exception {
User user1 = new User();
Class c1 = user1.getClass();
Method method = c1.getMethod("getName");
long startTime = System.currentTimeMillis();
method.setAccessible(true);
for (int i = 0; i < 100000000; i++) {
method.invoke(user1, null);
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
}
class User {
String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
结果
63
18075
828
所以反射是三个中最耗性能的