Java反射机制初步理解
一、反射的概念
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。(百度)
说白了:就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)
二、前提
获取字节码文件 **.Class
三种方式:
2.1、任意类继承的Object类,自带的getClass 方法
2.2、Class类的静态forName(String ClassName)方法
2.3、Java中任意对象都自带静态的.class属性
三、反射的几点应用:
我首先写一个普通的userInfo实体类,自定义一个注解myAnnotation,进行以下演示
代码地址:https://gitee.com/huelwyk/codes/rju0h5k4e13glp6vwyis941
useInfo类
1 package Reflection; 2 3 /** 4 * className UserInfo 5 * 测试的userInfo类 6 * 提供私有属性和公开属性,构造方法全部私有, 7 * 切记:利用反射原理,一定要将无参构造完善,后面会解释(自动填充对象) 8 * @author Java DaKun 9 * @date 2020/8/28 10 * @version:1.0 11 * @since:jdk:1.8 12 */ 13 @MyAnnotation(id = 1,name = "tom",age = 20)//可以手动给与参数,如果不加上,会自动加上为默认值 14 public class UserInfo { 15 16 private String name = "admin"; 17 18 public String str = "你好"; 19 20 private Integer id; 21 22 @Override 23 public String toString() { 24 return "UserInfo{" + 25 "name='" + name + '\'' + 26 ", str='" + str + '\'' + 27 ", id=" + id + 28 '}'; 29 } 30 31 //公开属性,可以加上get、set方法,私有属性就不加了 32 33 34 public Integer getId() { 35 return id; 36 } 37 38 public void setId(Integer id) { 39 this.id = id; 40 } 41 42 //两个带参方法 43 private String test(String str, Integer num) { 44 System.out.println("test.......num:" + num); 45 return str; 46 } 47 @MyAnnotation(id=1)//其它不赋值,采用默认值 name() default "Jim"; age() default 18; 48 public String test(Integer num) { 49 System.out.println("num:" + num); 50 return str; 51 } 52 53 public UserInfo() { //此处应该私有,为做比较,换为public 54 } 55 56 //构造私有 57 private UserInfo(Integer id) { 58 this.id = id; 59 } 60 61 }
myannotation类
1 package Reflection; 2 3 import java.lang.annotation.*; 4 5 /** 6 * className MyAnnotation 7 * 自定义注解 8 * @author Java DaKun 9 * @date 2020/8/28 10 * @version:1.0 11 * @since:jdk:1.8 12 */ 13 @Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})// 自定义注解 放置位置,不太理解的同学,可以看我上一篇博客 14 @Retention(RetentionPolicy.RUNTIME) 15 public @interface MyAnnotation { 16 int id(); 17 18 //利用反射获取注解,主要作用就是获取注解的参数,所以这边给出默认赋值 19 String name() default "Jim"; 20 21 byte age() default 18; 22 }
test类
1 public class reflectionTest { 2 public static void main(String[] args) { 3 //testFiled(); 4 //testMethod(); 5 //testConstructor(); 6 //testAnnotation(); 7 8 }
3.1、获取构造方法
1 private static void testConstructor() { 2 // 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员; 3 // * 4 // * 1.获取构造方法: 5 // * 1).批量的方法: 6 // * public Constructor[] getConstructors():所有”公有的”构造方法 7 // public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有) 8 // 9 // * 2).获取单个的方法,并调用: 10 // * public Constructor getConstructor(Class… parameterTypes):获取单个的”公有的”构造方法: 11 // * public Constructor getDeclaredConstructor(Class… parameterTypes):获取”某个构造方法”可以是私有的,或受保护、默认、公有; 12 // * 13 // * 调用构造方法: 14 // * Constructor–>newInstance(Object… args) 15 Class<UserInfo> userInfoClass = UserInfo.class; 16 17 System.out.println(); 18 19 System.out.println("--获取无参构造-返回值数组-"); 20 Constructor<?>[] constructors = userInfoClass.getConstructors(); 21 for (Constructor<?> constructor : constructors) { 22 System.out.println(constructor); 23 } 24 25 System.out.println("--获取任意有参构造方法- 返回值单一方法 -"); 26 try { 27 28 Constructor<?> constructor = userInfoClass.getDeclaredConstructor(Integer.class);//此处指定带一个Integer参数的构造 29 constructor.setAccessible(true);//此有参构造私有,授权 30 UserInfo userInfo = (UserInfo) constructor.newInstance(100); 31 System.out.println(userInfo.str);//new出对象后,得到实例变量str="你好" 32 33 } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { 34 e.printStackTrace(); 35 } 36 37 }
输出结果
1 --获取无参构造-返回值数组- 2 public Reflection.UserInfo() 3 --获取任意有参构造方法- 返回值单一方法 - 4 你好
3.2、获取成员变量
1 /*拿到类属性*/ 2 /* 1.批量的 3 * 1).Field[] getFields():获取所有的”公有字段” 4 * 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有; 5 * 2.获取单个的: 6 * 1).public Field getField(String fieldName):获取某个”公有的”字段; 7 * 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的) 8 * 9 * 设置字段的值: 10 * Field –> public void set(Object obj,Object value): 11 * 参数说明: 12 * 1.UserInfoClass:要设置的字段所在的对象; 13 * 2.name:要为字段设置的值;*/ 14 private static void testFiled() { 15 16 // 等于Class UserInfoClass1 = UserInfo.class; ?其实就是UserInfo自己或者子类,主要用于安全地访问数据 17 Class<? extends UserInfo> UserInfoClass = UserInfo.class; 18 19 System.out.println("--获取所有公有属性-返回值数组-"); 20 Field[] Fields = UserInfoClass.getFields(); 21 for (Field Field : Fields) { 22 23 System.out.println(Field); 24 } 25 26 System.out.println("--获取所有属性,包括私有的-返回值数组-"); 27 Field[] declaredFields = UserInfoClass.getDeclaredFields(); 28 for (Field declaredField : declaredFields) { 29 System.out.println(declaredField); 30 } 31 32 System.out.println("--获取任一公有属性-返回值单一属性-"); 33 try { 34 Field field = UserInfoClass.getDeclaredField("id"); 35 System.out.println(field.getName()); 36 System.out.println(field.getType()); 37 } catch (NoSuchFieldException e) { 38 e.printStackTrace(); 39 } 40 41 System.out.println("--获取任意属性,包括私有的-返回值单一属性-"); 42 try { 43 Field field = UserInfoClass.getDeclaredField("name"); 44 System.out.println(field.getName()); 45 System.out.println(field.getType()); 46 field.setAccessible(true);//由于name属性是私有的,需要授权 47 } catch (NoSuchFieldException e) { 48 e.printStackTrace(); 49 } 50 51 52 }
输出结果
1 --获取所有公有属性-返回值数组- 2 public java.lang.String Reflection.UserInfo.str 3 --获取所有属性,包括私有的-返回值数组- 4 private java.lang.String Reflection.UserInfo.name 5 public java.lang.String Reflection.UserInfo.str 6 private java.lang.Integer Reflection.UserInfo.id 7 --获取任一公有属性-返回值单一属性- 8 id 9 class java.lang.Integer 10 --获取任意属性,包括私有的-返回值单一属性- 11 name 12 class java.lang.String
3.3、获取成员方法
1 private static void testMethod() { 2 // * 获取成员方法并调用: 3 // * 4 // * 1.批量的: 5 // * public Method[] getMethods():获取所有”公有方法”;(包含了父类的方法也包含Object类) 6 // * public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的) 7 // * 2.获取单个的: 8 // * public Method getMethod(String name,Class<?>… parameterTypes): 9 // * 参数: 10 // * name : 方法名; 11 // * Class … : 形参的Class类型对象 12 // * public Method getDeclaredMethod(String name,Class<?>… parameterTypes) 13 // * 14 // * 调用方法: 15 // * Method –> public Object invoke(Object obj,Object… args): 16 // * 参数说明: 17 // * obj : 要调用方法的对象; 18 // * args:调用方式时所传递的实参; 19 Class<UserInfo> userInfoClass = UserInfo.class; 20 21 22 System.out.println("--获取所有公有方法包括父类、Object等-返回值数组-"); 23 Method[] methods = userInfoClass.getMethods(); 24 for (Method method : methods) { 25 System.out.println(method); 26 } 27 28 System.out.println("--获取类所有方法,包括私有的-返回值数组-"); 29 Field[] declaredFields = userInfoClass.getDeclaredFields(); 30 for (Field declaredField : declaredFields) { 31 System.out.println(declaredField); 32 } 33 34 System.out.println("--获取任意公有方法-返回值 单一方法-"); 35 try { 36 Method test = userInfoClass.getMethod("test", Integer.class); //指定一个参数的方法(此方法为public修饰),此方法返回值为实例变量str 37 UserInfo userInfo = userInfoClass.newInstance(); //获取一个实例 38 Object test1 = test.invoke(userInfo, 100); // 实例 + 参数 39 System.out.println(test1); 40 41 } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) { 42 e.printStackTrace(); 43 } 44 45 System.out.println("---获取任意方法,包括私有的-返回值 单一方法----"); 46 try { 47 Method test = userInfoClass.getDeclaredMethod("test", String.class, Integer.class);//可以指定私有test方法 48 UserInfo userInfo = userInfoClass.newInstance(); //获取一个实例 49 test.setAccessible(true); //授权 50 Object hello = test.invoke(userInfo, "hello", 100); 51 System.out.println(hello); 52 } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) { 53 e.printStackTrace(); 54 } 55 56 57 }
输出值为
1 Reflection.reflectionTest 2 --获取所有公有方法-返回值数组- 3 public java.lang.String Reflection.UserInfo.toString() 4 public java.lang.Integer Reflection.UserInfo.getId() 5 public java.lang.String Reflection.UserInfo.test(java.lang.Integer) 6 public void Reflection.UserInfo.setId(java.lang.Integer) 7 public final void java.lang.Object.wait() throws java.lang.InterruptedException 8 public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException 9 public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException 10 public boolean java.lang.Object.equals(java.lang.Object) 11 public native int java.lang.Object.hashCode() 12 public final native java.lang.Class java.lang.Object.getClass() 13 public final native void java.lang.Object.notify() 14 public final native void java.lang.Object.notifyAll() 15 --获取所有方法,包括私有的-返回值数组- 16 private java.lang.String Reflection.UserInfo.name 17 public java.lang.String Reflection.UserInfo.str 18 private java.lang.Integer Reflection.UserInfo.id 19 --获取任意公有方法-返回值 单一方法- 20 num:100 21 你好 22 ---获取任意公有方法,包括私有的-返回值 单一方法---- 23 test.......num:100 24 hello
3.4、获取注解
1 private static void testAnnotation() { 2 Class<UserInfo> infoClass = UserInfo.class; 3 4 //获得类上的注解 5 MyAnnotation annotation = infoClass.getAnnotation(MyAnnotation.class); 6 System.out.println(annotation.name());//赋值了tom 7 8 9 System.out.println("-------------------------------"); 10 try { 11 //获得方法上的注解 12 MyAnnotation myAnnotation = infoClass.getMethod("test", Integer.class).getAnnotation(MyAnnotation.class); 13 System.out.println(myAnnotation.name());//不赋值为Jim 14 } catch (NoSuchMethodException e) { 15 e.printStackTrace(); 16 } 17 }
输出结果
1 tom 2 ------------------------------- 3 Jim
怕什么真理无穷,进一寸有一寸的欢喜!

浙公网安备 33010602011771号