java反射知识
反射
概述
定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
用途
在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。
反射机制的相关类
与Java反射相关的类如下:
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Class类
Class代表类的实体,在运行的Java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。
- 获得类相关的方法
方法 | 用途 |
---|---|
asSubclass(Class clazz) | 把传递的类的对象转换成代表其子类的对象 |
Cast | 把对象转换成代表类或是接口的对象 |
getClassLoader() | 获得类的加载器 |
getClasses() | 返回一个数组,数组中包含该类中所有公共类和接口类的对象 |
getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 |
forName(String className) | 根据类名返回类的对象 |
getName() | 获得类的完整路径名字 |
newInstance() | 创建类的实例 |
getPackage() | 获得类的包 |
getSimpleName() | 获得类的名字 |
getSuperclass() | 获得当前类继承的父类的名字 |
getInterfaces() | 获得当前类实现的类或是接口 |
- 获得类中属性相关的方法
方法 | 用途 |
---|---|
getField(String name) | 获得某个公有的属性对象 |
getFields() | 获得所有公有的属性对象 |
getDeclaredField(String name) | 获得某个属性对象 |
getDeclaredFields() | 获得所有属性对象 |
- 获得类中注解相关的方法
方法 | 用途 |
---|---|
getAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的公有注解对象 |
getAnnotations() | 返回该类所有的公有注解对象 |
getDeclaredAnnotation(Class 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类
Field代表类的成员变量(成员变量也称为类的属性)。
方法 | 用途 |
---|---|
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Object obj, Object value) | 设置obj中对应属性值 |
Method类
Method代表类的方法。
方法 | 用途 |
---|---|
invoke(Object obj, Object... args) | 传递object对象及参数调用该对象对应的方法 |
Constructor类
Constructor代表类的构造方法。
方法 | 用途 |
---|---|
newInstance(Object... initargs) | 根据传递的参数创建类的对象 |
1.获取Class对象的几种方式
/**
* 获取Class对象的三种方式
* 1 Object ——> getClass();
* 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
* 3 通过Class类的静态方法:forName(String className)(常用)
*
*/
Student对象
package com.ooyhao.reflection.bean;
import java.io.Serializable;
public class Student implements Serializable {
public Integer id;
private String name;
private String sex;
private Integer age;
public Student() {}
public Student(String name){
this.name = name;
}
public Student(String name, Integer age){
this.name = name;
this.age = age;
}
public Student(Integer id, String name, String sex, Integer age) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
}
protected Student(Integer id,String name){
this.name = name;
}
private Student(Integer id){
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
private String printInfo(String message){
System.out.println("仅仅是为了演示:"+message);
this.name = message;
return message;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}
获取Class对象的几种方法
@Test
public void getClassFun() throws ClassNotFoundException {
/**
* 方式一:利用对象的getClass()方法来获取Class对象
* 说明:既然已经有了对象,在通过对象获取Class意义不太(不常用)
* */
Student student = new Student();
Class<?> aClass = student.getClass();
System.out.println(aClass);
/**
* 方式二:利用类的class属性来获取Class对象
* 说明:需要导入完整的包名,依赖性比较强,如果不导入包,则会报编译异常(不常用)
* */
Class<Student> studentClass = Student.class;
System.out.println(studentClass);
/**
* 方式三:利用Class类的forName()方法,通过完整的包名+类名获取Class对象
* 说明:不用导入包名、类名,也不用创建对象(推荐)
* 一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。
* */
Class<?> forName = Class.forName("com.ooyhao.reflection.bean.Student");
System.out.println(forName);
}
输出结果:
class com.ooyhao.reflection.bean.Student
class com.ooyhao.reflection.bean.Student
class com.ooyhao.reflection.bean.Student
2.获取构造方法并使用
1.获取构造方法:
1).批量的方法:
public Constructor[] getConstructors():所有”公有的”构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
2).获取单个的方法,并调用:
public Constructor getConstructor(Class… parameterTypes):获取单个的”公有的”构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取”某个构造方法”可以是私有的,或受保护、默认、公有;
调用构造方法:
Constructor–>newInstance(Object… initargs)
2、newInstance是 Constructor类的方法(管理构造函数的类)
api的解释为:
newInstance(Object… initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用
案例演示:
@Test
public void testConstructor() throws Exception{
Class<?> aClass = Class.forName("com.ooyhao.reflection.bean.Student");
/*获取所有public修饰的构造器*/
// Constructor<?>[] constructors = aClass.getConstructors();
/*获取所有构造器(private,protected,default,public)*/
Constructor<?>[] constructors = aClass.getDeclaredConstructors();
for (Constructor constructor : constructors){
System.out.println(constructor);
Class[] parameterTypes = constructor.getParameterTypes();
for (Class c : parameterTypes){
System.out.println(c);
}
System.out.println("-----------------");
}
/*获取共有的,无参的构造器*/
Constructor<?> constructor = aClass.getConstructor(null);
//public com.ooyhao.reflection.bean.Student()
System.out.println(constructor);
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Integer.class);
//private com.ooyhao.reflection.bean.Student(java.lang.Integer)
System.out.println(declaredConstructor);
declaredConstructor.setAccessible(true);//暴力访问(忽略掉访问修饰符)
Object o = declaredConstructor.newInstance(12);
Student student = (Student) o;
//student:Student{id=12, name='null', sex='null', age=null}
System.out.println("student:"+student);
}
运行结果:
private com.ooyhao.reflection.bean.Student(java.lang.Integer)
class java.lang.Integer
-----------------
protected com.ooyhao.reflection.bean.Student(java.lang.Integer,java.lang.String)
class java.lang.Integer
class java.lang.String
-----------------
public com.ooyhao.reflection.bean.Student(java.lang.Integer,java.lang.String,java.lang.String,java.lang.Integer)
class java.lang.Integer
class java.lang.String
class java.lang.String
class java.lang.Integer
-----------------
public com.ooyhao.reflection.bean.Student()
-----------------
public com.ooyhao.reflection.bean.Student(java.lang.String)
class java.lang.String
-----------------
public com.ooyhao.reflection.bean.Student(java.lang.String,java.lang.Integer)
class java.lang.String
class java.lang.Integer
-----------------
public com.ooyhao.reflection.bean.Student()
private com.ooyhao.reflection.bean.Student(java.lang.Integer)
student:Student{id=12, name='null', sex='null', age=null}
3.获取成员变量并调用
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的”公有字段”
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个”公有的”字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field –> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*/
案例演示:
@Test
public void testField() throws Exception{
Class<?> aClass = Class.forName("com.ooyhao.reflection.bean.Student");
System.out.println("----------获取public属性----------");
Field[] fields = aClass.getFields();
for (Field field : fields){
System.out.println(field);
}
System.out.println("----------获取public,default,protected,private属性----------");
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields){
System.out.println(field);
}
/*通过反射设置属性的值*/
System.out.println("------通过反射设置属性的值------");
Object o = aClass.newInstance();
Field name = aClass.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"欧阳浩");
Student student = (Student) o;
System.out.println(student);
}
运行结果:
----------获取public属性----------
public java.lang.Integer com.ooyhao.reflection.bean.Student.id
----------获取public,default,protected,private属性----------
public java.lang.Integer com.ooyhao.reflection.bean.Student.id
private java.lang.String com.ooyhao.reflection.bean.Student.name
private java.lang.String com.ooyhao.reflection.bean.Student.sex
private java.lang.Integer com.ooyhao.reflection.bean.Student.age
------通过反射设置属性的值------
Student{id=null, name='欧阳浩', sex='null', age=null}
4.获取成员方法并调用
/*
* 获取成员方法并调用:
*
* 1.批量的:
* public Method[] getMethods():获取所有”公有方法”;(包含了父类的方法也包含Object类)
* public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
* 2.获取单个的:
* public Method getMethod(String name,Class<?>… parameterTypes):
* 参数:
* name : 方法名;
* Class … : 形参的Class类型对象
* public Method getDeclaredMethod(String name,Class<?>… parameterTypes)
*
* 调用方法:
* Method –> public Object invoke(Object obj,Object… args):
* 参数说明:
* obj : 要调用方法的对象;
* args:调用方式时所传递的实参;
*/
案例演示:
@Test
public void testMethod() throws Exception{
Class<?> aClass = Class.forName("com.ooyhao.reflection.bean.Student");
System.out.println("----------获取public成员方法----------");
Method[] methods = aClass.getMethods();
for (Method method : methods){
System.out.println(method);
}
Method[] declaredMethods = aClass.getDeclaredMethods();
System.out.println("----------获取public,default,protected,private成员方法----------");
for (Method method : declaredMethods){
System.out.println(method);
}
/*获取setName方法*/
System.out.println("----------获取printInfo方法----------");
Method printInfo = aClass.getDeclaredMethod("printInfo", String.class);
System.out.println(printInfo);
// Object o1 = aClass.newInstance();
printInfo.setAccessible(true);//解除私有限定
Object o = aClass.getConstructor().newInstance();
Object ouYang = printInfo.invoke(o, "ouYangHao");
//返回的是对象Student对象。Student{id=null, name='ouYangHao', sex='null', age=null}
System.out.println("对象:"+o);
//返回的是方法的返回值。ouYangHao
System.out.println("方法返回值:"+ouYang);
}
运行结果:
----------获取public成员方法----------
public java.lang.String com.ooyhao.reflection.bean.Student.toString()
public java.lang.String com.ooyhao.reflection.bean.Student.getName()
public java.lang.Integer com.ooyhao.reflection.bean.Student.getId()
public void com.ooyhao.reflection.bean.Student.setName(java.lang.String)
public java.lang.String com.ooyhao.reflection.bean.Student.getSex()
public void com.ooyhao.reflection.bean.Student.setSex(java.lang.String)
public java.lang.Integer com.ooyhao.reflection.bean.Student.getAge()
public void com.ooyhao.reflection.bean.Student.setAge(java.lang.Integer)
public void com.ooyhao.reflection.bean.Student.setId(java.lang.Integer)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) 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,default,protected,private成员方法----------
public java.lang.String com.ooyhao.reflection.bean.Student.toString()
public java.lang.String com.ooyhao.reflection.bean.Student.getName()
public java.lang.Integer com.ooyhao.reflection.bean.Student.getId()
public void com.ooyhao.reflection.bean.Student.setName(java.lang.String)
private java.lang.String com.ooyhao.reflection.bean.Student.printInfo(java.lang.String)
public java.lang.String com.ooyhao.reflection.bean.Student.getSex()
public void com.ooyhao.reflection.bean.Student.setSex(java.lang.String)
public java.lang.Integer com.ooyhao.reflection.bean.Student.getAge()
public void com.ooyhao.reflection.bean.Student.setAge(java.lang.Integer)
public void com.ooyhao.reflection.bean.Student.setId(java.lang.Integer)
----------获取printInfo方法----------
private java.lang.String com.ooyhao.reflection.bean.Student.printInfo(java.lang.String)
仅仅是为了演示:ouYangHao
对象:Student{id=null, name='ouYangHao', sex='null', age=null}
方法返回值:ouYangHao
5.反射调用main方法
@Test
public void testMain() throws Exception {
//1、获取Student对象的字节码
Class<?> aClass = Class.forName("com.ooyhao.reflection.test.MainFun");
//2、获取main方法
Method main = aClass.getMethod("main", String[].class);
System.out.println(main);
//3、调用main方法
main.invoke(null,(Object)new String[]{"a","b","c"});//方法一
String[] args = new String[]{"Java","SpringBoot","SpringCloud","Dubbo","Zookeeper"};
//第一个参数,对象类型,因为方法是static静态的,所以为null可以,
//第二个参数是String数组,这里要注意在jdk1.4时是数组,jdk1.5之后是可变参数
//这里拆的时候将 new String[]{"a","b","c"} 拆成3个对象。。。所以需要将它强转。
main.invoke(null,new Object[]{args});//方法二
}
运行结果:
public static void com.ooyhao.reflection.test.MainFun.main(java.lang.String[])
----------执行main方法----------
main方法参数:[a, b, c]
----------执行main方法----------
main方法参数:[Java, SpringBoot, SpringCloud, Dubbo, Zookeeper]
6.返回跳过泛型检查
@Test
public void testGenetic() throws Exception {
List<String> list = new ArrayList<String>();
list.add("Java");
Class<?> aClass = list.getClass();
Method add = aClass.getMethod("add", Object.class);
add.invoke(list,100);
for (Object o : list){
System.out.println(o);
}
}
运行结果:
Java
100
使用注解和反射实现 对象和表的映射
1.注解
1.@Entity
package com.ooyhao.jdbc.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
public String value();//tableName
}
2.@Column
package com.ooyhao.jdbc.annotation;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
public String value();//列名
}
3.@IsExist
package com.ooyhao.jdbc.annotation;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface IsExist {
public boolean value();//是否存在
}
2.User Bean
package com.ooyhao.jdbc.bean;
import com.ooyhao.jdbc.annotation.Column;
import com.ooyhao.jdbc.annotation.Entity;
import com.ooyhao.jdbc.annotation.IsExist;
import java.io.Serializable;
import java.util.Date;
@Entity("sys_user")
public class User implements Serializable {
@Column("id")
private Long id;
@Column("username")
private String username;
@Column("password")
private String password;
@Column("create_time")
private Date createTime;
@Column("create_user")
private String createUser;
@Column("modify_time")
private Date modifyTime;
@Column("modify_user")
@IsExist(true)
private String modifyUser;
public User() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getCreateUser() {
return createUser;
}
public void setCreateUser(String createUser) {
this.createUser = createUser;
}
public Date getModifyTime() {
return modifyTime;
}
public void setModifyTime(Date modifyTime) {
this.modifyTime = modifyTime;
}
public String getModifyUser() {
return modifyUser;
}
public void setModifyUser(String modifyUser) {
this.modifyUser = modifyUser;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", createTime=" + createTime +
", createUser='" + createUser + '\'' +
", modifyTime=" + modifyTime +
", modifyUser='" + modifyUser + '\'' +
'}';
}
}
3.DBHelper
package com.ooyhao.jdbc.helper;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class DbHelper {
public static final String URL = "jdbc:mysql://120.79.167.XXX:3306/GD?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&autoReconnect=true&useSSL=false";
public static final String USERNAME = "root";
public static final String PASSWORD = "XXXXXXXX";
public static final String DRIVER = "com.mysql.jdbc.Driver";
public static Connection getConnection(){
try{
Class.forName(DRIVER);
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return connection;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public static void close(Connection connection, Statement statement, ResultSet resultSet){
try{
if (connection != null){
connection.close();
}
if (statement != null){
statement.close();
}
if (resultSet != null){
resultSet.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
public static void close(Connection connection, Statement statement){
try{
if (connection == null){
connection.close();
}
if (statement != null){
statement.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
4.IJdbcDao
package com.ooyhao.jdbc.jdbc;
import com.ooyhao.jdbc.annotation.Column;
import com.ooyhao.jdbc.annotation.Entity;
import com.ooyhao.jdbc.annotation.IsExist;
import com.ooyhao.jdbc.helper.DbHelper;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class IJdbcDao {
public <T> List<T> selectDataToBean(Class<T> tClass) {
List<T> list = new ArrayList<>();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
String simpleName = tClass.getSimpleName();
String tableName = String.valueOf(simpleName.charAt(0)).toLowerCase() + simpleName.substring(1);
boolean annotationPresent = tClass.isAnnotationPresent(Entity.class);
if (annotationPresent){
Entity entity = tClass.getAnnotation(Entity.class);
tableName = entity.value();
}
String sql = " select * from "+tableName;
connection = DbHelper.getConnection();
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
Field[] fields = tClass.getDeclaredFields();
Map<String,Field> map = new HashMap<>();
for (Field field : fields){
String columnValue = null;
if (field.isAnnotationPresent(Column.class)){
Column column = field.getAnnotation(Column.class);
columnValue = column.value();
}
boolean isExistValue = true;
if (field.isAnnotationPresent(IsExist.class)){
IsExist isExist = field.getAnnotation(IsExist.class);
isExistValue = isExist.value();
}
if (isExistValue){
map.put(columnValue,field);
}
}
int colCount = resultSet.getMetaData().getColumnCount();
while (resultSet.next()){
T t = tClass.newInstance();
for (int i = 1; i <= colCount; i++) {
String columnLabel = resultSet.getMetaData().getColumnLabel(i);
Field field = map.get(columnLabel);
if (field != null){
field.setAccessible(true);
field.set(t,resultSet.getObject(i));
}
}
list.add(t);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
DbHelper.close(connection,preparedStatement,resultSet);
}
return list;
}
}
5.测试及结果
public class App {
public static void main(String[] args) {
IJdbcDao iJdbcDao = new IJdbcDao();
List<User> users = iJdbcDao.selectDataToBean(User.class);
for (User user : users){
System.out.println(user);
}
}
}
结果:
User{id=1, username='admin', password='1', createTime=2019-01-23 17:24:24.0, createUser='admin', modifyTime=2019-01-23 17:24:24.0, modifyUser='admin'}
User{id=2, username='jack', password='1', createTime=2019-01-23 17:24:28.0, createUser='admin', modifyTime=2019-01-23 17:24:24.0, modifyUser='admin'}
User{id=8, username='23', password='null', createTime=2019-01-25 10:51:57.0, createUser='admin', modifyTime=2019-01-25 10:51:57.0, modifyUser='admin'}
User{id=3, username='林黛玉', password='123456', createTime=2019-01-23 17:29:56.0, createUser='admin', modifyTime=2019-01-23 17:29:56.0, modifyUser='admin'}
User{id=4, username='贾宝玉', password='123456', createTime=2019-01-23 17:30:24.0, createUser='admin', modifyTime=2019-01-23 17:30:24.0, modifyUser='admin'}
User{id=6, username='ouYang', password='123456', createTime=2019-01-23 17:30:47.0, createUser='admin', modifyTime=2019-01-23 17:30:47.0, modifyUser='admin'}
反射机制
类是用来描述一组对象,反射机制是用来描述一组类。可以与File对比。
使用Class类,Field类,Method类,Constructor类,Package类来描述任何类。
Class:用来描述类本身。
Package:用来描述类所属的包。
Field:用来描述类中的属性。
Method:用来描述类的方法。
Constructor:用来描述类的构造方法。
Annotation:用来描述类中的注解。
1.Class中常用的方法
-
int result = clazz.getModifiers();获取类的修饰符(权限,特征)
-
String name = clazz.getName();获取名字(全类名)
-
String simpleName = clazz.getSimpleName();获取简单类名
-
Package p = clazz.getPackage(); (package类中的getName方法)p.getName(); 获取包/包名
-
Class claz = clazz.getSuperClass();获取超类
-
Class[] clazzes = clazz.getInterfaces();获取接口类
-
Class[] clazzes = clazz.getClasses();获取类中的内部类(public),私有的内部类是获取不到的。
-
Object obj = clazz.newInstance();默认调用无参数构造方法创建对象。若不存在无参构造器则会抛出异常。
- 抛出NoSuchMethodException。
-
Field nameField = clazz.getField("name");获取名为name的Field。(获取name属性,只是公有的,包括父类的)
-
Field[] fields = clazz.getFields();获取所有的Field。(获取所有公有的Field,包括父类的)
-
Field nameField = class.getDeclaredField("name")。(获取name属性,不管是私有或是共有,只能获取本类的)
-
Field[] fields = clazz.getDeclaredFields();获取所有的属性。只能获取本类的
-
Method method = clazz.getMethod("方法名",Class...参数列表);获取公有的方法(自己类+父类)
-
Method[] ms = clazz.getMethods();获取所有公有的方法(自己类+父类)
-
Method method = clazz.getDeclaredMethod("方法名",Class...参数列表);获取方法(公有+私有,只能获取本类的)
-
Method[] methods = clazz.getDeclaredMethods();获取所有方法(公有+私有,只能获取本类的)
-
Constructor c = clazz.getConstructor(Class...参数类型);获取构造方法
-
Constructor[] cs = clazz.getConstructors();获取所有的公有的构造方法
-
Constructor c = clazz.getDeclaredConstructor(Class...参数类型);获取私有+公有的构造方法
-
Constructor[] cs = clazz.getDeclaredConstructors();获取所有私有+公有的构造方法。
2.Field类中常用的方法
- int result = f.getModifiers();获取修饰符。
- Class clazz = f.getType();获取属性的类型。
- String name = f.getName();获取属性名
操作属性
设置属性的值
nameField.set(对象,属性值);例如:nameField.set(student,"ouYang");
获取属性的值
Object fieldValue = field.get(对象);例如:String name = (String)nameField.get(student);
为私有属性赋值/取值,需要开启访问权限
field.setAccessible(true)。表示私有属性可以直接被操作
我们知道,String字符串的内容和长度是不可以修改的,但是可以通过反射来改变
@Test
public void testString() throws NoSuchFieldException, IllegalAccessException {
String s = "abc";
Field value = s.getClass().getDeclaredField("value");
value.setAccessible(true);
char[] o = (char[]) value.get(s);
o[0] = '欧';
o[1] = '阳';
o[2] = '浩';
System.out.println(o);
value.set(s,o);
System.out.println(s);
}
3.Method类常用的方法
- int result = m.getModifiers();获取修饰符。(权限+特征)
- Class mothedReturnType = m.getReturnType();获取返回值的数据类型。
- String methodName = m.getName();获取方法的名字。
- Class[] mpts = m.getParameterTypes();获取方法参数列表的类型。
- Class[] mets = m.getExceptionTypes();获取方法抛出的异常类型。
调用方法,执行方法
如果没有找到,则会抛出异常(NoSuchMethodException)
Class pClass = Person.class;
Method m = p.getMethod("eat",String.class);参数列表是一个可变参数,表示方法的参数是0,1...个参数。
Object o = m.invoke(p,"吃饭");如果调用的方法有参数,则需要传入参数,如果方法有返回值,则可以接收放回值。
具体代码示例可以参考上面的示例代码
如果方法是私有的方法,是不允许访问,需要设置访问权限。
m.setAccessible(true);
4.Constructor构造方法
- int result = c.getModifiers();获取构造方法的修饰符
- String name = c.getName();获取构造方法的名字
- Class[] classes = c.getParameterTypes();获取构造方法的参数类型
- Class[] classes = c.getExceptionTypes();获取构造方法的异常类型
操作构造方法
创建对象(newInstance(Class...参数类型)
- 使用无参数构造方法,创建对象。
Class clazz = Person.class;
Constructor c = clazz.getConstructor();
Person p = (Person)c.newInstance();
- 使用带参数构造方法,创建对象。
Class clazz = Person.class;
Constructor c = clazz.getConstructor(String.name,Integer.class);
Person p = (Peroson)c.newInstance("ouYang",23);
System.out.println(p);
class Person{
private String name;
private Integer age;
public Person(String name,Integer age){
this.name = name;
this.age = age;
}
}
项目运用实例:
package com.global.struct.persistence.dbutils.transformer;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import com.global.struct.core.exception.StructRuntimeException;
public class ExtendedBeanListHandler<T> extends BeanListHandler<T> {
private Class<T> resultClass;
public ExtendedBeanListHandler(Class<T> type) {
super(type);
this.resultClass = type;
}
@Override
public List<T> handle(ResultSet rs) throws SQLException {
List<T> list = new ArrayList<T>();
try {
ResultSetMetaData rsmd = rs.getMetaData();
while(rs.next()){
T result = resultClass.newInstance();
int cols = rsmd.getColumnCount();
for (int col = 1; col <= cols; col++) {
String columnName = rsmd.getColumnLabel(col);
if (null == columnName || 0 == columnName.length()) {
columnName = rsmd.getColumnName(col);
}
String aliase = columnName;
String[] aliaseTmp = aliase.split("\\_");
StringBuffer sbAlise = new StringBuffer();
for (int j = 0; j < aliaseTmp.length; j++) {
String alstr = aliaseTmp[j];
if (j != 0) {
alstr = String.valueOf(alstr.charAt(0)).toUpperCase()
+ alstr.substring(1);
}
sbAlise.append(alstr);
}
Field field = null;
try {
field = resultClass.getDeclaredField(sbAlise.toString());
} catch (NoSuchFieldException e) {
continue;
}
field.setAccessible(true);
String fieldType = field.getType().getSimpleName();
Object fieldVal = rs.getObject(columnName);
if (fieldVal != null) {
String type = rsmd.getColumnTypeName(col);
if (fieldType.equals("Long")) {
fieldVal = Long.valueOf(fieldVal.toString());
} else if (fieldType.equals("String")) {
fieldVal = String.valueOf(fieldVal);
} else if (fieldType.equals("Integer")) {
if (type.equals("Boolean")) {
boolean tmpVal = (Boolean) fieldVal;
fieldVal = tmpVal ? 1 : 0;
}else {
fieldVal = Integer.valueOf(fieldVal.toString());
}
} else if(fieldType.equals("Boolean")){
if(!(fieldVal!=null&&fieldVal instanceof Boolean)) {
if(fieldVal!=null&&(fieldVal.toString().equals("1"))){
fieldVal = true;
}else {
fieldVal = false;
}
}
}
}
if(fieldType.equals("Double")){
try {
field.set(result, fieldVal);
} catch (Exception e) {
field.set(result, Double.valueOf(fieldVal.toString()));
}
}else{
field.set(result, fieldVal);
}
}
list.add(result);
}
} catch (Exception e) {
throw new StructRuntimeException("dbutils sql to bean fail",e);
}
return list;
}
}
最后
如果觉得不错的话,那就关注一下小编哦!一起交流,一起学习