zoukankan      html  css  js  c++  java
  • 基础知识:Java反射机制

    反射机制的原理

       

    一般来说,如果想生成一个类的对象,那么运行这个程序的JVM会去确认这个类的class对象是否已经加载。如果尚未加载,那么JVM会根据类名查找.class文件,并将其载入,一旦这个类的class对象被载入内存,它就可以被用来创建这个类的的所有对象

       

    另外如果遇到一个未知类型的引用,(JVM?)通常会采用强制类型转换的形式来得到开发者想要的类型引用,如果执行了错误的类型转换,则会报一个ClassCastException异常

       

    在以上两个过程中,Class类一直都在起作用,因为Class类实例包含的是一个类的全部信息,包括方法、属性、构造器等

       

    如果不是在启动时去创建这个Class实例,而是在运行时获得这个Class类实例,那么我们就可以动态的去加载一个类,动态的调用类的方法,已经动态的去访问一个类的属性,反射机制就是为这种场景而产生的,反射机制的出发点就在于JVM会为每个类创建一个java.lang.Class类的实例,通过该对象可以获取该类的全部信息,然后通过java.lang.reflect包下的API以达到以上所述的动态需求

       

    三种情况会导致一个Java类被加载到JVM

       

    Student stu=new Student();

    使用该类创建对象

       

    System.out.println(student.count)

    访问该类的静态成员

       

    Class.forName("com.Student");

    使用Class类的静态方法forName方法,动态的加载一个指定类名的类

    ps…JDBC导入驱动类就是一个很常用的例子

       

    三种得到一个类Class对象的方法

       

    ClassforName方法返回的就是一个类的对象的引用

       

    通过类的Class属性

    Class<Student> clazz=Student.class;

       

    通过getClass方法,这个方法是从Object类继承下来的

    Student stu=new Student();

    Class<Student> clazz=stu.getClass();

       

    ps…获得类的Class对象后,就可以用这个对象创建和调用和访问这个类中的各种东西了

    ps…Class类对象的方法getNamegetConstructorgetMethodnewInstance

       

    Field的用法:操作类的成员变量

       

    通过Class类的getDeclaredField方法可以获得一个Field类对象的引用,有了这个对象的引用之后,就可以调用该对象的getXXX方法,其中XXX包括intdoublebyte等获得某个成员变量

       

    通过Field对象的使用来按照某一规则比较两个对象的大小

       

    private static FieldReflect compareReflect(FieldReflect obj1,FieldReflect obj2)

       

    三种获得的方式,本质上是三种获得Class对象的方式

       

    //1

    Field field=obj1.getClass().getDeclaredField("age");

    //2

    Field field=FieldReflect.class.getDeclaredField("age");

    //3

    Class clazz = Class.forName("com.FieldReflect.FieldReflect");

       

    得到Class对象之后,就可以调用getDeclaredField方法得到Field对象的引用了

       

    Field field = clazz.getDeclaredField("age");

       

    得到Field对象的引用之后,就可以调用getXXX方法获得某一成员变量了

       

    Field的用法:操作类的私有成员

       

    首先我们写一个类,类的成员变量为私有

       

    class PrivateFieldReflectClass {

    private String name;

    private int age;

    public PrivateFieldReflectClass(String name, int age) {

    super();

    this.name = name;

    this.age = age;

    }

    }

    然后我们在主类中去通过反射机制得到类的Field

       

    public class PrivateFieldReflectTest {

    public static void main(String[] args) {

    PrivateFieldReflectClass fieldReflect1 = new PrivateFieldReflectClass(

    "Tong", 23);

    // 访问私有变量

    Class<PrivateFieldReflectClass> clazz = PrivateFieldReflectClass.class;

    Field field = clazz.getDeclaredField("age");

    // field.setAccessible(true);

    System.out.println(field.getInt(fieldReflect1));

    }

    }

       

    当我们试图去访问私有变量时,会发生错误java.lang.IllegalAccessException

    如果我们想去访问私有变量,需要把Field的实例对象设置Accessible属性为true即可

       

    Field的用法:覆盖toString方法,使其能够动态更改类对象的toString展示

       

    需要覆盖类中的toString方法,主要思想就是用类对象的getDeclaredFields方法得到Field数组,循环遍历,得到相应的NameValue

       

    class DataObject{

    private String name;

    private int age;

    private String description;

    private String other;

    public DataObject(String name, int age, String description, String other) {

    super();

    this.name = name;

    this.age = age;

    this.description = description;

    this.other = other;

    }

    @Override

    public String toString() {

    StringBuffer sb=new StringBuffer();

    Field[] fields=DataObject.class.getDeclaredFields();

    for (Field field : fields) {

    sb.append(field.getName());

    sb.append("=");

    sb.append(field.get(this));

    sb.append(" ");

    }

    return sb.toString();

    }

    }

       

    Method的用法:操作类的方法

       

    Method类,代表的是类的方法,包括静态和非静态的,与Field类似,通过反射机制,具体来说就是通过Class类对象的getMethod方法可以获得Method类的对象,然后通过该对象额invoke方法,将类名作为参数传入该方法,即可完成方法的调用

       

    首先类中定义两个方法

       

    public class MethodReflect {

    public void m1() {

    System.out.println("method 1");

    }

    public void m2() {

    System.out.println("method 2");

    }

    }

       

    然后在main函数就可以利用反射机制获取并调用想要的方法了

    反射机制的过程仍旧是先得到类的对象的引用,然后通过类对象的getDeclaredMethod方法得到方法类对象的引用,然后创建一个类的对象,然后利用方法对象的invoke方法将刚创建的类对象作为参数传入,注意,这里如果方法有参数,需要将参数列表也作为参数传入invoke

       

    Class clazz=MethodReflect.class;

    Method method=clazz.getDeclaredMethod("m1");

    MethodReflect methodReflect=new MethodReflect();

    method.invoke(methodReflect);

       

    Constructor类的用法:利用反射机制实例化一个类

       

    一般来说,我们可以通过new关键字实例化一个类,也就是创建一个类的对象,而如何通过反射机制实例话一个类呢,其实不管是通过new关键字还是通过反射,都是去调用类的构造函数,如果是去调用无参的构造函数,我们可以使用ClassnewInstance方法。如果是要用到有参的构造函数的话,我们就需要用到反射包下的Constructor

       

    首先也是要得到类的对象的引用

       

    Class<Student> clazz1=Student.class;

    //无参:通过newInstance

    Student student1=clazz1.newInstance();

    //有参:通过构造器

    Constructor<Student> constructor=clazz1.getConstructor(String.class,int.class);

    student1=constructor.newInstance("Tong",23);

       

  • 相关阅读:
    使用火炬之光资源(转)
    (转)Visual Leak Detector (VLD)使用
    (转)ofusion 导出注意事项
    OgreMax 导出(转)
    (转)C++ 内存池 C++ Memory Pool 翻译版
    Maven教程初级篇01: 简介
    浅谈JSON 数据源格式
    面向连接的Socket Server的简单实现
    oracle杀死死锁进程
    重构——让程序员快乐的工作
  • 原文地址:https://www.cnblogs.com/keedor/p/4495040.html
Copyright © 2011-2022 走看看