反射机制概念
主要是指在运行过程中,对于任意一个类(或者成为对象,一切皆为对象),都能获取到它的所有属性和方法,这种动态获取信息,动态调用对象方法的功能叫做Java的反射机制。本质是JVM通过得到class对象,再通过class对象反编译,从而获取对象的属性、方法各种信息。
应用
- 生成动态代理
- 面向切片编程(例如Springboot)
- 比如IDE这种编辑器,输入点之后就能自动弹出相应方法就用到了反射
应用场景
对于一些没有被提前加载到JVM的类,程序运行时需要的时候可以通过反射机制来动态创建对象,并使用它的属性和方法。
基本使用
1.class获取方式
//第一种方式获取Class对象
Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
Class stuClass = stu1.getClass();//获取Class对象
System.out.println(stuClass.getName());
//第二种方式获取Class对象
Class stuClass2 = Student.class;
System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
//第三种方式获取Class对象
try {
Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
一般使用第三种方式,第二种方式需要导入类包
判断是否为某个类的实例
public native boolean isInstance(Object obj);
创建实例
// 第一种:使用Class对象的newInstance()方法来创建Class对象对应类的实例
Class<?> c = String.class;
Object str = c.newInstance();
// 第二种:先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建对象,这种方法可以用指定的构造器构造类的实例
//获取String的Class对象
Class<?> str = String.class;
//通过Class对象获取指定的Constructor构造器对象
Constructor constructor=c.getConstructor(String.class);
//根据构造器创建实例:
Object obj = constructor.newInstance(“hello reflection”);
获取构造方法
// 批量获取
public Constructor[] getConstructors() //所有"公有的"构造方法
public Constructor[] getDeclaredConstructors() //获取所有的构造方法(包括私有、受保护、默认、公有)
// 单个获取
public Constructor getConstructor(Class... parameterTypes) //获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes) //获取"某个构造方法"可以是私有的,或受保护、默认、公有
// 调用构造方法
Constructor.newInstance(Object... initargs)
// 暴力反射,解除私有限定
setAccessible(true)
具体示例
public class ReflectTest
{
public static void main(String[] args) throws Exception{
//1.获取类,注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
Class c = Class.forName("CustomerService");
//获取某个特定的方法
//通过:方法名+形参列表
Method m = c.getDeclaredMethod("login",String.class,String.class);
//通过反射机制执行login方法.
Object o = c.newInstance();
//调用o对象的m方法,传递"admin""123"参数,方法的执行结果是retValue
Object retValue = m.invoke(o, "admin","123");
System.out.println(retValue); //true
}
}
public class CustomerService
{
//登录
public boolean login(String name,String pwd){
if("admin".equals(name) && "123".equals(pwd)){
return true;
}
return false;
}
//退出
public void logout(){
System.out.println("系统已安全退出!");
}
}
优缺点
- 优点:对于Java这种先编译后运行的语言来说,最大的优点就是灵活;
- 缺点:反射会消耗一定资源、反射调用方法可以忽略权限检查,容易造成安全性问题。
参考博客:
java反射机制原理是什么
Java基础篇:反射机制详解