Java反射,即将运行时已加载至内存之中数据,以人类可理解之对象进行解剖使用。
利其特性,可知内存对象中属性方法等任意内容,且可动态获取其实时的数据。
反射仅用Java中已存对象即可实现,各对象完成对内存之剖析与展示,简便矣。
类名 | 用途 |
---|---|
Class | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field | 代表类的成员变量(成员变量也称为类的属性) |
Method | 代表类的方法 |
Constructor | 代表类的构造方法 |
其描述“类”一物质的相关数据,所有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 |
方法 | 用途 |
---|---|
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Object obj, Object value) | 设置obj中对应属性值 |
方法 | 用途 |
---|---|
invoke(Object obj, Object... args) | 传递object对象及参数调用该对象对应的方法 |
方法 | 用途 |
---|---|
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(); } }
深耕静禅_Java_反射_2020年4月4日15:29:46
原文:https://www.cnblogs.com/agoodjavaboy/p/12632083.html