深耕静禅_Java_反射_2020年4月4日15:29:46

上文有枚举,其有部分删减则为反射。时用反射剖析枚举类中各内容及继承,使之哗然,甚不知反射如此重要,无论研究学习亦工作生产。特此紧跟反射一文,助日后学习可用。反射曾位于个人教学文案中,可日久未阅依然积灰破败,新上一封,亦是重学。——2020年4月4日

概述

  • Java反射,即将运行时已加载至内存之中数据,以人类可理解之对象进行解剖使用。

  • 利其特性,可知内存对象中属性方法等任意内容,且可动态获取其实时的数据。

  • 反射仅用Java中已存对象即可实现,各对象完成对内存之剖析与展示,简便矣。

反射常用类API

类名 用途
Class 代表类的实体,在运行的Java应用程序中表示类和接口
Field 代表类的成员变量(成员变量也称为类的属性)
Method 代表类的方法
Constructor 代表类的构造方法

Class类

  • 其描述“类”一物质的相关数据,所有Java程序皆有类组成,此类即可描述最基础Java分子。

  • 利用其类,可读取某类数据,可用以下方法对目标进行读取:

    方法 用途
    asSubclass(Class<U> clazz) 把传递的类的对象转换成代表其子类的对象
    Cast 把对象转换成代表类或是接口的对象
    getClassLoader() 获得类的加载器
    getClasses() 返回一个数组,数组中包含该类中所有公共类和接口类的对象
    getDeclaredClasses() 返回一个数组,数组中包含该类中所有类和接口类的对象
    forName(String className) 根据类名返回类的对象
    getName() 获得类的完整路径名字
    newInstance() 创建类的实例
    getPackage() 获得类的包
    getSimpleName() 获得类的名字
    getSuperclass() 获得当前类继承的父类的名字
    getInterfaces() 获得当前类实现的类或是接口
  • 可用其获得某类中属性内容,仅需调用Class类中方法即可:

    方法 用途
    getField(String name) 获得某个公有的属性对象
    getFields() 获得所有公有的属性对象
    getDeclaredField(String name) 获得某个属性对象
    getDeclaredFields() 获得所有属性对象
  • 可获得类中注解信息,调用以下方法:

    方法 用途
    getAnnotation(Class<A> annotationClass) 返回该类中与参数类型匹配的公有注解对象
    getAnnotations() 返回该类所有的公有注解对象
    getDeclaredAnnotation(Class<A> annotationClass) 返回该类中与参数类型匹配的所有注解对象
    getDeclaredAnnotations() 返回该类所有的注解对象
  • 可获得构造器信息,调用以下方法:

    方法 用途
    getConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法
    getConstructors() 获得该类的所有公有构造方法
    getDeclaredConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的构造方法
    getDeclaredConstructors() 获得该类所有构造方法
  • 可获得类中方法,调用以下方法:

    方法 用途
    getMethod(String name, Class...<?> parameterTypes) 获得该类某个公有的方法
    getMethods() 获得该类所有公有的方法
    getDeclaredMethod(String name, Class...<?> parameterTypes) 获得该类某个方法
    getDeclaredMethods() 获得该类所有方法
  • 其他常用的方法如下:

    方法 用途
    isAnnotation() 如果是注解类型则返回true
    isAnnotationPresent(Class<? extends Annotation> annotationClass) 如果是指定类型注解类型则返回true
    isAnonymousClass() 如果是匿名类则返回true
    isArray() 如果是一个数组类则返回true
    isEnum() 如果是枚举类则返回true
    isInstance(Object obj) 如果obj是该类的实例则返回true
    isInterface() 如果是接口类则返回true
    isLocalClass() 如果是局部类则返回true
    isMemberClass() 如果是内部类则返回true

Field类

方法 用途
equals(Object obj) 属性与obj相等则返回true
get(Object obj) 获得obj中对应的属性值
set(Object obj, Object value) 设置obj中对应属性值

Method类

方法 用途
invoke(Object obj, Object... args) 传递object对象及参数调用该对象对应的方法

