欢迎关注专栏《Java 架构筑基》——专注于 Java 技术的研究与分享!
- Java 架构筑基——专注于 Java 技术的研究与分享!
- 后续文章将首发此专栏!
- 欢迎各位 Java 工程师朋友投稿和关注
反射机制
Java 反射机制 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种 动态 获取的信息以及动态调用对象的方法的功能称为 java 语言的 反射机制。
获取 Class 类对象的三种方式
万物皆对象,包括 类 也有对象,称为 类对象。要想获取类的信息首先要获取 类。
Class 类的与反射有关的重要方法:
获取 Class 类对象方式一:
// 通过类的全限定类名(包名+类名)获取类
Class clazz = Class.forName("类的全限定类名(包名+类名)");
获取 Class 类对象方式二:
// 直接获取类
Class clazz = Object.class;
获取 Class 类对象方式三:
// 通过实例对象获取其类
Class clazz = object.getClass();
- 根据类加载机制,运行时一个类仅有一个类对象。
java.lang.reflect 包中的类
万物皆对象,不仅 类 有类对象,类的方法、字段,甚至修饰符都可以有 对象。
java.lang.reflect 包提供了用于通过反射获取 _类信息 (方法、属性、修饰符、参数等)的类、接口、异常。下面主重介绍一下有关反射的_类:
反射的实际操作
案例 1:
现在有个需求,想获取一个 用户实体 中所有的字段。
package com.foovv.example;
/**
* 用户实体类
*
* @author 代码风水师
* @version jdk1.8
*/
public class User {
/** 用户id */
private String id;
/** 用户名称 */
private String userName;
/** 用户性别 */
private String userGender;
/** 用户年龄 */
private Integer userAge;
/** 用户邮箱 */
private String email;
/* getter & setter 方法略 */
}
package com.foovv.example;
/** 要反射类中的字段,就要引入reflect.Field类 */
import java.lang.reflect.Field;
/**
* 反射字段的demo
*
* @author 代码风水师
* @version jdk1.8
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 1、要想获取类的字段,就先要获取该类。下面通过全限定类名来获取的。
Class user = Class.forName("com.foovv.example.User");
// 2、上面已得到User类的类对象,那么下面就获取其所有字段的类对象数组
Field[] fields = user.getDeclaredFields();
// 3、遍历字段的数组集合,一个一个字段去处理
for (Field field : fields) {
// 此处的是打印User类对象中的字段名称
System.out.println(field.getName());
}
}
}
输出结果:
id
userName
userGender
userAge
email
Process finished with exit code 0
案例 2:
在很多框架中,常使用注解来标记类、方法、字段的特征。比如持久化框架常用来反射生成 SQL,下面就动手实战一下:
实体:
package com.foovv.example;
/** 描述略 */
public class User {
private String id;
private String userName;
private String userGender;
private Integer userAge;
private String email;
/* getter & setter 方法略 */
}
通过反射生成 SQL 语句:
SELECT id, user_name, user_gender, user_age,email FROM user;
1、定义两个注解类,一个注解类 Table 标注实体对应的表名,另一个注解类 Column 标注对应的数据表的列名:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
String value();
}
2、对实体类及其字段使用注解标注:
@Table("user")
public class User {
@Column("id")
private String id;
@Column("user_name")
private String userName;
@Column("user_gender")
private String userGender;
@Column("user_age")
private Integer userAge;
@Column("email")
private String email;
/* getter & setter 方法略 */
}
3、上面做了处理,下面开始对这个实体类做反射、获取注解:
public class ReflectSql {
public static void main(String[] args) throws ClassNotFoundException {
// 拼接的SQL
StringBuilder sql = new StringBuilder();
// 1、要想获取类的字段,就先要获取该类。下面通过全限定类名来获取的。
Class user = Class.forName("com.foovv.example.User");
// 2、获取实体类上的Table注解,然后通过value()获取对应的表名
// 当前你也可以使用getDeclaredAnnotations()获取注解数组,然后遍历
Table table = (Table) user.getDeclaredAnnotation(Table.class);
String tableName = table.value();
// 3、获取字段上的注解,然后获取通过value()获取对应的数据表的列名
Field[] fields = user.getDeclaredFields();
sql.append("SELECT ");
// 遍历每个字段
for (int i = 0; i < fields.length; i++) {
// 获取字段上Column注解
Column column = fields[i].getAnnotation(Column.class);
// 进而获取value()值,既对应指定的数据表列名
// 拼接SQL
sql.append(column.value());
if (i < fields.length - 1) {
sql.append(", ");
}
}
sql.append(" FROM ");
sql.append(tableName);
sql.append(";");
System.out.println(sql);
}
}
运行结果:
SELECT id, user_name, user_gender, user_age, email FROM user;
Process finished with exit code 0