Java 反射(二)运行时获取类的信息
一、获得类的运行时结构
1. 获得类的名字
getName()
:包名+类名
getSimpleName()
:类名
Class c1 = Class.forName("reflection.User");
// 获得类的名字
System.out.println(c1.getName()); //包名+类名
System.out.println(c1.getSimpleName()); //获得类名
====================运行结果====================
reflection.User
User
2. 获得类的属性
获取属性列表
getFields()
:只能找到public属性
getDeclaredFields()
:可以找到所有属性
User
类
class User{
private String name;
private int id;
private int age;
// getter、setter、构造函数
}
示例:
// 获得类的属性
Field[] fields =c1.getFields(); // 只能找到public属性
Arrays.stream(fields).forEach(System.out::println);
System.out.println("==============");
fields = c1.getDeclaredFields(); // 可以找到所有属性
Arrays.stream(fields).forEach(System.out::println);
=====================运行结果=====================
==============
private java.lang.String reflection.User.name
private int reflection.User.id
private int reflection.User.age
获取指定属性
getField(String fieldName)
:public属性
getDeclaredField(String fieldName)
:所有属性
//获得指定属性的值
Field name = c1.getDeclaredField("name");
=====================打印结果=====================
private java.lang.String reflection.User.name
3. 获取类的方法
获得类的方法列表
getMethods()
:获得本类和父类的public
方法
getDeclaredMethods()
:只获得本类的所有方法(包括private
的方法)
//获得本类和父类的public方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("==============");
//只获得本类的所有方法
methods = c1.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
=====================打印结果=====================
public java.lang.String reflection.User.getName()
public java.lang.String reflection.User.toString()
public void reflection.User.setName(java.lang.String)
public int reflection.User.getId()
public void reflection.User.setAge(int)
public int reflection.User.getAge()
public void reflection.User.setId(int)
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
==============
public java.lang.String reflection.User.getName()
public java.lang.String reflection.User.toString()
public void reflection.User.setName(java.lang.String)
public int reflection.User.getId()
public void reflection.User.setAge(int)
public int reflection.User.getAge()
public void reflection.User.setId(int)
可以发现,使用getMethods()
还可以获得父类Object
的public方法
获得指定方法
getMethod(String methodName, Class<?> ...parameterTypes)
:获得本类和父类指定的public
方法
getDeclaredMethods(String methodName, Class<?> ...parameterTypes)
:只获得本类指定的方法(包括private
的方法)
其中methodName
是方法名,...parameterTypes
是参数列表的参数类型的Class对象,因为java中存在函数重载,可以存在多个名字相同的方法,通过参数列表不同进行区分。
// 获得指定方法
Method getName = c1.getMethod("getName", null);
Method setAge = c1.getMethod("setAge", int.class);
System.out.println(getName);
System.out.println(setAge);
=====================打印结果=====================
public java.lang.String reflection.User.getName()
public void reflection.User.setAge(int)
4. 获得的构造器
获得构造器列表
getConstructors()
:获取public
getDeclaredConstructors()
:获取所有
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println("#" + constructor);
}
public reflection.User()
public reflection.User(java.lang.String,int,int)
#public reflection.User()
#public reflection.User(java.lang.String,int,int)
获得指定构造器
getConstructor(Class<?> ...parameterTypes)
getDeclaredConstructor(Class<?> ...parameterTypes)
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("指定: " + declaredConstructor);
指定: public reflection.User(java.lang.String,int,int)
二、通过反射动态创建对象
1. 使用newInstance()
要求
- 类必须有一个无参数的构造器
- 类的构造器的访问权限需要足够
// 获得Class对象
Class<?> c1 = Class.forName("reflection.User");
// 创造一个对象
User user = (User) c1.newInstance();// 本质是使用无参构造器
2.先获取构造器再创建对象
// 通过构造器创造对象
Constructor<?> constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) constructor.newInstance("秦疆", 1, 18);
三、通过反射调用对象的方法
- 获取
Method
对象method
method.invoke(Object obj, Object ...args)
,其中obj
为方法调用者,args
为填入参数
// 通过反射调用普通方法
User user3 = (User) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
// (对象,方法的参数)
setName.invoke(user3,"狂神");
四、通过反射操作对象的属性
- 获取
Field
对象field
field.set(Object obj, Object value)
,其中obj
为方法调用者,value
为填入的值
tips: 若操作的是private属性,在set前需要设置访问权限为true
// 通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
// 不能直接操作私有属性,需要打开访问权限
name.setAccessible(true);
name.set(user4,"狂神2");
setAccessible(true)
还可以提高代码执行效率。
五、通过反射获取泛型信息
method.getParameterTypes()
,其中method
是Method
类型对象,返回类型为Class<?>[]
1. 获取方法参数类型
public class Test11 {
public void test01(Map<String, User> map, List<User> list){
System.out.println("test01");
}
public Map<String, User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
// 获取泛型参数类型
Method method = Test11.class.getMethod("test01", Map.class, List.class);
Class<?>[] parameterTypes = method.getParameterTypes();
Arrays.stream(parameterTypes).forEach(System.out::println);
}
}
打印结果:
interface java.util.Map
interface java.util.List
2. 获取方法带泛型的参数类型
method.getGenericParameterTypes()
,其中method
是Method
类型对象,返回类型为Type[]
Type[] genericParameterTypes = method.getGenericParameterTypes();
Arrays.stream(genericParameterTypes).forEach(System.out::println);
打印结果:
java.util.Map<java.lang.String, reflection.User>
java.util.List<reflection.User>
3. 从参数类型(ParameterizedType)中获取泛型信息
- 先强制转换为
ParameterizedType
(之前先判断类型) - 调用
getActualTypeArguments()
方法,返回类型为
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("#"+genericParameterType);
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
运行结果:
#java.util.Map<java.lang.String, reflection.User>
class java.lang.String
class reflection.User
#java.util.List<reflection.User>
class reflection.User
获取返回值类型中的泛型也是同理,这里不再赘述。
六、通过反射获取注解信息
我们尝试编写一个模拟业务的pojo类Student2
class Student2{
private int id;
private int age;
private String name;
// getter、setter、toString
}
先编写两个注解,@Tablekuang
和@Fieldkuang
@Tablekuang
用于修饰一个类,用于说明这个类和数据库中的哪个表相对应@Fieldkuang
用于说明和数据库的哪个字段对应,类型是什么,长度是多少
// 类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tablekuang{
String value();
}
// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldkuang{
String columnName();
String type();
int length();
}
然后我们使用注解在Student2类上进行标注:
@Tablekuang("db_student")
class Student2{
@Fieldkuang(columnName = "db_id", type = "int", length = 10)
private int id;
@Fieldkuang(columnName = "db_age", type = "int", length = 10)
private int age;
@Fieldkuang(columnName = "db_name", type = "varchar", length = 3)
private String name;
// getter、setter、toString
}
然后我们进行注解信息的读取。
获取注解
1. 获取类上的注解
Class
成员方法
getAnnotations()
:获得所有注解,返回值为Annotation[]
getAnnotation(Class annotationClass)
:获得指定注解,返回值为Annotation
Class<?> c1 = Class.forName("reflection.Student2");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
打印结果:
@reflection.Tablekuang(value=db_student)
2. 获取属性上的注解
Field
成员方法
getAnnotations()
:获得所有注解,返回值为Annotation[]
getAnnotation(Class annotationClass)
:获得指定注解,返回值为Annotation
获取注解中携带的属性值
注解对象.属性名()
// 获得注解的value值
Tablekuang tablekuang = c1.getAnnotation(Tablekuang.class);
System.out.println(tablekuang.value());
// 获得某字段上的注解
Field f = c1.getDeclaredField("id");
Fieldkuang annotation = f.getAnnotation(Fieldkuang.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
运行结果:
db_student
db_id
int
10
Java 反射(二)运行时获取类的信息的更多相关文章
- Java——反射:运行时的类信息
RTTI的使用 如果不知道某个对象的确切类型,RTTI会告诉我们,但是有一个限制:这个类型在编译时必须已知,这样才能使用RTTI识别它,并利用这些信息做一些有用的事情. 2.什么情况下需要反射 假设 ...
- Java反射《一》获取类
package com.study.reflect; /** * 反射:java程序运行中,可以获得该类的所有属性和方法,对于任意一个对象可以 调用它的属性和方法,这种动态获得属性和方法,调用对象属性 ...
- swift3.0 运行时获取类的属性
//定义Person类 class Person: NSObject { var name: String? //注意这里基本数据类型我定义的是必选属性 var age: Int = override ...
- Java如何在运行时识别类型信息?
在日常的学习工作当中,有一些知识是我们在读书的时候就能够习得:但有一些知识不是的,需要在实践的时候才能得到真知——这或许就是王阳明提倡的“知行合一”. 在Java中,并不是所有的类型信息都能在编译阶段 ...
- [Java反射基础二]获取类的信息
本文接上文“Class类的使用”,以编写一个用来获取类的信息(成员函数.成员变量.构造函数)的工具类来讲解"反射之获取类的信息" 1.获取成员函数信息 /** * 获取成员函数信息 ...
- 背水一战 Windows 10 (76) - 控件(控件基类): Control - 基础知识, 焦点相关, 运行时获取 ControlTemplate 和 DataTemplate 中的元素
[源码下载] 背水一战 Windows 10 (76) - 控件(控件基类): Control - 基础知识, 焦点相关, 运行时获取 ControlTemplate 和 DataTemplate 中 ...
- 反射01 Class类的使用、动态加载类、类类型说明、获取类的信息
0 Java反射机制 反射(Reflection)是 Java 的高级特性之一,是框架实现的基础. 0.1 定义 Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对 ...
- iOS开发——运行时OC篇&使用运行时获取系统的属性:使用自己的手势修改系统自带的手势
使用运行时获取系统的属性:使用自己的手势修改系统自带的手势 有的时候我需要实现一个功能,但是没有想到很好的方法或者想到了方法只是那个方法实现起来太麻烦,一或者确实为了装逼,我们就会想到iOS开发中最牛 ...
- 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】
方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; priva ...
随机推荐
- VsCode中添加tasks.json
选中项目文件夹,按ctrl+shift+p,输入tasks 选择之后,继续选择 然后选择 选中就可以了
- 『心善渊』Selenium3.0基础 — 9、使用Seleniun中的By类定位元素
目录 1.使用By定位的前提 2.By定位的方法 3.By定位的使用 4.复数形式的示例 我们还可以通过Seleniun测试框架中的By类,来实现页面中的元素定位. 1.使用By定位的前提 需要导入B ...
- 手摸手,带你用Beego撸商城系列一(基础篇)
完整项目地址: go-shop-b2c 系列文章: 手摸手,带你用 Beego撸商城 系列一(基础篇) 手摸手,带你用 Beego撸商城 系列二(登录篇) 手摸手,带你用 Beego撸商城 系列三(系 ...
- flutter中ListView的详细讲解
1.ListView的简单介绍 ListView是最常用的可以滚动组件之一, 它可以沿一个方向进行线性排列所有的子组件. 下面是ListView的属性值介绍: scrollDirection:列表的滚 ...
- 数据备份[APIO/CTSC 2007]题解
题目描述 你在一家IT公司为大型写字楼或办公楼的计算机数据做备份. 然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣. 已知办公楼 ...
- java实现遍历文件目录,根据文件最后的修改时间排序,并将文件全路径存入List集合
package com.ultra.aliyun.control.main; import java.io.File; import java.util.ArrayList; import java. ...
- linux学习之路第七天(压缩和解压类指令详解)
压缩和解压类 1.gzip/gunzip 指令 gzip 指令用于压缩文件, gunzip用于解压的 基本语法 gzip 文件 (功能描述:压缩文件,指令将文件压缩成*.gz文件) gunzip 文件 ...
- ROS2学习之旅(12)——创建工作空间
workspace(工作空间)是包含ROS2 packages(包)的文件夹.在使用ROS 2之前,有必要在终端中source一下ROS 2的安装工作区,这样就可以在该终端中使用ROS 2的软件包. ...
- STM32笔记一
1.脉冲宽度调制是(PWM):用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量.通信到功率控制与变换的许多领域中.一般用于直流电机调速. 2.外部中断:外部中断是单片机实 ...
- java基础---集合(2)
一. Set 集合 java.util.Set集合是Collection集合的子集合,与List集合平级.该集合中元素没有先后放入次序,且不允许重复. 存储的数据在底层数组中并非按照数组索引的顺序添加 ...