提到Java的反射,势必会联想到Java类的class文件对象,而反射就是通过class文件对象的一些方法来操作Java类的。比如说通过class文件对象我们就可以通过反射创建出相应的Java类对象。下面通过一些简单易懂的代码来实现上述所说(以学生类为例)
1、创建实体类
package cn.dragon09;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int age;
private String name;
}
2、创建测试类
public class test{
public static void main(String[] args){
}
}
3、获取student类的class文件对象
package cn.dragon09;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取class文件对象的方式有三种,这里选择使用Class类中的静态方法forname来获取
/*
static Class<?> forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。
参数:
String className:全类名(包名+类名)==>可以确定类的唯一性
cn.dragon09.Student
*/
Class<?> clazz = Class.forName("cn.dragon09.Student");
}
}
4、通过class文件对象获取student类中的构造方法
package cn.dragon09;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取class文件对象的方式有三种,这里选择使用Class类中的静态方法forname来获取
/*
static Class<?> forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。
参数:
String className:全类名(包名+类名)==>可以确定类的唯一性
cn.dragon09.Student
*/
Class<?> clazz = Class.forName("cn.dragon09.Student");
//参数说明:要获取空参数构造方法,可以不传任何参数.获取满参数构造方法,传入参数类型对应的class文件
Constructor<?> constructor = clazz.getConstructor();
Constructor<?> constructor1 = clazz.getConstructor(int.class, String.class);
System.out.println(constructor);
System.out.println(constructor1);
}
}
获取结果如下:
public cn.dragon09.Student()
public cn.dragon09.Student(int,java.lang.String)
5、通过上面获取到的构造方法创建student对象
//无参构造方法创建对象
Object o1 = constructor.newInstance();
System.out.println(o1);//Student(age=0, name=null)
//满参构造方法创建对象
Object o2 = constructor1.newInstance(19, "洗狗陈");
System.out.println(o2);//Student(age=19, name=洗狗陈)
6、反射技术创建对象的简化方式
Object o3 = clazz.newInstance();
System.out.println(o3);//Student(age=0, name=null)
//要给o3赋值可通过student类中提供的set方法,父类的对象无法使用子类特有的属性,所以得向下转型
Student student = (Student) o3;
student.setName("胡歌");
student.setAge(18);
System.out.println(student);//Student(age=18, name=胡歌)
7、反射技术获取student类中的成员方法
//class文件对象获取多个方法
//Method[] getMethods() 获取本类中,父类中,接口中继承的所有公共的方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//Method[] getDeclaredMethods() 获取包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
//Method类中的方法getName:获取方法的名称
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod.getName());
}
8、反射获取student类中指定的成员方法
//Method getMethod(String name, Class<?>... parameterTypes) 获取指定公共成员方法(包含继承的)
//参数说明:String name: 类中方法的名称。Class<?>... parameterTypes:方法参数的列表的class文件对象
Method getName = clazz.getMethod("getName");
Method setName = clazz.getMethod("setName", String.class);
9、反射技术运行所获取到的方法
//使用Method类中方法invoke运行获取到的成员方法
Object o4 = clazz.newInstance();
Object obj1 = setName.invoke(o4, "老八");
System.out.println(obj1);//null setName方法没有返回值
Object obj2 = getName.invoke(o4);//相当于调用getName方法获取对象的name值
System.out.println(obj2);//老八
/*
java.lang.reflect.Method类
Object invoke(Object obj, Object... args) 运行成员方法
参数:
Object obj:运行方法需要对象的支持,运行哪个类中的方法,就传递哪个类中的对象
运行student类中的方法,传递student对象,可以使用反射简化方式获取
Object... args:调用方法传递的实际参数
返回值:
Object:方法的返回值
方法的返回值类型不是void,Object用来接收方法的返回值
方法的返回值类型是void,没有返回值,不用接收,Object的值是null
*/
以上是个人对反射技术的初步了解,少年还需努力。