❤ 作者主页:李奕赫揍小邰的博客
❀ 个人介绍:大家好,我是李奕赫!( ̄▽ ̄)~*
🍊 记得点赞、收藏、评论⭐️⭐️⭐️
📣 认真学习!!!🎉🎉
文章目录
- Java反射机制简述
- 1、四种方式获取Class类的对象
- 2、获取class类对象的属性,构造和方法
- 3、使用newInstance创建对象
- 4、通过Constructor对象调用无参和有参方法
- 5、使用反射动态调用有无参有无返回值的Method方法
- 6、反射会破坏OOP对象
- 7、方法重载
- 8、setAccessible的作用
Java反射机制简述
Java反射机制的核心时在程序运行时动态加载类并获取类的详细信息,从而可以调用类或对象的属性和方法。
它的本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象和类的各种信息。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
1、四种方式获取Class类的对象
前置:新建一个UserInfo实体类在com.jjl.domain下面
Class class1= UserInfo.class;
Class class2=new UserInfo().getClass();
Class class3=UserInfo.class.getClassLoader().loadClass("com.jjl.domain.UserInfo");
Class class4=Class.forName("com.jjl.domain.UserInfo");
2、获取class类对象的属性,构造和方法
public static void main(String[] args) {
Class userInfoClass= UserInfo.class; //属性列表
Field[] a=userInfoClass.getDeclaredFields();
//getFields()方法获取类的全部公共字段,getDeclaredFields()方法获取全部字段
for(Field field:a){
System.out.println(field.getName());
}
//构造列表
Constructor[] b=userInfoClass.getConstructors();
for(Constructor constructor:b){
System.out.println(constructor.getName());
}
//方法列表
Method[] c=userInfoClass.getDeclaredMethods();
for(Method method:c){
System.out.println(method.getName());
}}
3、使用newInstance创建对象
//不用new来创建对象,原理就是反射技术
String newObjectName="com.jjl.domain.UserInfo";
Class class4=Class.forName(newObjectName);
//newInstance开始创建对象
UserInfo userInfo=(UserInfo) class4.newInstance();
4、通过Constructor对象调用无参和有参方法
String newObjectName="com.jjl.domain.UserInfo";
Class class4=Class.forName(newObjectName);
Constructor constructor1=class4.getDeclaredConstructor(); //调用无参方法
UserInfo userInfo1=(UserInfo) constructor1.newInstance();
System.out.println(userInfo1.hashCode());
Constructor constructor=class4.getDeclaredConstructor(long.class,String.class,String.class); //调用有参方法
System.out.println(constructor.newInstance(11,"a1","aa1").hashCode());
System.out.println(constructor.newInstance(12,"a2","aa2").hashCode()); //结果下图
5、使用反射动态调用有无参有无返回值的Method方法
String newObjectName="com.jjl.domain.UserInfo";
Class class4=Class.forName(newObjectName);
UserInfo userInfo=(UserInfo) class4.newInstance();
String methodName="test";
//调用无参无返回值的Method方法
Method method=class4.getDeclaredMethod(methodName);
System.out.println(method.getName());
method.invoke(userInfo); //根据获取的方法,反射执行该方法 getName()获取名称,invoke()反射执行
//调用有参无返回值的Method方法
Method method=class4.getDeclaredMethod(methodName,String.class);
System.out.println(method.getName());
method.invoke(userInfo,"我的地址在北京");
//调用有参有返回值的Method方法
Method method=class4.getDeclaredMethod(methodName,Integer.class);
System.out.println(method.getName());
Object returnValue=method.invoke(userInfo,99999);
System.out.println("returnValue"+returnValue);
6、反射会破坏OOP对象
单例模式由于构造方式式private的,不能new实例化对象,只有调用getOneInstance()获取自身对象,而且可以保证单例。但是使用反射技术能破坏OOP对象,导致可以创建出多个单例对象。
OneInstance o1=OneInstance.getOneInstance(); //单例模式(饱汉式) 保证当前进程只有一个实例对象
OneInstance o2=OneInstance.getOneInstance();
OneInstance o3=OneInstance.getOneInstance();
System.out.println(o1);
System.out.println(o2);
System.out.println(o3);
Class classRef=Class.forName("com.jjl.objectfactory.OneInstance"); //从这里开始使用反射实例化对象
Constructor c=classRef.getDeclaredConstructor();
c.setAccessible(true);
OneInstance one1=(OneInstance) c.newInstance();
OneInstance one2=(OneInstance) c.newInstance();
System.out.println(one1);
System.out.println(one2);
执行结果:
7、方法重载
使用反射可以调用重载方法
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class class15=Test15.class;
Object object=class15.newInstance();
Method method1=class15.getDeclaredMethod("testMethod", String.class);
Method method2=class15.getDeclaredMethod("testMethod", String.class,String.class);
method1.invoke(object,"法国");
method2.invoke(object,"中国","中国人");
}
public void testMethod(String username){
System.out.println("public void testMethod(String username)");
System.out.println(username);
}
public void testMethod(String username,String password){
System.out.println("public void testMethod(String username,String password)");
System.out.println(username+" "+password);
}
8、setAccessible的作用
setAccessible功能是启用或禁用安全检查;具体的用处主要有两处,作用于方法上,method.setAccessible(true);作用于属性上field.setAccessible(true);
将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查;实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 ;
由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的