反射 (Reflection)
是 Java 的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。
Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
每个类都有一个自身的 Class
对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class
文件,该文件内容保存着 Class
对象。类加载相当于 Class 对象的加载,类在第一次使用时才动态加载到 JVM
中。
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class
不存在也可以加载进来。
Class
和 java.lang.reflect
一起对反射提供了支持,java.lang.reflect
类库主要包含了以下三个类:
private
方法);package cn.dioxide.cn;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class arraylist_t {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得一个class类对象
Class c1 = Class.forName("cn.dioxide.cn.User");
User user = (User) c1.newInstance(); //调用类的无参构造器
System.out.println(user);
//通过构造器创建对象
Constructor con = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) con.newInstance("李四", 001, 18);
System.out.println(user2);
//通过反射调用普通方法
User user3 = (User) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(user3, "张三"); //invoke方法激活:("方法名", "对象值")
System.out.println(user3.getName());
//通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true); //绕过private保护
name.set(user4, "王五");
System.out.println(user4.getName());
}
}
package cn.dioxide.cn;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class arraylist_t {
//普通构造器 19ms
public static void demo1() {
User u1 = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
u1.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("cost time: " + (endTime - startTime) + "ms");
}
//反射构造器 2183ms
public static void demo2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User u1 = new User();
Class c1 = u1.getClass();
Method getname = c1.getDeclaredMethod("getName", null);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getname.invoke(u1, null);
}
long endTime = System.currentTimeMillis();
System.out.println("cost time: " + (endTime - startTime) + "ms");
}
//反射构造器 权限越级 1138ms
public static void demo3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User u1 = new User();
Class c1 = u1.getClass();
Method getname = c1.getDeclaredMethod("getName", null);
getname.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getname.invoke(u1, null);
}
long endTime = System.currentTimeMillis();
System.out.println("cost time: " + (endTime - startTime) + "ms");
}
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
demo1();
demo2();
demo3();
}
}
package cn.dioxide.cn;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class arraylist_t {
//反射解析泛型
public static void demo1(Map < String, User > map, List < User > list) {
System.out.println("test01");
return;
}
public Map < String, User > demo2() {
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = arraylist_t.class.getMethod("demo1", Map.class, List.class);
//参数化类型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType: genericParameterTypes) {
System.out.println("#" + genericParameterType);
if (genericParameterType instanceof ParameterizedType) {
//获得参数类型
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument: actualTypeArguments) {
System.out.println("demo1 " + actualTypeArgument);
}
}
}
method = arraylist_t.class.getMethod("demo2", null);
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType) {
//判断参数类型
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument: actualTypeArguments) {
System.out.println("demo2 " + actualTypeArgument);
}
}
}
}
package cn.dioxide.cn;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class arraylist_t {
//反射操作注解
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("cn.dioxide.cn.student");
//通过反射获得注解类
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation: annotations) {
System.out.println(annotation);
}
//获得注解的value值
Dioxide dioxide = (Dioxide) c1.getAnnotation(Dioxide.class);
String value = dioxide.value();
System.out.println(value);
//获得类指定的注解
Field f = c1.getDeclaredField("name");
FieldDioxide annotation = f.getAnnotation(FieldDioxide.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@Dioxide(value = "db_student")
class student {
@FieldDioxide(columnName = "db_id", type = "int", length = 10)
private int id;
@FieldDioxide(columnName = "db_age", type = "int", length = 10)
private int age;
@FieldDioxide(columnName = "db_name", type = "varchar", length = 10)
private String name;
public student() {}
public student(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int 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;
}
@Override
public String toString() {
return "student{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Dioxide {
String value();
}
//属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldDioxide {
String columnName();
String type();
int length();
}