Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
反射技术大量用于Java设计模式和框架技术,最常见的设计模式就是工厂模式和单例模式。
单例模式(Singleton):这个模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。这样做就是为了节省内存空间,保证我们所访问到的都是同一个对象。
工厂模式(Factory):工厂模式利用Java反射机制和Java多态的特性可以让我们的程序更加具有灵活性。用工厂模式进行大型项目的开发,可以很好的进行项目并行开发。
下面就是反射基础代码的实现:
首先建立一个person类
package com.dc.esb.reflect;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* @auther zhanggt
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
public String name;
private Integer age;
private String birth;
private void run(){
System.out.println("我是一个私有的方法。。。。。。");
}
private Person(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", birth='" + birth + '\'' +
'}';
}
}
下面建立测试类:
DemoTest
package com.dc.esb.reflect;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
/**
* @auther zhanggt
*/
public class DemoTest {
@Test
public void test() throws Exception {
//获取类的以及实例化三种方式
Class<?> clazz = Class.forName("com.dc.esb.reflect.Person");
Person person = (Person) clazz.getDeclaredConstructor().newInstance();
//第二种方式
Class<Person> clazz1 = Person.class;
Person person1 = (Person) clazz1.getDeclaredConstructor().newInstance();
//第三种方式
Class<? extends Person> clazz2 = new Person().getClass();
Person person2 = (Person) clazz2.getDeclaredConstructor().newInstance();
}
/**
* 获取目标类的构造方法
*
* @throws Exception
*/
@Test
public void test1() throws Exception {
System.out.println("获取构造方法开始。。。。。。。。。。。。。。。。。。。");
Class<?> clazz = Class.forName("com.dc.esb.reflect.Person");
//只能获取到public修饰的构造方法
Constructor<?>[] constructors1 = clazz.getConstructors();
for (Constructor<?> c1 : constructors1) {
System.out.println(c1.getName() + "参数:" + c1.getParameterCount());
}
System.out.println("----------------分割线---------------------");
//获取到所有修饰符修饰的方构造法
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> c : constructors) {
System.out.println(c.getName() + "参数:" + c.getParameterCount());
}
System.out.println("获取构造方法结束。。。。。。。。。。。。。。。。。。。");
}
/**
* 获取目标类中的属性
*
* @throws Exception
*/
@Test
public void test2() throws Exception {
System.out.println("获取属性开始。。。。。。。。。。。。。。。。。。。");
Class<Person> clazz1 = Person.class;
Person instance = clazz1.getDeclaredConstructor().newInstance();
//只能获取到public修饰的属性
Field[] fields = clazz1.getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
System.out.println("----------------分割线---------------------");
//获取到所有修饰符修饰的属性
Field[] fields1 = clazz1.getDeclaredFields();
for (Field f : fields1) {
System.out.println(f.getName());
//给某一个属性注入值
if ("age".equals(f.getName())) {
//给私有属性设置值必须禁用jdk安全检查
f.setAccessible(true);
f.set(instance, 123456);
System.out.println(instance.toString());
}
}
System.out.println("获取属性结束。。。。。。。。。。。。。。。。。。。");
}
/**
* 获取目标类中的方法
*
* @throws Exception
*/
@Test
public void test3() throws Exception {
System.out.println("获取方法开始。。。。。。。。。。。。。。。。。。。");
Class<? extends Person> clazz = new Person().getClass();
Person instance = clazz.getDeclaredConstructor().newInstance();
//只能获取到public修饰的方法
Method[] methods = clazz.getMethods();
for (Method m : methods) {
System.out.println(m.getName());
}
System.out.println("----------------分割线---------------------");
//获取到所有修饰符修饰的方法
Method[] methods1 = clazz.getDeclaredMethods();
for (Method m : methods1) {
System.out.println(m.getName());
if ("run".equals(m.getName())) {
//给私有方法设置值必须禁用jdk安全检查
m.setAccessible(true);
m.invoke(instance, "run被反射执行了。。。。");
}
}
System.out.println("获取方法结束。。。。。。。。。。。。。。。。。。。");
}
/**
* 获取目构造方法实例化对象
*
* @throws Exception
*/
@Test
public void test4() throws Exception {
Class<?> clazz = Class.forName("com.dc.esb.reflect.Person");
Person instance = (Person) clazz.getDeclaredConstructor(String.class, Integer.class, String.class).newInstance("第一种", 1, new Date().toString());
System.out.println(instance.toString());
}
}
运行结果
获取构造方法开始。。。。。。。。。。。。。。。。。。。
com.dc.esb.reflect.Person参数:0
com.dc.esb.reflect.Person参数:3
----------------分割线---------------------
com.dc.esb.reflect.Person参数:0
com.dc.esb.reflect.Person参数:2
com.dc.esb.reflect.Person参数:3
获取构造方法结束。。。。。。。。。。。。。。。。。。。
获取属性开始。。。。。。。。。。。。。。。。。。。
name
----------------分割线---------------------
name
age
Person{name='null', age=123456, birth='null'}
birth
获取属性结束。。。。。。。。。。。。。。。。。。。
获取方法开始。。。。。。。。。。。。。。。。。。。
equals
toString
hashCode
getName
setName
getAge
setAge
getBirth
setBirth
wait
wait
wait
getClass
notify
notifyAll
----------------分割线---------------------
run
我是一个私有的方法。。。。。。run被反射执行了。。。。
equals
toString
hashCode
getName
setName
canEqual
getAge
setAge
getBirth
setBirth
获取方法结束。。。。。。。。。。。。。。。。。。。
Person{name='第一种', age=1, birth='Sun Nov 26 16:56:12 CST 2023'}