Java反射
更新时间:2021-01-25 14:34:53点击次数:314次
反射的特点
1. 性能问题
Java反射机制中包含了一些动态类型,所以Java虚拟机不能够对这些动态代码进行优化。因此,反射操作的效率要比正常操作效率低很多。我们应该避免在对性能要求很高的程序或经常被执行的代码中使用反射。而且,如何使用反射决定了性能的高低。如果它作为程序中较少运行的部分,性能将不会成为一个问题。
2.安全限制
使用反射通常需要程序的运行没有安全方面的限制。如果一个程序对安全性提出要求,则最好不要使用反射。因为反射回破坏程序的封装,在使用反射的时,未知类或已知类中私有(private)成员也会被调用到,大大将地了程序的安全性。
3.程序健壮性
反射允许代码执行一些通常不被允许的操作,所以使用反射有可能会导致意想不到的后果。反射代码破坏了Java程序结构的抽象性,所以当程序运行的平台发生变化的时候,由于抽象的逻辑结构不能被识别,代码产生的效果与之前会产生差异。
Java中反射用到的类
类表示含义
java.lang.Class反射的核心
java.lang.reflect.Field表示类的属性
java.lang.reflect.Method表示类的方法
java.lang.reflect.Constructor表示类的构造方法
使用反射
一. 获取类信息
分为三中方法:
1.调类或接口实例的getClass()方法
Class cls = obj.getClass;//obj为某个类型的实例
2.调用类或接口的class属性
Class cls = Student.class;//Student为自定义的学生类型
3.使用Class.forName()方法
Class cls = Class.forName("com.mysql.cj.jdbc.Driver");
//com.mysql.cj.jdbc.Driver是该类所在包(包括类名)
二.获取Class实例中的信息
获取类的基本信息
Class cls = Person.class;
//Person是提前编写好的实体列
System.out.println("全类名 = " + cls.getName());
//getName()获取包名+类名
System.out.println("类名 = " + cls.getSimpleName());
//getSimpleName()获取类名
System.out.println("包名 = " + cls.getPackage().getName());
//cls.getPackage().getName()获取包名
System.out.println("父类 = " + cls.getSuperclass().getSimpleName());
//cls.getSuperclass().getSimpleName()获取该类所继承的父类类名
for (Class> anInterface : cls.getInterfaces()) {
//getInterfaces()获取该类所实现的接口,以数组类型返回
System.out.println("遍历接口 = " + anInterface.getSimpleName());
}
int modifiers = cls.getModifiers();
System.out.println("cls.getModifiers() = " + modifiers);
//getModifiers()获取访问修饰符,但是是以int类型返回,必须通过Modifier.toString(modifiers)解码
获取类的属性信息
//获得Field对象
//修饰符 数据类型 属性名
System.out.println("------------getField-------------");
//getField 获得指定属性名的属性信息并且修饰符是public
Field name = cls.getField("name");
System.out.println("name = " + name);
System.out.println("------------getFields-------------");
//getFields 获取所有属性信息并且修饰符是public
for (Field field : cls.getFields()) {
System.out.println("field = " + field);
int modifiers = field.getModifiers();
System.out.println("修饰符 = " + Modifier.toString(modifiers));
System.out.println("数据类型 = " +field.getType().getSimpleName());
System.out.println("属性名 = " + field.getName());
}
System.out.println("--------------getDeclaredField--------------");
//getDeclaredField 获得指定属性名的属性信息并且修饰符无限制
Field address = cls.getDeclaredField("address");
System.out.println(" "+address);
Field declaredField = cls.getDeclaredField("name");
System.out.println("declaredField = " + declaredField);
System.out.println("--------------getDeclaredFields--------------");
//getDeclaredFields 获得所有的属性信息修饰符无限制
for (Field field : cls.getDeclaredFields()) {
System.out.println("field = " + field);
int modifiers = field.getModifiers();
System.out.println("修饰符 = " + Modifier.toString(modifiers));
System.out.println("数据类型 = " + field.getType().getSimpleName());
System.out.println("属性名 = " + field.getName());
}
获取类的方法信息
//Method对象
//修饰符 返回值类型 方法名 参数列数
System.out.println("-------getMethod-------");
//getMethod 获取指定方法名的方法信息并且修饰符是public
Method getName = cls.getMethod("getName");
System.out.println("getName = " + getName);
//getMethods 获取所有方法信息并且修饰符是public
System.out.println("-------getMethods-------");
for (Method method : cls.getMethods()) {
System.out.println("method = " + method);
int modifiers = method.getModifiers();
System.out.println("修饰符 " + Modifier.toString(modifiers));
System.out.println("返回值类型 = " + method.getReturnType().getSimpleName());
System.out.println("方法名 = " + method.getName());
for (Class> parameterType : method.getParameterTypes()) {
ystem.out.println("parameterType = " + parameterType.getSimpleName());
}
}
System.out.println("-------getDeclaredMethod-------");
//getDeclaredMethod 获得指定方法名的方法信息修饰符无限制
Method setName = cls.getDeclaredMethod("setName", String.class);
System.out.println("setName = " + setName);
Method getAge = cls.getDeclaredMethod("getAge");
System.out.println("getAge = " + getAge);
System.out.println("-------getDeclaredMethods-------");
//getDeclaredMethods 获得所有方法信息修饰符无限制
for (Method method : cls.getDeclaredMethods()) {
System.out.println("method = " + method);
int modifiers = method.getModifiers();
System.out.println("修饰符 " + Modifier.toString(modifiers));
System.out.println("返回值类型 = " + method.getReturnType().getSimpleName());
System.out.println("方法名 = " + method.getName());
for (Class> parameterType : method.getParameterTypes()) {
System.out.println("parameterType = " + parameterType.getSimpleName());
}
}
获取类的构造函数信息
//获取Constructor对象
//修饰符 参数列表
System.out.println("------------getConstructor-----------");
//getConstructor 获取指定参数类型的构造方法并且修饰符是public
Constructor> constructor = cls.getConstructor();
System.out.println("constructor = " + constructor);
Constructor> constructor1 = cls.getConstructor(String.class, int.class);
System.out.println("constructor1 = " + constructor1);
System.out.println("------------getConstructors-----------");
//getConstructors 获取所有构造信息并且修饰符是public
for (Constructor> con : cls.getConstructors()) {
System.out.println("con = " + con);
int modifiers = con.getModifiers();
System.out.println("修饰符 = " + Modifier.toString(modifiers));
for (Class> parameterType : con.getParameterTypes()) {
System.out.println("参数列表 = " + parameterType.getSimpleName());
}
}
System.out.println("-----------getDeclaredConstructor-------------");
//getDeclaredConstructor 获取指定参数类型的构造信息修饰符无限制
Constructor> constructor2 = cls.getDeclaredConstructor(String.class, int.class, String.class);
System.out.println("constructor2 = " + constructor2);
Constructor> constructor3 = cls.getDeclaredConstructor(String.class, int.class);
System.out.println("constructor3 = " + constructor3);
System.out.println("-------------getDeclaredConstructors-------------");
//getDeclaredConstructors 获取所有构造信息修饰符无限制
for (Constructor> con : cls.getDeclaredConstructors()) {
System.out.println("con = " + con);
int modifiers = con.getModifiers();
System.out.println("修饰符 = " + Modifier.toString(modifiers));
for (Class> parameterType : con.getParameterTypes()) {
System.out.println("参数列表 = " + parameterType.getSimpleName());
}
}
创建实例
1.使用Class实例的newInstance()方法创建实例
Class cls = Class.forName("cn.pojo.Person");
Person person = (Person)cls.newInstance();
//Person的无参构造为public,所以这里能直接访问,如果要调用有参构造须在小括号中传参
2.使用Constructor是创建实例
Class cls = Person.class;
Constructor con = cls.getDeclaredConstructor();
//小括号中可以写参数类型,实列时可以调用相对应的构造函数
con.setAccessible(true);
//如果构造不为public时,程序无法访问,通过setAccessible()可以让程序检查强制访问
Person person = (Person)con.newInstance();
//如果调用的时有参构造时,应在括号中编写参数列表
访问类的属性
通过set和get , 设置和获取属性值
//获取Class对象
Student stu = new Student ();
Class cls = stu.getClass();
//获取属性sex
Field field = cls.getField("sex");
field.setAccessible(true);
//通过set方法向sex属性中设值,stu是sex所在的类
field.set(stu,"张三");
//通过get方法获取sex中的数据
Object value = field.get(stu);
System.out.println(value);
调用方法
通过invoke()方法调用方法
//获取Class对象
Student stu = new Student ();
Class cls = stu.getClass();
//getDeclaredMethod 获得指定方法名的方法信息修饰符无限制
Method name = cls.getDeclaredMethod("getName");
name.setAccessible(true);
//如果所选方法是带参方法时,应在invoke()方法中穿相应参数
Object val = name.invoke();
System.out.println(val);
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。