java——反射机制

要点

  1. java反射机制
  2. 反射机制的功能
  3. Class类
  4. 方法反射
  5. 反射机制的应用

java反射机制

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

反射机制的功能
主要是动态处理类

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

Class类
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。 Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

1、在java中,除了静态的成员、普通数据类型,其他的都是对象
2、class也是一个对象,是java.lang.Class类的实例对象
3、任何一个类都是Class的实例对象

        //Food的实例对象是foo1
        Food foo1 = new Food();
        //Food这个类 是Class类的实例对象,这个实例对象有三种表示方式

        //第一种表示方式(任何一个类都有一个隐含的静态成员变量class)
        Class c1 = Food.class;

        //第二中表达方式  已经知道该类的对象通过getClass方法
        Class c2 = foo1.getClass();

        //第三种表达方式
        Class c3 = null;
        try {
            c3 = Class.forName("test.reflect.Food");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 实例对象c1 ,c2,c3 表示了Food类的类类型(class type)

        //不管c1  or c2都代表了Food类的类类型,一个类只可能是Class类的一个实例对象
        //c1 == c2 的结果是true
                Class c = obj.getClass();

        /*
         * 类的成员变量也是对象
         * java.lang.reflect.Field
         * Field类封装了关于成员变量的操作
         * getFields()方法获取的是所有的public的成员变量的信息
         * getDeclaredFields获取的是该类自己声明的成员变量的信息
         */
        //Field[] fs = c1.getFields();
        Field[] fs = c1.getDeclaredFields();
        for (Field field : fs) {
            //得到成员变量的类型的类类型
            Class fieldType = field.getType();
            String typeName = fieldType.getName();
            //得到成员变量的名称
            String fieldName = field.getName();
            System.out.println(typeName+" "+fieldName);
        }
        /*
         * 构造函数也是对象
         * java.lang. Constructor中封装了构造函数的信息
         * getConstructors获取所有的public的构造函数
         * getDeclaredConstructors得到所有的构造函数
         */
        //Constructor[] cs = c.getConstructors();
        Constructor[] cs = c.getDeclaredConstructors();
        for (Constructor constructor : cs) {
            System.out.print(constructor.getName()+"(");
            //获取构造函数的参数列表--->得到的是参数列表的类类型
            Class[] paramTypes = constructor.getParameterTypes();
            for (Class class1 : paramTypes) {
                System.out.print(class1.getName()+",");
            }
            System.out.println(")");

方法反射

  1. 方法的名称和方法的参数列表才能唯一决定某个方法
  2. 方法反射的操作 method.invoke(对象,参数列表)

补充:编译和运行是两个不同的操作,先编译才可以运行,编译过程会进行静态加载类,实际开发中一些功能性的类应使用动态加载,从而使我们的项目健壮性更好,不会因为一个类出错而导致整个项目不能运行

 //要获取print(int ,int )方法  1.要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型
        A a1 = new A();
        Class c = a1.getClass();
        /*
         * 获取方法 名称和参数列表来决定  
         * getMethod获取的是public的方法
         * getDelcaredMethod自己声明的方法
         */
        try {
            //Method m =  c.getMethod("print", new Class[]{int.class,int.class});
            Method m = c.getMethod("print", int.class,int.class);//两种方法的效果是一样的

            //方法的反射操作  
            //a1.print(10, 20);方法的反射操作是用m对象来进行方法调用 和a1.print调用的效果完全相同
            //方法如果没有返回值返回null,有返回值返回具体的返回值
            //Object o = m.invoke(a1,new Object[]{10,20});
            Object o = m.invoke(a1, 10,20);
            System.out.println("==================");
            //获取方法print(String,String)
             Method m1 = c.getMethod("print",String.class,String.class);
             //用方法进行反射操作
             //a1.print("hello", "WORLD");
             o = m1.invoke(a1, "hello","WORLD");
             System.out.println("===================");
           //  Method m2 = c.getMethod("print", new Class[]{});
                Method m2 = c.getMethod("print");
               // m2.invoke(a1, new Object[]{});
                m2.invoke(a1);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        //ps:invoke方法可以绕过编译阶段,可以在指定类型的泛型集合中添加其他类型的数据

反射机制的应用

/**
 * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
 */ 

interface animal {
    public abstract void eat();
}
class Pig implements animal {
    public void eat() {
        System.out.println("I like eatting");
    }
}
class Dog implements fruit {
    public void eat() {
        System.out.println("dog");
    }
}
class Factory {
    public static animal getInstance(String ClassName) {
        animal animal1 = null;
        try {
            animal1= (animal) Class.forName(ClassName).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return animal1;
    }
}



PS:博文中如有什么不对的地方恳请大家指出,谢谢~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值