Java反射机制是Java语言被视为准动态语言的关键性质。Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调用其方法或修改其域(甚至是本身声明为private的域或方法)。很多主流框架使用了反射,如典型的Spring的IOC(控制反转)、读取properties文件内容等
Class类是整个Java反射机制的源头,因此,要想使用Java反射,我们首先得到Class类的对象。
准备好一个实体类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class User { private Integer id; private String name; private Integer age; public User (Integer id, String name, Integer age) { this .id = id; this .name = name; this .age = age; } public User () { } private void say (String word) { System.out.println(word); } public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Integer getAge () { return age; } public void setAge (Integer age) { this .age = age; } }
获取Class的方式: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class ReflectDemo { public static void main (String[] args) { try { Class<User> userClass1 = User.class; Class<?> userClass2 = Class.forName("com.yakai.bean.User" ); User user = new User (); Class<? extends User > userClass3 = user.getClass(); System.out.println(userClass1); System.out.println(userClass2); System.out.println(userClass3); Integer i = 4 ; Boolean b = false ; Class<Integer> iClass = i.TYPE; Class<Boolean> bClass = b.TYPE; System.out.println(iClass); System.out.println(bClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
操作class对象: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public class ReflectDemo2 { public static void main (String[] args) { try { Class<?> userClass = Class.forName("com.yakai.bean.User" ); Object o = userClass.newInstance(); User user=null ; if (o instanceof User){ user= (User) o; } System.out.println(user); Field[] fields = userClass.getDeclaredFields(); Field nameField = userClass.getDeclaredField("name" ); Method[] declaredMethods = userClass.getDeclaredMethods(); Method setName = userClass.getDeclaredMethod("setName" , String.class); setName.invoke(user,"zhangsan" ); System.out.println(user.getName()); Method say = userClass.getDeclaredMethod("say" ,String.class); say.invoke(user, "helloworld" ); Constructor<?>[] constructors = userClass.getConstructors(); Constructor<?> constructor = userClass.getConstructor(); System.out.println(constructor); Constructor<?> constructor2 = userClass.getConstructor(Integer.class, String.class, Integer.class); System.out.println(constructor2); Class<?>[] interfaces = userClass.getInterfaces(); } catch (Exception e) { e.printStackTrace(); } } }
执行say.invoke(user, "helloworld");
报错!错误信息:
1 2 3 4 5 6 java.lang.IllegalAccessException: Class com.yakai.demo.ReflectDemo2 can not access a member of class com .yakai.bean.User with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102 ) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296 ) at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288 ) at java.lang.reflect.Method.invoke(Method.java:490 ) at com.yakai.demo.ReflectDemo2.main(ReflectDemo2.java:44 )
这是因为如果要执行private修饰的方法,必须要say.setAccessible(true);
才可以
添加这行代码后再执行:
1 2 3 4 5 com.yakai.bean.User@1b6d3586 zhangsan helloworld public com.yakai.bean.User()public com.yakai.bean.User(java.lang.Integer,java.lang.String,java.lang.Integer)
同样对于私有属性Field来说,也是需要field.setAccessible(true);
才可以调用私有属性。
JAVA反射的再次学习,灵活的运用它,能够使我们的代码更加灵活,但是它也有它的缺点,就是运用它会使我们的软件的性能降低,复杂度增加。