java框架基础--反射

前言

本文将详细讲述反射的基本概念以及反射底层代码的部分实现

反射

就是程序在运行状态时,对于任何一个类,都在 知道类名的状况下,动态获取该类中的所有属性和方法(包括私有),可以动态地通过该类的对象调用类的属性和方法的机制称为反射机制

是将java中的类映射成一个个对象

例如类中拥有成员变量,成员方法,构造方法等等信息,而反射机制就是将这些信息映射成一个个对象.而在这个过程中相关的类主要包括

Class 类型 Constructor 构造方法 Method 方法 Field 属性

除了Class外,其他类都位于java.lang.reflect包中

可见,反射API将类的类型、方法、属性都封装成了类,其中最重要的类是 Class,可以说,反射的使用都是从Class开始.

Class类

Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本信息

一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被 使用时都会创建一个Class对象。

那么就有一个问题:

如何获得Class对象

Class类的对象,表示当前正在运行中的类和接口.

以一个User类和一个Car类举例:

其中User类的成员变量有account,password

Car类中的成员变量有name,color

使用反射机制时,我们只知道类的名称(包名+类名)

String classname = "com.zhu.javareflect.User";

方式一:Class类的静态方法 forName(String name)

Class clazz1 = Class.forName(classname);
System.out.println(clazz1);

方式二:类名.class方式:适用于通过类名获得Class实例的情况

Class clazz2 = User.class;
System.out.println(clazz1==clazz2);

方式三:Object类中的getClass方法:适用于通过对象获得Class实例的情况

User user = new User();
Car car = new Car();
Class clazz3 = user.getClass();
Class clazz4 = car.getClass();

System.out.println(clazz1==clazz3);

API中 Constructor 构造方法

除Class类之外,我们还可以通过API中 Constructor 构造方法获得类中的构造方法来获得类中的信息

Class类中定义了如下方法

Constructor getConstructor(Class... parameterTypes) :

通过指定参数类型,返回构造方法实例。

获得类中的构造方法,通过构造方法api中的方法创建对象

Constructor实例通过Class实例获得,所以都需要Class对象

String classname = "com.zhu.javareflect.User";

1.通过类名,获得类的Class对象

Class aClass = Class.forName(classname);
System.out.println(aClass);

2.通过类的Class对象,创建对象

Object object = aClass.newInstance();
System.out.println(object);

3.获得类中的构造方法,通过构造方法api中的方法创建对象

Constructor类可以通过getXXX方法获得构造方法的基本信息

getName:返回构造方法的名字

除了获得构造方法的基本信息,还可以创建实例

newInstance(Object... initargs) :创建实例

Constructor constructor1 = aClass.getConstructor();//获得指定的公共构造方法
Object object1 = constructor1.newInstance();
Constructor constructor2 = aClass.getConstructor(String.class,String.class);
Object object2 = constructor2.newInstance("zhangsan","111");
System.out.println(object1);
System.out.println(object2);

Constructor [] constructors = aClass.getConstructors();//获得所有公共的构造方法
System.out.println(constructors.length);

4。虽然可以获得私有构造方法,但是一般不建议操作私有成员,会打破封装性

aClass.getDeclaredConstructor();//获得类中任意的构造方法,包含私有的

aClass.getDeclaredConstructors();//获得类中所有的构造方法,包含私有的

Field 属性

相同的,我们也可以通过field属性来获取类中的信息

获得Field实例例,都是通过Class中的方法实现

public Field getField(String name)通过指定Field名字,返回 Field实例.

........ 注意Field的访问权限

Field类的作用

Field类将类的属性进行封装,可以获得属性的基本信息、属性的值,也 可以对属性进行赋值.

getName:返回属性的名字

set:设置属性值

获得类中成员变量

Field实例通过Class实例获得,所以都需要Class对象

String classname = "com.zhu.javareflect.User";

1.通过类名,获得类的Class对象

Class aClass = Class.forName(classname);

2.通过类的Class对象,创建对象

Object object = aClass.newInstance();

3.获得类中成员变量

Field accountField = aClass.getField("account");//获得指定名称的公共的成员变量

