专栏首页迹_Jason的AppZoneJava反射获取类和对象信息全解析

Java反射获取类和对象信息全解析

反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题。

在两个人协作开发时,你只要知道对方的类名就可以进行初步的开发了。

获取类对象

  • Class.forName(String clazzName)静态方法
  • 调用类的class属性,Person.class返回的就是Person的class对象(推荐使用)
  • 调用某个对象的getClass()方法

具体使用还是要根据实际来选择,第一种方式是比较自由的,只要知道一个类名就可以了,其不会做该类是否存在的校验,第二种、第三种则会做校验

获取类的信息

获取类构造器
  • Connstructor<T> getConstructor(Class<?>...parameterTypes):返回此Class对象对应类的带指定形参的public构造器
  • Constructor<?>[] getConstructors():返回此Class对象对应类的所有public构造器
  • Constructor<T>[] getDeclaredConstructor(Class<?>...parameterTypes):返回此class对象对应类的带指定参数的构造器,与构造器的访问权限无关
  • Constructor<?>[] getDeclaredConstructors():返回此class对象对应类的所有构造器,与构造器的访问权限无关
获取类成员方法
  • Method getMethod(String name,Class<?>...parameterTypes):返回此class对象对应类的带指定形参的public方法
  • Method[] getMethods():返回此class对象所表示的类的所有public方法
  • Method getDeclaredMethod(string name,Class<?>...parameterTypes):返回此class对象对应类的带指定形参的方法,与方法访问权限无关
  • Method[] getDeclaredMethods():返回此class对象对应类的全部方法,与方法的访问权限无关
获取类成员变量
  • Field getField(String name):返回此class对象对应类的指定名称的public成员变量
  • Field[] getFields():返回此class对象对应类的所有public成员变量
  • Field getDeclaredField(String name):返回此class对象对应类的指定名称的成员变量,与成员变量访问权限无关
  • Field[] getDeclaredFields():返回此class对象对应类的全部成员变量,与成员变量的访问权限无关
获取类注解
  • <A extends Annotation>A getAnnotation(Class<A>annotationClass):尝试获取该class对象对应类上村子的指定类型的Annotation,如果该类型注解不存在,则返回null
  • <A extends Annotation>A getDeclaredAnnotation(Class<A>annotationClass):这是Java 8中新增的,该方法获取直接修饰该class对象对应类的指定类型的Annotation,如果不存在,则返回null
  • Annotation[] getAnnotations():返回修饰该class对象对应类上存在的所有Annotation
  • Annotation[] getDeclaredAnnotations():返回修饰该Class对象对应类上存在的所有Annotation
  • <A extends Annotation>A[] getAnnotationByType(Class<A>annotationClass):该方法的功能与前面介绍的getAnnotation()方法基本相似,但由于Java8增加了重复注解功能,因此需要使用该方法获取修饰该类的指定类型的多个Annotation
  • <A extends Annotation>A[] getDeclaredAnnotationByType(Class<A>annotationClass):该方法发功能与前面介绍的getDeclaredAnnotations()方法相似,也是因为Java8的重复注解的功能,需要使用该方法获取直接修饰该类的指定类型的多个Annotation
获取该类内部类
  • Class<?>[] getDeclaredClasses():返回该class队形对应类里包含的全部内部类
获取该类对象所在的外部类
  • Class<?> getDeclaringClass():返回该Class对象对应类所在的外部类
获取该类对象对应类所实现的接口
  • Class<?>[] getInterfaces():返回该Class对象对应类所实现的全部接口
获取该类对象对应类所继承的父类
  • Class<? super T> getSuperclass():返回该Class对象对应类的超类的Class对象
获取该类对象对应类的修饰符、所在包、类名等基本信息
  • int getModifiers():返回此类或接口的所有修饰符,修饰符由public、protected、private、final、static、abstract等对应的常量组成,返回的整数应使用Modifier工具类的方法来解码,才可以获取真是的修饰符
  • Package getPackage():获取该类的包
  • String getName():以字符串形式返回此CLass对象所表示的类的简称
