JAVA中的反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。


先看一下反射的概念:

              主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

             反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!

             看概念很晕的,继续往下看。

 

反射机制的作用:

             

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法

在这里先看一下sun为我们提供了那些反射机制中的类:

java.lang.Class;                

java.lang.reflect.Constructor; java.lang.reflect.Field;        

java.lang.reflect.Method;

java.lang.reflect.Modifier;


class 类

众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、 equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。 Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、 array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载, 或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。如果您想借由“修改Java标准库源码” 来观察Class 对象的实际生成时机(例如在Class的constructor内添加一个println()),这样是行不通的! 因为Class并没有public constructor。

具体实现

使用java的反射机制,一般需要遵循三步:

    1. 获得你想操作类的Class对象
    2. 通过第一步获得的Class对象去取得操作类的方法或是属性名
    3. 操作第二步取得的方法或是属性

     Java运行的时候,某个类无论生成多少个对象,他们都会对应同一个Class对象,它表示正在运行程序中的类和接口。如何取得操作类的Class对象,常用的有三种方式:

    1. 调用Class的静态方法forName,如上例;
    2. 使用类的.class语法,如:Class<?> cls = String.class;
    3. 调用对象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();

首先我们写一个Employee类
public class Employee {
    public Employee(){  
        name = "nick";
        age = 25;
    }
    String name="";
    int age=0;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


1,反射机制获取类有三种方法,我们来获取Employee的Class

       //第一种方式:  
            Class c1 = Class.forName("package.xxx.Employee"); //完整的路径名
            //第二种方式:  
            //java中每个类型都有class 属性.  
            Class c2 = Employee.class;

            //第三种方式:  
            //java语言中任何一个java对象都有getClass 方法  
            Employee e = new Employee();
            Class c3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)  
注意 Employee若是内部类,这类名前为$号,而不是“.”
 
2 ,创建对象:获取类以后我们来创建它的对象,利用 new Instance
   Class c =Class.forName("com.jd.wxsq.jzcircle.bean.Employee");
        //创建此Class 对象所表示的类的一个新实例
        Object o = c.newInstance(); //调用了Employee的无参数构造方法.

 
 
 
 

注意,若获取内部类构造方法时,需要将其外部类的类对象作为参数传进去

Constructor constructor = c.getDeclaredConstructor(new Class[] {

Out.class });

同样实例化内部类时,也需要将外部类对象作为参数传进去

obj = constructor.newInstance(new Out());


    3, 获取属性:分为所有的属性和指定的属性:
        //获取所有的属性?
            Field[] fs = c.getDeclaredFields();
            //定义可变长的字符串,用来存储属性
            StringBuffer sb = new StringBuffer();
            //通过追加的方法,将每个属性拼接到此字符串中
            //最外边的public定义
            sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");
            //里边的每一个属性
            for(Field field:fs){
                sb.append("\t");//空格
                sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
                sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字
                sb.append(field.getName()+";\n");//属性的名字+回车
            }

            sb.append("}");
由打印信息我们可以看到能够获取到Employee的所以成员。
        //获取特定的“name"属性
            Field f = c.getDeclaredField("name");
            //使用反射机制可以打破封装性,导致了java对象的属性不安全,设置可访问
            f.setAccessible(true);
            //给o对象的name属性赋值
            f.set(o,"Join");
通过上面方法我们可以获取指定的属性,并改变它的值。
4,获取方法
        //获取特定的setAge方法,Integer.TYPE为其对应的形参数类型
            Method method = c.getDeclaredMethod("setAge",Integer.TYPE);
            //调用特定的setAge方法,若为静态方法,则invoke的第一个参数为null
            method.invoke(o,100);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值