Field accountField = aClass.getDeclaredField("account");//获得指定名称的公共的成员变量 包含私有的

accountField.setAccessible(true);//允许访问操作私有属性

accountField.set(object, "admin");

System.out.println(object);

4.以集合的形式获取类中信息

模拟从数据库查到的数据

HashMap<String,String> map = new HashMap<>();
map.put("account", "admin");
map.put("password", "1111");

获得类中所有的成员变量

Field[] declaredFields = aClass.getDeclaredFields();
for(Field field : declaredFields){
field.setAccessible(true);//允许访问操作私有属性 不建议

field.set(object,map.get(field.getName()));
}
System.out.println(object);

Method 方法

Method实例都是通过Class类的方法获得

Method getMethod(String name, Class... parameterTypes) :

通过指定方法名,参数类型,返回一个Method实例

Method类的作用

Method类将类中的方法进行封装,可以动态获得方法的信息,例如

getName:获得方法名字

getParameterTypes:获得方法参数类型

除了动态获得方法信息外,Method还能动态调用某一个对象的具体方法

invoke(Object obj, Object... args) :使用obj调用该方法,参数为args

演示通过属性的get和set方法,对类中私有属性进行赋值取值操作

Method实例通过Class实例获得,所以都需要Class对象

String classname = "com.zhu.javareflect.User";

1.通过类名,获得类的Class对象

Class aClass = Class.forName(classname);

2.通过类的Class对象,创建对象

Object object = aClass.newInstance();

3.模拟从数据库查到的数据

HashMap<String,String> map = new HashMap<>();
map.put("account", "admin");//account,password是根据类名中的属性名进行更改
map.put("password", "1111");

4.把查询到的数据封装到对象中

先拿到类中的所有的私有属性

Field[] declaredFields = aClass.getDeclaredFields();
for (Field field:declaredFields){

//根据属性名 生成set方法的名称

String setmethod = "set"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);

//通过Class对象获得对应的Set方法对象

Method setmethodObj = aClass.getMethod(setmethod, field.getType());

//调用set方法

setmethodObj.invoke(object,map.get(field.getName()));

System.out.println(object);
}

反射案例

自定义java对象转json工具类

JsonUtil是类名

在main方法中对User类和Car类中的属性存入数据

public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
User user = new User();
user.setAccount("admin");
user.setPassword("1111");

Car car = new Car();
car.setName("宝马");
car.setColor("红色");

System.out.println(JsonUtil.objectToJson(user));
System.out.println(JsonUtil.objectToJson(car));

}

在main方法外定义objectToJson(Object object)方法

public static String objectToJson(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

//获得传入参数object的Class对象
Class clazz = object.getClass();
String json = "{";

//获得类中所有属性

Field[] declaredFields = clazz.getDeclaredFields();
for (Field field:declaredFields){

//生成属性get方法名字

String getmethod = "get"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);

//获得方法对象

Method method = clazz.getMethod(getmethod);

//调用方法

String value = (String) method.invoke(object);

//把属性名和值拼接成键值

json +=field.getName()+":"+value+",";
}
json = json.substring(0,json.length()-1);//去掉多余的逗号

json +="}";
return json;
}

相关推荐
C-SDN花园GGbond1 小时前
【探索数据结构与算法】插入排序:原理、实现与分析(图文详解)
c语言·开发语言·数据结构·排序算法
迷迭所归处2 小时前
C++ —— 关于vector
开发语言·c++·算法
架构文摘JGWZ2 小时前
Java 23 的12 个新特性!!
java·开发语言·学习
leon6252 小时前
优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序
开发语言·算法·matlab
拾光师3 小时前
spring获取当前request
java·后端·spring
aPurpleBerry3 小时前
neo4j安装启动教程+对应的jdk配置
java·neo4j
锦亦之22333 小时前
QT+OSG+OSG-earth如何在窗口显示一个地球
开发语言·qt
我是苏苏3 小时前
Web开发:ABP框架2——入门级别的增删改查Demo
java·开发语言
姜太公钓鲸2333 小时前
c++ static(详解)
开发语言·c++
菜菜想进步3 小时前
内存管理(C++版)
c语言·开发语言·c++