判断该类是否为接口、枚举、注解类型
  • boolean isAnnotation():返回此class对象是否表示一个注解类型
  • boolean isAnnotationPresent(Class<? extends Annotation>annotationClass):判断此Class对象是否使用类Annotation修饰
  • boolean isAnonymousClass():返回此class对象是否是一个匿名类
  • boolean isArray():返回此class对象是否表示一个数组类
  • boolean isEnum():返回此class对象是否表示一个枚举
  • boolean isInterface():返回此class对象是否表示一个接口
  • boolean isInstance(Object obj):判断obj是否是此class对象的实例,该方法可以完全代替instanceof操作符
public interface Colorable {
	 public void value();
}
public class ClassInfo {
	
	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		Class<Colorable> cls=Colorable.class;
		System.out.println(cls.getMethod("value"));
		System.out.println(cls.isAnnotation());
		System.out.println(cls.isInterface());
	}

}

结果

public abstract void com.em.Colorable.value()
false
true

Java8中新增的方法参数反射

  • int getParameterCount():获取该构造器或方法的形参个数
  • Parameter[] getParameters():获取该构造器或方法的所有形参
  • getModifiers():获取修饰该形参的修饰符
  • String getName():获取形参名
  • Type getParameterizedType():获取带泛型的形参类型
  • Class<?>getType():获取形参类型
  • boolean isNamePresent():该方法返回该类的class文件中是否包含了方法的形参名信息
  • boolean isVarArgs():该方法用于判断该参数是否为个数可变的形参
public class Test {
	public void getInfo(String str,List<String>list){
		System.out.println("成功");
	}
}
public class ClassInfo {
	
	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		Class<Test> cls=Test.class;
		Method med=cls.getMethod("getInfo", String.class,List.class);
		System.out.println(med.getParameterCount());
		Parameter[] params=med.getParameters();
		System.out.println(params.length);
		for(Parameter par:params){
			System.out.println(par.getName());
			System.out.println(par.getType());
			System.out.println(par.getParameterizedType());
		}
	}

}

结果

2
2
arg0
class java.lang.String
class java.lang.String
arg1
interface java.util.List
java.util.List<java.lang.String>

反射生成对象

  • 使用Class对象的newInstance()方法创建Class对象的实例,该方法要求要有默认构造器(比较常用)
  • 先使用Class对象获取指定的Constructor对象,在调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例

反射调用方法

  • Object invoke(Object obj,Object...args):该方法中的obj是执行该方法的主调,后面的args是执行该方法时传入该方法的实参
public class Test {
	
	public Test(String str) {
		System.out.println(str);
	}
	public void getInfo(String str){
		System.out.println(str);
	}
}
public class ClassInfo {
	
	public static void main(String[] args) throws Exception {
		Class<Test> cls=Test.class;
		Constructor<Test>construct=cls.getConstructor(String.class);
		Test test=construct.newInstance("初始化");
		Method med=cls.getMethod("getInfo", String.class);
		med.invoke(test, "调用方法成功");
	}

}

结果

初始化
调用方法成功

接下来看官仔细看下面的栗子

public class Test {
	
	public Test(String str) {
		System.out.println(str);
	}
	//私有方法
	private void getInfo(String str){
		System.out.println(str);
	}
}
public class ClassInfo {
	
	public static void main(String[] args) throws Exception {
		Class<Test> cls=Test.class;
		Constructor<Test>construct=cls.getConstructor(String.class);
		Test test=construct.newInstance("初始化");
      //为啥使用这个方法呢?
		Method med=cls.getDeclaredMethod("getInfo", String.class);
      //为啥使用这个方法呢?
		med.setAccessible(true);
		med.invoke(test, "调用方法成功");
	}

}

结果

初始化
调用方法成功

setAccessible(boolean flag):将值设为true,指示该Method在使用是应该取消Java语言的访问权限检查

