一、什么是反射:
(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
三、反射的优缺点:
1、优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:
(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
5.获取Class类对象的三种方式:一般用第三种
(1)方法一:
//方法1:对象.getClass()
Student stu=new Student();
Class clazz=stu.getClass();
(2)方法二:
//方法2:类.class
Class clazz= Student.class;
Class clazz=String.class;
方法三:
//方法3:Class.forName()
clazz=Class.forName(“java.lang.String”);
clazz=Class.forName(“java.util.Date”);
以下案例((示例均已上述Student类为基础):
package com.ptx.ad.controller.test;
/**
* @Author: dev_guo
* @Date: 2021/12/14 10:02
*/
public class Student {
private String name;
private int age;
private double score;
public Student() {
}
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
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 double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public void learn() {
System.out.println(this.name + "正在学习...");
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", score=" + score
+ "]";
}
}
1.获取Class类对象测试类:
package com.ptx.ad.controller.test;
import java.lang.reflect.Modifier;
/**
* @Author: dev_guo
* @Date: 2021/12/14 10:05
*/
public class ClassDemo {
public static void main(String[] args) {
Student stu = new Student();
Class<?> c1 = stu.getClass();//方式一
Class<Student> c2 = Student.class;//方式二
Class<?> c3 = null;
try {
c3 = Class.forName("com.ptx.ad.controller.test.Student"); // 方式三
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("方式一获取的Class对象为:" + c1.getSimpleName());
System.out.println("方式二获取的Class对象为:" + c2);
System.out.println("方式三获取的Class对象为:" + c3);
int mod = c1.getModifiers();//获取修饰符所对应的整数
String modifier = Modifier.toString(mod);//获取修饰符
System.out.println(c1 + "类所用的修饰符为:" + modifier);
}
//运行结果:
//方式一获取Class类对象:Student
//方式二获取Class类对象:reflect.Student
//方式三获取Class类对象:reflect.Student
//Student类的修饰符:public
}
2.获取Filed对象
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* @Author: dev_guo
* @Date: 2021/12/14 10:15
*/
public class FiledDemo {
public static void main(String[] args) {
Class<Student> cl = Student.class;//获取代表Student类的Class对象
Field[] fields = cl.getDeclaredFields();//获取属性对象,返回数组
System.out.println(cl.getSimpleName() + "类中声明的属性有:");
for (Field f : fields) {
String filedName = f.getName();//获取属性名
Class<?> filedType = f.getType();//获取属性类型
int mod = f.getModifiers();//获取修饰符对应整数
String modifier = Modifier.toString(mod);//获取修饰符
System.out.println(modifier + " " + filedType.getSimpleName() + " " + filedName);
}
}
//运行结果:
//Student类中声明的属性有:
//private String name
//private int age
//private double score
}
3.获取Method对象:
package com.ptx.ad.controller.test;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* @Author: dev_guo
* @Date: 2021/12/14 10:19
*/
public class MethodDemo {
public static void main(String[] args) {
try {
Class<?> cls=Class.forName("com.ptx.ad.controller.test.Student");
Method[] methods=cls.getDeclaredMethods();
for(Method method:methods){
String methodName=method.getName(); // 获取方法名称
Class<?> returnType=method.getReturnType(); // 获取方法的返回值类型
String modStr= Modifier.toString(method.getModifiers()); // 获取方法的修饰符
Class<?>[] paramTypes=method.getParameterTypes(); // 获取参数类型
System.out.print(modStr+" "+returnType.getSimpleName()+" "+methodName+"(");
if(paramTypes.length==0){
System.out.print(")");
}
for(int i=0;i<paramTypes.length;i++){ // 遍历形式参数类型
if(i==paramTypes.length-1){
System.out.print(paramTypes[i].getSimpleName()+" args"+i+")");
}else{
System.out.print(paramTypes[i].getSimpleName()+" args"+i+",");
}
}
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
}
//运行结果:
//public void eat(String args0,String args1)
//public int getAge()
//public void setAge(int args0)
//public double getScore()
//public void setScore(double args0)
}
4.获取Constructor对象:
package com.ptx.ad.controller.test;
import java.lang.reflect.Constructor;
/**
* @Author: dev_guo
* @Date: 2021/12/14 10:30
*/
public class ConstructorDemo {
public static void main(String[] args) {
Class<Student> cl = Student.class;//获取Class对象,代表Student类
try {
Constructor<Student> con = cl.getDeclaredConstructor(String.class, int.class, double.class);//获取散参构造方法
Student stu = con.newInstance("张无忌", 23, 96.7);
System.out.println(stu);
} catch (Exception e) {
e.printStackTrace();
}
}
//运行结果: Student [name=张无忌, age=23, score=96.7]
}
5.动态创建方法:
package com.ptx.ad.controller.test;
import java.lang.reflect.Method;
/**
* @Author: dev_guo
* @Date: 2021/12/14 10:51
*/
public class InvokeMethod {
public static void main(String[] args) {
Class<Student> cls = Student.class;
try {
Student stu = cls.newInstance(); // 通过反射机制实例化对象,使用此newInstance()方法,要求类中必须包含一个无参构造方法
Method setNameMethod = cls.getMethod("setName", String.class);
setNameMethod.invoke(stu, "风清扬"); // 使用stu对象调用setName(String name)方法,传入"风清扬"参数
Method getNameMethod = cls.getMethod("getName");
System.out.println(getNameMethod.invoke(stu)); // 使用stu对象调用getName()方法,返回一个值
} catch (Exception e) {
e.printStackTrace();
}
}
//运行结果: 风清扬
}