码迷,mamicode.com
首页 > 编程语言 > 详细

Java中类加载机制和反射技术

时间:2016-11-02 23:40:44      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:font   类对象   动态   rate   它的   class   创建   edm   方便   

       我们知道一个对象在运行时有两种类型,一个是编译类型,一个是运行时类型。在程序运行时,往往是需要发现类和对象的真实的信息的。那么如何获的这种信息呢?

其一,如果我们在编译和运行时都知道类型的具体信息,这时是可以手动将一个对象转换为运行时的类型。

其二,如果我们在编译时无法预知对象和类到底是属于哪些类,那么程序只有依靠运行时的信息来发现对象和类的真实的信息了,这时就必须要用到反射技术。

在谈具体的发射技术之前,我想先回顾下,有关类的加载的一些基本的性质和原理,以方便我们更好地理解,反射的作用和特点。而实际上,一个类如果可以被执行,那么对于JVM来说,它的执行流程为:类的加载、连接、初始化。通过这种方式,才可以获取到一个类的类对象,即java.lang.Class对象,并在此基础上获取到该类的成员变量,方法和构造器等内在的东东。

   那么,什么是类的加载呢?类的加载就是将类的class文件读入内存,并为之创建一个java.lang.Class对象,也就是说当程序使用任何类时,系统都会为之建立一个java.lang.Class对象。同时,类的加载是由类加载器完成的。

类的连接:连接阶段负责把类的二进制数据合并到JRE中。第一,验证,检验被加载的类是否有正确的内部结构;第二,准备,负责为类的类变量分配内存,并设置默认初始值。第三,解析将类的二进制数据中的符号引用替换成直接引用。类的初始化,主要对类变量进行初始化。

   这样,我们清楚地认识到了一个类的生命周期变化,那么这些也为我们的反射机制带来了铺垫,要获取一个类的class对象,有三重方式:

       (1)使用Class类的forName(String clazzName)静态方法

       (2)调用某个类的class属性获取该类对应的Class对象

       (3)调用某个类的getClass()方法

       通过这三种手段就可以获取到了一个类的Class对象,这样就可以动态获取该对象的实际的信息了。下面通过一个具体的例子说明下,如果通过反射机制,创建一个类的对象,如何通过获取的对象再进一步获取该对象的属性和方法,以及动态为该对象注入新的参数值。

 

 1 package ReflectionEntity;
 2 import java.util.Date;
 3 
 4 /**
 5  * @author XuJiaqing
 6  * 
 7  */
 8 public class Student {
 9     //get/set方法
10     public String getStudentID() {
11         return studentID;
12     }
13 
14     public void setStudentID(String studentID) {
15         this.studentID = studentID;
16     }
17 
18     public String getStudentName() {
19         return studentName;
20     }
21 
22     public void setStudentName(String studentName) {
23         this.studentName = studentName;
24     }
25 
26     public Date getBirthday() {
27         return birthday;
28     }
29 
30     public void setBirthday(Date birthday) {
31         this.birthday = birthday;
32     }
33 
34     public int getScore() {
35         return score;
36     }
37 
38     public void setScore(int score) {
39         this.score = score;
40     }
41 
42     private String studentID;//学生id
43     public String studentName;//学生姓名
44     private Date birthday;//学生生日
45     private int score;//学生成绩
46     //实现的任务 的方法
47     public void achieveTask(String taskName) {
48         System.out.println(studentName + "实现了" + taskName + "技术");
49     }
50 }

 

package ReflectionTest;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import ReflectionEntity.Student;

/**
 * @author XuJiaqing
 * 
 */
public class test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            // 获取Student的Class对象
            Class<?> clazz = Class.forName("ReflectionEntity.Student");
            // 获取该类中所有的属性
            Field[] fields = clazz.getDeclaredFields();
            // 遍历所有的属性
            for (Field field : fields) {
                // 打印属性信息,包括访问控制修饰符,类型及属性名
                System.out.println(field);
                System.out.println("修饰符:"
                        + Modifier.toString(field.getModifiers()));
                System.out.println("类型:" + field.getType());
                System.out.println("属性名:" + field.getName());
            }
            // 获取该类中的所有方法
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                // 打印方法签名
                System.out.println(method);
                System.out.println("修饰符:"
                        + Modifier.toString(method.getModifiers()));
                System.out.println("方法名:" + method.getName());
                System.out.println("返回类型:" + method.getReturnType());
                // 获取方法的参数对象
                Class<?>[] clazzes = method.getParameterTypes();
                for (Class<?> class1 : clazzes) {
                    System.out.println("参数类型:" + class1);
                }
            }

            // 通过Class对象创建实例
            Student student = (Student) clazz.newInstance();
            // 获取属性名为studentName的字段(Field)对象,以便下边重新设置它的值
            Field studentName = clazz.getField("studentName");
            // 设置studentName的值为”XuJiaqing“
            studentName.set(student, "XuJiaqing");

            // 通过Class对象获取名为”finishTask“,参数类型为String的方法(Method)对象
            Method finishTask = clazz.getMethod("achieveTask", String.class);
            // 调用achieveTask方法
            finishTask.invoke(student, "反射");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

包的目录结构和运行结果为:

技术分享

 

Java中类加载机制和反射技术

标签:font   类对象   动态   rate   它的   class   创建   edm   方便   

原文地址:http://www.cnblogs.com/jiaqingshareing/p/6024541.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!