Constructor类

方法 用途
newInstance(Object... initargs) 根据传递的参数创建类的对象
setAccessible(boolean flag) 设置构造方法访问权限,来自父类

使用反射

  • 备一可创建对象之测试类,名为Book,其中属性、构造方法、方法均有,且提供toString及封装内容:

    package com.xx;
    ​
    public class Book{
        private final static String TAG = "BookTag";
    ​
        private String name;
        private String author;
    ​
        @Override
        public String toString() {
            return "Book{" +
                    "name='" + name + '\'' +
                    ", author='" + author + '\'' +
                    '}';
        }
    ​
        public Book() {
        }
    ​
        private Book(String name, String author) {
            this.name = name;
            this.author = author;
        }
    ​
        public String getName() {
            return name;
        }
    ​
        public void setName(String name) {
            this.name = name;
        }
    ​
        public String getAuthor() {
            return author;
        }
    ​
        public void setAuthor(String author) {
            this.author = author;
        }
    ​
        private String declaredMethod(int index) {
            String string = null;
            switch (index) {
                case 0:
                    string = "I am declaredMethod 1 !";
                    break;
                case 1:
                    string = "I am declaredMethod 2 !";
                    break;
                default:
                    string = "I am declaredMethod 1 !";
            }
    ​
            return string;
        }
    }
  • 可对其进行读取并创建对象,此类创建对象并未new方式,而是反射方式:

    public static void reflectNewInstance() {
        try {
            //使用forName方法,对类进行定为,此处传入Book类全限定名
            Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
    ​
            //newInstance方法可获取此类对象
            Object objectBook = classBook.newInstance();
    ​
            //对其转型后即可调用其中方法
            Book book = (Book) objectBook;
            book.setName("Android进阶之光");
            book.setAuthor("刘望舒");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
  • 可读取到类构造方法,此方法访问权限为私有,可将其设置为“可访问”后利用其创建对象:

    public static void reflectPrivateConstructor() {
        try {
            //对类进行读取定为
            Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
    ​
            //getDeclaredConstructor方法可获得构造方法,并可根据传入参数获得指定构造,此处获得两个String参数构造
            Constructor<?> declaredConstructorBook = classBook.getDeclaredConstructor(String.class,String.class);
    ​
            //将访问权限设置为:可防伪标
            declaredConstructorBook.setAccessible(true);
    ​
            //利用构造方法进行对象创建,且传入参数。下文中进行类型转换
            Object objectBook = declaredConstructorBook.newInstance("Android开发艺术探索","任玉刚");
            Book book = (Book) objectBook;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
  • 可对其属性进行获取,在获取其值时要注意指定:哪个对象中此属性之值:

    public static void reflectPrivateField() {
        try {
            //对类进行加载
            Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
    ​
            //通过Class对象进行对象创建
            Object objectBook = classBook.newInstance();
    ​
            //使用Class类中方法,通过属性名获取属性
            Field fieldTag = classBook.getDeclaredField("TAG");
    ​
            //因其访问类型为私有,将其开放
            fieldTag.setAccessible(true);
    ​
            //获得此属性位于objectBook对象中之值
            String tag = (String) fieldTag.get(objectBook);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
  • 对其方法访问依然要使用类定为的方式,在方法参数过多时,可在getDeclaredMethod方法中继续向后累加参数:

    public static void reflectPrivateMethod() {
        try {
            //对类进行读取
            Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
    ​
            //获取类中方法,根据方法名即参数类型
            Method methodBook = classBook.getDeclaredMethod("declaredMethod",int.class);
    ​
            //将其访问权限修改为开放访问
            methodBook.setAccessible(true);
    ​
            //创建类对象
            Object objectBook = classBook.newInstance();
    ​
            //使用方法对象进行方法启动,定为于哪个类中,并传入参数。并获得返回值
            String string = (String) methodBook.invoke(objectBook,0);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

猜你喜欢

转载自www.cnblogs.com/agoodjavaboy/p/12632083.html