java反射机制

java反射机制

 

Ø  反射技术的由来?


         反射技术可以:通过配置文件的形式,配置具体dao的实现类,当调用这些方法的时候,可以读取配置文件,通过反射技术类来生成实例,以后需要变更的时候,直接的修改配置文件,大大的扩展了程序的可扩展性。

         目的就是为了让你不修改源码,直接扩展你的程序,这就是反射技术的由来。

 

Ø  什么是反射?

        

         对于一个java的可执行文件class,可以对这个文件进行解剖,直接从class文件中获取构造方法,成员变量,成员方法,有了这些方法和变量,那就可以运行这些方法。

 

         反射技术是在运行期间执行的,而非编译期间。

 

Ø  解析class字节码文件的方法?

 

java是一个面向对象的语言,一切都是对象,可执行文件class也是一个对象,既然class文件是一个对象,有没有描述这个对象类呢? java.lang.Class。

 

1、解析class对象的类:java.lang.Class

 

2、解析class文件中内容的类: java.lang.reflect

 

         一个class文件中,包含有构造方法,成员变量,成员方法。

        

         描述构造方法的类:

                   java.lang.reflect.Constructor

        

         描述成员变量的类:

                   java.lang.reflect.Field

        

         描述成员方法的类:

                   java.lang.reflect.Method

 

3、获取class字节码文件对象的3中方式?

 

   第一种方式,通过类的对象获取

           Person ps = new Person();

          Classc1 = ps.getClass();

 

  第二种方式,通过类名直接获取

           Class c2 = Person.class;

 

  第三种获取字节码文件对象的方式,使用是Class类的中一个静态方法 forName

         staticClass<?> forName(String className)

       Class c3 = Class.forName("cn.itcast.reflect.Person");

      

         重点推荐使用第三种方式,获取一个类的字节码文件对象。原因是:类名,是一个字符串的表现形式,可以采用参数传递的方式来获取灵活性,更高。

 

 

Ø  反射的步骤

         第一步:加载class字节码文件;

         第二步:通过java.lang.reflect反射类中的方法,反射出字节码文件中的内容。

 

1 访问构造方法

获取class字节码对象

       Class clazz  =Class.forName("cn.itcast.reflect.Person");

 

// 有了字节码文件对象,可以获取其中的构造方法,查找找Class类中的方法

// 获取一个构造方法,即可,区分构造方法的条件是:构造方法中的参数。

      

1,访问不带参数公共的构造方法

Constructor<T> getConstructor(Class<?>... parameterTypes)

返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。

 

Constructor con  =clazz.getConstructor();

Object obj = con.newInstance();//实例化

 

2,访问带参数公共的构造方法

Constructor con = clazz.getConstructor(int.class);

con.newInstance(20);

 

3,获取私有权限的构造方法

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法

Constructor描述构造方法的类,有一个父类, AccessibleObject

void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值。

constructor.setAccessible(true); // 取消访问检查,暴力访问

 

Constructor constructor = clazz.getDeclaredConstructor(String.class);

           constructor.setAccessible(true); // 取消访问检查,暴力访问

           constructor.newInstance("张三");

 

//返回所有的构造方法(了解)

Constructor [] constructors  =clazz.getDeclaredConstructors();

       for(int= 0 ; i < constructors.length ; i++){

           Constructor c = constructors[i];

           System.out.println(c);

           Class []type = c.getParameterTypes(); //获取参数类型

           for(Class cs:type){

              System.out.println(cs.getName());

           }

       }

 

 

2 获取成员变量,并修改值

// 获取class字节码对象

       Class clazz = Class.forName("cn.itcast.reflect.Person");

 

Field[] getFields()

1 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段

     Field[] fields = clazz.getFields();

    for(Field fd:fields){

       System.out.println(fd.getName());

    }

 

2 获取私有的属性

    Field field  = clazz.getDeclaredField("name"); //获取指定字段的值

    field.setAccessible(true); //取消该字段的访问权限

    Object obj = clazz.newInstance();//Class类中的方法 newInstanse()保证类有空参数的,权限是public的构造方法

    // void set(Object obj, Object value)

   //将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

       //改变该字段的值

   field.set(obj, "zhangsan");

   System.out.println(obj);

 

 

3 访问成员方法,并执行

 

// 获取class字节码对象

    Class clazz = Class.forName("cn.itcast.reflect.Person");

//获取到得是公共的,和继承的

    Method[] methods = clazz.getMethods();

    for(Method m:methods){

       System.out.println(m);

    }

//获取指定名称带参数的方法

    Method method = clazz.getMethod("show",String.class,int.class);

//获取到,运行的方法的

    method.invoke(clazz.newInstance(), "字符串",200);

// 获取静态方法

    Method method =  clazz.getMethod("testStatic");

    method.invoke(clazz.newInstance());

 

// 获取私有的方法

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

    //取消权限控制

    method.setAccessible(true);

    //执行

    method.invoke(clazz.newInstance());

 

 

4  通过反射,破坏单例设计模式

 

/**

 *单例

 */

publicclass Single {

    private Single() {}

    privatestaticfinal Single single = new Single();

    publicstatic Single getInstance() {

       returnsingle;

    }

}

 

/**

 *反射破坏单例模式

 */

publicclass Demo5 {

    publicstaticvoid main(String[] args) throws Exception {

       //获取Single类的字节码文件对象

       Class clazz = Single.class;

       // 获取构造方法

       Constructor con  = clazz.getDeclaredConstructor();

       // 取消权限控制

       con.setAccessible(true);

       //实例化

       System.out.println(con.newInstance());

       System.out.println(con.newInstance());

       System.out.println(con.newInstance());

       System.out.println(con.newInstance());

       System.out.println(con.newInstance());

      

    }

}

 

 

注意:

         一般情况下访问私有的成员变量、成员方法和构造方法,都是getDeclaredXX();

         直接使用clazz.newInstance()的时候,必须被反射的类中又一个公共的的空的构造方法。

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值