zoukankan      html  css  js  c++  java
  • java学习--Reflection反射机制

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

    Java反射机制主要提供了以下功能:

    1. 在运行时判断任意一个对象所属的类;

    Integer aInteger = Integer.valueOf(120);
    boolean isEqual = Integer.class.isInstance(bInteger);

    判断aInteger对象是否是Integer类的实例,返回的值是true

    2. 在运行时构造任意一个类的对象;

    Class clazz = Class.forName("java.lang.Strings");
    String newString = (String) clazz.newInstance();

    这个class只能调用类的无参构造方法,如果需要调用有参构造方法需要使用Constractor.newInstace方法

    3. 在运行时判断任意一个类所具有的成员变量和方法;

     getFields和getMethods方法获取所有非private的变量和方法数组

    4. 在运行时调用任意一个对象的方法;生成动态代理。

                Class<?> clazz = Class.forName("java.lang.String");
                String newString = (String) clazz.newInstance();
                newString = "123456789";
                Method lengthMethod = clazz.getMethod("length");
                int length = (int) lengthMethod.invoke(newString);
                System.out.println("字符串长度:"+length);
    //输出
    字符串长度:9

    不华丽得分割线


    Java有个Object 类,是所有Java 类的继承根源。其中方法getClass()返回一个Class 对象。

    Class没有public constructor。只有一个private constructor

    private Class() {},意指不允许任何人经由编程方式产生Class object。是的,其object 只能由JVM 产生。

    Class是Reflection故事起源。针对任何您想探勘的类,唯有先为它产生一个Class 对象,接下来才能经由后者唤起为数十多个的Reflection APIs。

    Member接口    该接口可以获取有关类成员(域或者方法)后者构造函数的信息。
    AccessibleObject类    该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认
                          Java 语言访问控制检查的能力。
    Array类    该类提供动态地生成和访问JAVA数组的方法。
    Constructor类    提供一个类的构造函数的信息以及访问类的构造函数的接口。
    Field类    提供一个类的域的信息以及访问类的域的接口。
    Method类    提供一个类的方法的信息以及访问类的方法的接口。
    Modifier类    提供了 static 方法和常量,对类和成员访问修饰符进行解码。
    Proxy类    
    提供动态地生成代理类和类实例的静态方法。

    获取Class方式

    getClass()、

    Sting s1="123"
    
    Class clazz=s1.getClass()

    getSuperclass()、

    Class superClazz=clazz.getSuperclass()

    运用.class 语法

    Class clazz=String.class

    运用static method------Class.forName()(最常被使用)

    Class clazz=Class.forName("java.lang.String")包名加类名

    运用primitive wrapper classes的TYPE 语法这里返回的是原生类型,和Boolean.class返回的不同

    基本数据类型及其包装类型才有

    Class<?> clazz=Integer.TYPE;//输出为int

    Class<?> clazz=int.class//输出为int

    Class<?> clazz=Integer.class//输出为class java.lang.Integer

    获取类的Fields

    Field getField(String name)获取对应name的field对象 即获取对应name的字段

    Field[] getFields()获得对象内所有public字段的field对象数组

    上面这两个只能获得所有public修饰符修饰的所有字段

    Field[] getDeclaredFields()获得本对象或接口内定义的所有field对象数组(包括public, protected, default (package) access, and private fields)。

    不包括继承的字段。

    This includes public, protected, default (package) access, and private fields, but excludes inherited fields.

    Field getDeclaredField(String name)这也只能获得本对象或接口定义的字段,不包括继承字段

    这两个declared方法可以获得本对象或接口内的所有字段包括public、protected、private、缺省修饰的字段,但不包括继承的字段

     运用,下面的Student类举例

    获取Student类定义的所有变量

    Class<?> clazz=Student.class;
    Field[] fields = clazz.getDeclaredFields(); for(Field f:fields){ f.setAccessible(true); System.out.println(f.getName()+"变量类型"+f.getGenericType()+"变量值"+(String)f.get(clazz)); }

    setAccessible(true)是为了能够访问private私有变量,否则当访问到是一个private 变量时会抛出异常。

    Set the accessible flag for this object to the indicated boolean value. A value of 
    true indicates that the reflected object should suppress Java language access 
    checking when it is used. A value of false indicates that the reflected object should
     enforce Java language access checks.
    当设值为true时这个反射对象应该禁止java语言访问检查
    值为false表示反射对象应强制实施Java语言访问检查。

    如果是要获取基本类型的值,有特定的方法可以调用类似getXxx(obj)

    如获取整形getInt(obj)

    获取类的Method

    通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法

    Method[] getMethods()同上获取所有共有方法的method对象数组

    Method getMethod(String name, Class<?>... parameterTypes)

    Method[] getDeclaredMethods()

    Method getDeclaredMethod(String name, Class<?>... parameterTypes)

    方法的说明和field变量/字段的说明相同。

    参数后面解释

    获取类的Constructor

    Constructor<?>[] getConstructors()

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

    Constructor<?>[] getDeclaredConstructors()

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

    新建类的实例(对象)

    调用无参的构造方法创建新的实例时2种方法

    Creates a new instance of the class represented by this Class object. The class is 
    如果这个类没有被实例化,则创建一个新的类的实例,这个类是被无参数列表的构造方法实例化了 instantiated as
    if by a new expression with an empty argument list. The class is initialized if it has not already been initialized

    Class.newInstance()

    Constructor.newInstance()

    调用有参的构造方法创建新的实例。

    java.lang.reflect.Constructor.newInstance(Object... initargs)
    Parameters:
    initargs array of objects to be passed as arguments to the constructor call; values of primitive types are wrapped in a wrapper object of the 11:20:42type 
    对属数组。构造方法中的参数列表
     
    运用
    新建一个Student类只有简单的姓名年龄
    public class Student {
        public int age;
        String name;
        public Student(){
            this.age = 0;
            this.name="default name";
        }
        public Student(int age, String name) {
            super();
            this.age = age;
            this.name = name;
        }
        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;
        }
        
        
    }
    View Code

     1、获得class类2、获得class类实例3、获得class类中指定方法4、反射调用该方法

            Class<?> clazz=Student.class;
            //System.out.println(clazz);
            //Object inst = clazz.newInstance();
            Constructor<?> constractor=clazz.getDeclaredConstructor(int.class,String.class);
            Object inst=constractor.newInstance(11,"德玛西亚");
            Method getNameMethod=clazz.getDeclaredMethod("getName");
            //Type methodType=getNameMethod.getReturnType();
            String stuName=(String) getNameMethod.invoke(inst);

    System.out.println("clazz:"+clazz);
    System.out.println("inst:"+inst);
    System.out.println("方法返回值类型"+methodType);
    System.out.println("返回值为"+stuName);

    clazz:class Student
    inst:Student@15db9742
    方法返回值类型class java.lang.String
    返回值为德玛西亚

    创建动态代理

    java.lang.reflect.Proxy    
    Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类
    InvocationHandler    
    是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

    抽象角色:声明真实对象和代理对象的共同接口

    代理角色:代理角色内部包含有真实对象的引用,从而可以操作真实对象。

    真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

    用不到的以后再补充

    经验有限,为防止忘记,做学习记录使用。

    参考资料http://blog.csdn.net/yongjian1092/article/details/7364451

  • 相关阅读:
    Git修改注释
    数组和切片的区别
    SpringBoot启动报:Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
    eclipse中web.xml报:The content of element type "web-app" must match "(icon?,display- name?,
    eclipse错误: 在类xxx中找不到 main 方法, 请将 main 方法定义为: public static void main(String[] args) 否则 JavaFX 应用程序类必须扩展javafx.application.Application
    idea Cannot resolve method ‘setAttribute(java.lang.String, java.lang.String)/不能使用pageContext.setAttribute()
    解决Nginx启动报nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    数据仓库开发规范
    详解会话技术cookie、session和token
    Requests爬虫包及解析工具 xpath、正则、Beautiful Soup
  • 原文地址:https://www.cnblogs.com/gne-hwz/p/7693946.html
Copyright © 2011-2022 走看看