访问成员变量值

  • getXxx(Object obj):获取obj对象的该成员变量的值。此处的Xxx对应8种基本类型,如果该成员变量的类型是引用类型的,则去掉Xxx部分
  • setXxx(Object obj,Xxx val):将obj对象的该成员变量设置为val值。此处的Xxx对应8中基本类型,如果该成员变量的类型是引用类型,则取消set后面的Xxx

以上两个方法可以方法所有的成员变量,包括private的私有成员变量

public class Test {
	private int num;
	
	public Test(String str) {
		System.out.println(str);
	}
	private void getInfo(String str){
		System.out.println(str);
	}
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	
}
public class ClassInfo {
	
	public static void main(String[] args) throws Exception {
		Class<Test> cls=Test.class;
		Constructor<Test>construct=cls.getConstructor(String.class);
		Test test=construct.newInstance("初始化");
		Method med=cls.getDeclaredMethod("getInfo", String.class);
		med.setAccessible(true);
		med.invoke(test, "调用方法成功");
		Field fld=cls.getDeclaredField("num");
		fld.setAccessible(true);
		fld.setInt(test, 12);
		System.out.println(fld.getInt(test));
	}

}

结果

初始化
调用方法成功
12

操作数组

java.lang.reflect包下有一个Array类,其可以动态创建数组

static Object newInstance(Class<?>componentType,int...length):创建一个具有指定的元素类型、指定维度的新数组

static xxx getXxx(Object array,int index):返回array数组中第index个元素。其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变为get()

static void setXxx(Object array,int index,xxx val):将array数组中低index 个元素的值设为val,其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变为set()

public class ArrayInfo {

	public static void main(String[] args) {
		Object arrays=Array.newInstance(String.class, 3);
		Array.set(arrays, 0, "第一个");
		Array.set(arrays, 1, "第二个");
		Array.set(arrays, 2, "第三个");
		System.out.println(Array.get(arrays, 2));
	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Vertx-Phoenix实践

    Vertx是一个高效的异步框架,支持Java、Scala、JavaScript、Kotlin等多种语言。在非性能调优的场景下,TPS可以高达2-3万,同时,支持...

    迹_Jason
  • Feign 如何支持进行文件上传

    最近,别的项目组提出需要SDK,就利用Feign做了一个,在此期间发现上传文件是一个坑,正常的实现是无法支持文件上传,需要进行对资源有一个Convert。为了避...

    迹_Jason
  • SpringAOP面向切面详解(带实例)

    通知定义了切面是什么,以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。

    迹_Jason
  • Java中的反射总结

    刚开始学习Java的时候真的很难理解反射到底是个什么东西 一些书籍,哪怕是很经典的书籍都解释的让人感觉懵懵的,或许的确是我太笨 况且,网上说在将来学习框架的时...

    顶级程序员
  • spring boot整合hessian

    首先添加hessian依赖 <dependency> <groupId>com.caucho</groupId> <artifactId>he...

    春哥大魔王
  • -Android -线程池 批量上传图片 -附php接收代码

    (出处:https://cloud.tencent.com/developer/user/1148436/activities) 目录:   1,前序   2,...

    林冠宏-指尖下的幽灵
  • [ASP.NET Core 3框架揭秘]服务承载系统[5]: 承载服务启动流程[上篇]

    Host类型是对IHost接口的默认实现,它仅仅是定义在NuGet包“Microsoft.Extensions.Hosting”中的一个内部类型,由于我们在本节...

    蒋金楠
  • 十分钟搞懂Java效率工具Lombok使用与原理

    Lombok是一款好用顺手的工具,就像Google Guava一样,在此予以强烈推荐,每一个Java工程师都应该使用它。Lombok是一种Java™实用工具,可...

    java思维导图
  • 怎么获取泛型T.class类?

    如上代码,要调用getA()方法,必须传入一个Class类,使用泛型怎么传递这个Class类呢?

    hbbliyong
  • bash 的变量和参数

    对一个编程脚本来说,最最基础的当然是变量。 对大多数开发者来说,变量也是最不值得的大说特说的。 但 bash 里的变量有一些特别的地方值得说说,谨防跌坑。 基本...

    IMWeb前端团队

扫码关注云+社区

领取腾讯云代金券