zoukankan      html  css  js  c++  java
  • java 反射

     

    反射的意义与作用

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;

    这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

    反射主要的作用如下:

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

    Java反射机制的实现要借助于4个类:Class,Constructor,Field,Method,反射的实现主要依靠Class类,以下重点阐述Class类。

    Class类

    Class类也是类的一种,只不过是一个比较特殊的类。Class类的对象用于描述某个类的信息(构造器、字段、方法)。

    得到某个类的Class对象有以下三种方法:

    通过该类实例对象的getClass()

            // num为Integer类的实例对象
            Integer num = new Integer(3);
            // 通过num的getClass()方法得到Integer类的Class对象
            Class<?> intClass = num.getClass();

    使用“类.class”取得

            // 得到Integer类的Class对象
            Class<?> intClass = Integer.class;

    使用Class类内部定义的一个static方法 forName(String className)

            // 得到Integer类的Class对象
            Class<?> intClass = Class.forName("java.lang.Integer");

    Class类对象的作用

    得到某个类的Class类对象,该Class对象包含了这个类的所有信息(所有的方法,所有的构造函数,所有的字段)。

    通过某个类的Class类对象,可以实现以下功能:

    创建该类实例(类似new)

    package exercise5;
    
    public class ReflectionTest {
    
    
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    
            // 得到Computer类的Class对象
            Class<?> computerClass = Class.forName("exercise5.Computer");
            // 通过Computer的Class对象computerClass
            // 创建Computer类的实例
            Computer com = (Computer) computerClass.newInstance();
        }
    }
    
    
    
    class Computer {
    
        public Computer() {
            System.out.println("A constructor without arguments");
        }
    
        public Computer(String name) {
            System.out.println("Name is " + name);
        }
    
        public Computer(String name, int i){
            System.out.println("Name is " + name);
            System.out.println("Price is " + price);
        }
    
    
        private String brand;
        public void setBrand(String brand) {this.brand = brand;}
        public String getBrand() {return this.brand;}
    
        private double price;
        public void setPrice(double price) {this.price = price;}
        public double getPrice() {return this.price;}
    
    }

    对于对象的实例化操作,除了使用关键字new之外又多了一个反射机制操作。

    获取该类的构造器对象及使用该对象调用该类的构造器

    取得一个类的指定参数构造:public Constructor<T> getConstructor(Class<?>... parameterTypes) 

    parameterTypes:方法参数的Class对象

        public static void main(String[] args) throws Exception {
    
            // 得到Computer类的Class对象
            Class<?> computerClass = Class.forName("exercise5.Computer");
            // 通过Computer的Class对象computerClass获取该类的第二个构造器对象
            Constructor<?> cons = computerClass.getConstructor(String.class);
            // 使用该构造器对象创建实例
            Computer com = (Computer) cons.newInstance("Acer");
        }

     几种获取构造器的方法

    public Constructor<?>[] getConstructors()                   获得所有公共构造方法

    public Constructor<?>[] getDeclaredConstructors()     获得所有构造方法(包括非public方法)

    public Constructor<T> getConstructor(Class<?>... parameterTypes)                    获得单个公共构造方法

    public Constructor<T> getDeclaredtConstructor(Class<?>... parameterTypes)     获得单个构造方法

    由上述两个例子可知,类对象computerClass.newInstance()   与   构造器对象cons.newInstance("Acer"); 都可以创建实例。

    类对象创建实例,只能调用public 无参的构造函数,相当于通过公共无参构造器对象创建实例。

    获取该类的方法对象及使用该对象调用该类的方法

     取得指定方法:public Method getMethod(String name, Class<?>... parameterTypes) 

    name:方法名

    parameterTypes:方法参数的Class对象

        public static void main(String[] args) throws Exception {
    
            // 得到Computer类的Class对象
            Class<?> computerClass = Class.forName("exercise5.Computer");
            // 创建Computer类的实例
            Computer com = (Computer) computerClass.newInstance();
    
            // 获取Computer类的setBrand()方法对象
            Method setMet = computerClass.getMethod("setBrand", String.class);
            // 通过该方法对象,调用com中的setBrand()方法
            setMet.invoke(com, "lenovo");
    
            // 获取Computer类的getBrand()方法对象
            Method getMet = computerClass.getMethod("getBrand");
            // 通过该方法对象,调用com中getBrand()方法
            System.out.println(getMet.invoke(com));
    
        }

      获取该类的属性(字段)对象及使用该对象调用该类的属性

     取得指定的成员:public Field getDeclaredField(String name)

    name:成员名字

        public static void main(String[] args) throws Exception {
    
            // 得到Computer类的Class对象
            Class<?> computerClass = Class.forName("exercise5.Computer");
            // 创建Computer类的实例
            Computer com = (Computer) computerClass.newInstance();
    
            // 获取Computer类的brand字段对象
            Field brandField = computerClass.getDeclaredField("brand");
            // 解除封装
            brandField.setAccessible(true);
            // 使用brandField对象设置com中brand的值
            brandField.set(com, "samsung");
            System.out.println(com.getBrand());
        }

    从类的开发要求而言,一直都强调类之中的属性必须封装,所以现在调用之前要想办法解除封装。

    解除封装:public void setAccessible(boolean flag) 

    getField 可以获取public字段,包括该类所定义的public字段与其所继承的public字段(父类中的public字段、父类的父类中的public字段、...,但不包括Object中的public字段)。
    getDeclaredField 可以获取该类本身所定义的字段,包括private、default、protected、public,但是不包括继承来的字段。
    getMethod 与 getDeclaredMethod() 相同的道理。

    总结:

    反射作用于程序运行阶段,主要通过Class类实现,Class可以获得某个类的Class对象,

    通过Class对象可以得到该类的所有信息(属性、构造器、方法),且可以创建该类的实例,调用该类的方法、构造器、属性。

  • 相关阅读:
    【转】android新建项目时 出现appcompat_v7工程错误和红色感叹号
    【转】eclipse新建项目,报错“Error: workspaceappcompat_v7 esvalues-v21styles_base.xml No resource found that matches the given name”
    【转】android开发工具Eclipse,androidStudio,adt网盘下载--不错
    【转】Windows搭建Eclipse+JDK+SDK的Android
    【转】Ubuntu 14.04配置安装java环境和android开发环境(包括真机调试环境)
    【转】[MTK软件原创] [SELinux] 如何设置确认selinux模式
    【转】Android中removeCallbacks失效原因
    【转】Android
    【转】Android开发20——单个监听器监听多个按钮点击事件
    【编程】辨异 —— proxy 与 delegate
  • 原文地址:https://www.cnblogs.com/deltadeblog/p/9391794.html
Copyright © 2011-2022 走看看