一.什么是反射
反射是指通过Java的反射机制获得指定类的Class类。并通过Class类获取指定类的属性,方法和构造方法。也可以获取Class类的注解信息和修改属性的值。
二.反射获取Class类的方式
常规获取Class主要有以下三种方法
package com.test2;
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Test test = new Test();
Class c ;
//方式一,通过实体对象获取
c = test.getClass();
System.out.println(c);
//方式二,通过Class.forName获取
c = Class.forName("com.test2.Test");
System.out.println(c);
//方式三,直接将 Test.class 赋给class类
c = Test.class;
System.out.println(c);
}
}
class Test{
String str;
public Test() {
}
public Test(String str) {
this.str = str;
}
}
三.常见的反射使用方法
- 获取类的构造器
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Test test;
Class c = Class.forName("com.test2.Test");
System.out.println("获取类的所有构造方法");
Constructor[] constructors = c.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("-----------------------");
System.out.println("获取类的指定构造方法");
//需要传入指定构造方法的参数
Constructor constructor = c.getConstructor(String.class);
System.out.println(constructor);
}
}
- 获取和修改类的属性
package com.test2;
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Test test = new Test();
Class c = test.getClass();
//获取当前类指定的属性
Field field = c.getDeclaredField("str");
//由于str是私有属性,想要赋值需要关闭安全检测
field.setAccessible(true);
//给test的str属性赋值
field.set(test,"123");
System.out.println(test);
}
}
class Test{
private String str;
public Test() {
}
public Test(String str) {
this.str = str;
}
@Override
public String toString() {
return "Test{" +
"str='" + str + '\'' +
'}';
}
}
- 获取类的方法
package com.test2;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException {
Class c = Class.forName("com.test2.Test");
//初始化test对象
Test test = (Test)c.newInstance();
System.out.println("获取类的所有方法");
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("-----------------------");
System.out.println("获取类的指定方法");
//需要传入指定方法的名字和参数
Method method = c.getDeclaredMethod("method1",null);
method.invoke(test,null);
System.out.println("-----------------------");
method = c.getDeclaredMethod("method2", String.class);
method.invoke(test,"hello");
}
}
class Test{
private String str;
public Test() {
}
public Test(String str) {
this.str = str;
}
public void method1(){
System.out.println("执行方法一");
}
public void method2(String str){
this.str = str;
System.out.println(str);
}
}
4. 获取类的注解信息
package com.test2;
import java.lang.annotation.*;
public class Main {
public static void main(String[] args) {
Test test = new Test();
Class c = test.getClass();
System.out.println("获取类的所有注解信息");
Annotation[] annotations = c.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
System.out.println("-------------");
System.out.println("获取类指定的注解信息");
Tt annotation = (Tt)c.getAnnotation(Tt.class);
System.out.println("id="+annotation.id());
System.out.println("name="+annotation.name());
}
}
@Tt(name = "测试类",id = 1)
class Test{
private String str;
public Test() {
}
public Test(String str) {
this.str = str;
}
@Override
public String toString() {
return "Test{" +
"str='" + str + '\'' +
'}';
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tt{
String name();
int id();
}