生活中迷茫感的产生,往往源之于坚持一件事放弃的那一刻,因为从那一刻起,你开始变得无聊,变得没有方向感。
-
运行环境
** JDK8 + IntelliJ IDEA 2018.3 **
-
本文中使用的jar包链接
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">https://files.cnblogs.com/files/papercy/jsoup_jar%E5%8C%85.rar</pre>
-
概述
1、Java反射机制(Java-Reflect):
ava 反射是Java语言的一个很重要的特征,它使得Java具有了“动态性”。
Java提供了一套机制来动态获取类的信息以及动态调用对象的方法的功能,这套机制就叫——反射
在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java的反射机制。
反射机制是如今很多流行框架的实现基础,其中包括Struts、Spring、Hibernate等。
反射是Java开发中一个非常重要的概念,掌握了反射的知识,才能更好的学习Java高级课程.
2、Java 反射机制的功能
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
生成动态代理。
-
通过JAVA反射查看类信息
1、获得Class对象
每个类被加载之后,系统就会为该类生成一个对应的Class对象。通过该Class对象就可以访问到JVM中的这个类。
在Java程序中获得Class对象通常有如下四种方式:
- obj.getClass();
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;"> Object obj=new String();
Class clz1 = obj.getClass();
System.out.println("第一种:"+clz1); </pre>
- class属性
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;"> Class clz2 = String.class;
System.out.println("第二种:"+clz2);</pre>
- Class.forName();
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;"> Class clz3 = Class.forName("java.lang.String");
System.out.println("第三种:"+clz3);</pre>
- ClassLoader
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;"> ClassLoader cl = ClassLoader.getSystemClassLoader();
Class clz4 = cl.loadClass("java.util.ArrayList");
System.out.println("第四种:"+clz4);</pre>
运行结果:
-
构造方法
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">public static void main(String[] args) throws Exception { //反射string 类的所有构造方法
Class clz = Student.class;
System.out.println("所有构造方法:");
Constructor[] cons = clz.getConstructors();
cons = clz.getDeclaredConstructors(); for (Constructor con : cons) {
System.out.println("访问修饰权限:" + Modifier.toString(con.getModifiers()));
System.out.println("方法名:" + con.getName());
System.out.println("****************************");
System.out.println(Modifier.toString(con.getModifiers()) + " "
+ con.getName());
}
System.out.println("=============================="); //找无参的构造方法
Student s = new Student();
Constructor con = clz.getDeclaredConstructor();
Object obj = con.newInstance();
System.out.println(obj); //找带string,int类型参数的构造方法
Student s1 = new Student("zhangsan",12);
con = clz.getDeclaredConstructor(String.class, int.class);
obj = con.newInstance("zhangsan", 12);
System.out.println(obj);
con = clz.getDeclaredConstructor(String.class);
}</pre>
运行结果:
-
Class中的常用方法(获得类的属性)
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;"> 1 public static void main(String[] args) throws Exception { 2
3 Class clz = Student.class;
4
5 System.out.println("得到所有字段:");
6 Field[] fields = clz.getDeclaredFields(); 7 for(Field field : fields) {
8 System.out.println(Modifier.toString(field.getModifiers())+" " + field.getType().getSimpleName() + " " + field.getName()); 9 } 10 //利用反射为s学生对象的两个属性字段赋值
11 Student s= new Student(); 12 Class clzz = s.getClass(); 13 System.out.println(clzz); 14 System.out.println("======================"); 15
16 //为x字段赋值
17 Field field_x = clzz.getField("x"); 18 field_x.set(s, "feifeiye"); 19 System.out.println(s.x); 20 System.out.println("======================"); 21
22 //得到name字段
23 Field field_name = clzz.getDeclaredField("name"); 24 field_name.setAccessible(true); 25 field_name.set(s, "zhangsan"); 26 field_name.setAccessible(false); 27
28 Field field_age = clzz.getDeclaredField("age"); 29 field_age.setAccessible(true); 30 field_age.set(s, 20); 31 field_age.setAccessible(false); 32 System.out.println(s); 33
34 }</pre>
运行结果:
-
Class中的常用方法(获得类的方法)
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;"> 1 public static void main(String[] args) throws Exception { 2 Class clz = Student.class;
3
4 Method[] methods = clz.getDeclaredMethods(); 5 for (Method method : methods) { 6 Class[] clzz = method.getParameterTypes(); 7 String temp = "";
8 for(Class cz:clzz) {
9 temp += cz.getSimpleName()+","; 10 } 11
12 System.out.println(Modifier.toString(method.getModifiers()) + " "
13 + method.getReturnType().getSimpleName() + " "
14 + method.getName()+"("+temp+")"); 15 } 16
17
18 //调用类无参的构造方法实例化对象
19 Student st = (Student)clz.newInstance(); 20
21 //调用无参的构造方法实例化
22 Student st1 = (Student)clz.getConstructor().newInstance(); 23
24
25 //得到fun1方法并调用
26 Method method_fun1 = clz.getMethod("fun1", String.class, int.class); 27 method_fun1.invoke(st, "feifeiye", 100); 28
29
30 Method method_fun2 = clz.getMethod("fun2", String.class, int.class, double.class); 31 Object returnValue = method_fun2.invoke(st, "feifeiye",200, 3.14); 32 System.out.println(returnValue); 33
34
35 }</pre>
运行结果:
-
反射动态调用类的成员
调用方法步骤:
- 设定调用方法的参数列表(Class[])
- 获得调用方法的对象(Method)
- 设定调用方法的参数的值(Object[])
- 普通方法:invoke(obj,values);
- 构造方法:newInstance(values)
调用属性步骤:
- 根据属性名字获得属性对象(Field)
- 赋值:set(obj,value)
- 取值:get(obj)
- 如果需要强制访问类的私有成员,则需要设定:setAccessible(true);
-
总结