目录
- 概述
- 什么是反射
- 优缺点
- Class类
- 获得Class对象
- 反射创建对象
- 获取构造方法
- 获取成员变量
- 获取成员方法
- 通过反射创建对象
- 反射的应用
- 序列化&反序列化
概述
什么是反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
反射就是把java类中各个成分映射成一个个java对象也就是Class类对象
例如一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象
优缺点
优点
动态的获取实例,提高灵活性
缺点
性能较低,需要解析字节码,将内存中的对象解析
Class类
- 一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被使用时都会创建一个Class对象
- Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本信息
获得Class对象
public class Text {
public static void main(String[] args) throws ClassNotFoundException {
/*
获取Class对象
*/
//方式1:通过其class属性获取,任何数据类型(包括基本数据类型)都有一个“静态”的class属性
Class c1 = Car.class;
System.out.println(c1);
//方式2:Object类里的getClass(),public final native Class<?> getClass(); native:本地方法(C++),操作系统实现
Class c2 = new Car().getClass();
//方式3:Class类的静态方法:forName(),根据类的地址将类的信息加载到内存中,并创建Class对象
Class c3 = Class.forName("com.ff.dormitoryManage.reflect.Car");
}
}
反射创建对象
T newInstance() 创建由此 类对象表示的类的新实例。
Car car1 = (Car) c1.newInstance();//创建了Class对象所表示的类的对象
获取构造方法
批量的方法
- public Constructor[] getConstructors():所有"公有的"构造方法
- public Constructor[] getDeclaredConstructors():获取所有的构造方法
获取单个的方法
- public Constructor
getConstructor
(Class… parameterTypes):获取单个的"公有的"构造方法: - public Constructor
getDeclaredConstructor
(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Text {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("com.ff.dormitoryManage.reflect.Car");
/*
通过Class对象可以获取类中的构造方法
1.获取构造方法:
1).批量的方法:
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
2).获取单个的方法,并调用:
public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
调用构造方法:
Constructor-->newInstance(Object... initargs)
*/
//获取所有的共有构造方法
for (Constructor constructor : c.getConstructors()) {
System.out.println(constructor);
}
//获取所有的构造方法
for (Constructor declaredConstructor : c.getDeclaredConstructors()) {
System.out.println(declaredConstructor);
}
//获取公有无参构造方法
Constructor constructor = c.getConstructor();
//获取私有构造方法
Constructor declaredConstructor = c.getDeclaredConstructor(String.class, String.class);
//修改权限(忽略访问修饰符)
declaredConstructor.setAccessible(true);
//调用构造方法创建对象
Car car = (Car) declaredConstructor.newInstance("宝马", "红色");
}
}
获取成员变量
批量的
- Field[] getFields():获取所有的"公有字段"
- Field[] getDeclaredFields():获取所有字段
单个的
- public Field
getField(String fieldName)
:获取某个"公有的"字段; - public Field
getDeclaredField(String fieldName)
:获取某个字段(可以是私有的)
设置字段的值
Field --> public void set(Object obj,Object value):
参数说明: 1.obj:要设置的字段所在的对象 2.value:要为字段设置的值
package com.ff.dormitoryManage.reflect;
import java.lang.reflect.Field;
public class Text2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
Class c = Class.forName("com.ff.dormitoryManage.reflect.Car");
Car car = (Car) c.newInstance();
/*
获取成员变量并调用:
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:要为字段设置的值
*/
//获取所有共有的属性
for (Field field : c.getFields()) {
System.out.println(field);
}
//获取所有的属性
for (Field declaredField : c.getDeclaredFields()) {
System.out.println(declaredField);
}
//获取指定的属性并调用
Field name = c.getField("name");
name.set(car, "宝马");
System.out.println(car);
Field color = c.getDeclaredField("color");
color.setAccessible(true);
color.set(car, "黑色");
System.out.println(car);
}
}
获取成员方法
批量的
- public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
- public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
获取单个
- 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:调用方式时所传递的实参
package com.ff.dormitoryManage.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class text4 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("com.ff.dormitoryManage.reflect.Car");
Car car = (Car) c.newInstance();
/*
获取成员方法并调用:
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:调用方式时所传递的实参;
*/
//获得成员方法
Method run1 = c.getMethod("run");
run1.invoke(car);
Method run2 = c.getMethod("run", int.class);
run2.invoke(car, 60);
//获得get/set方法
Field[] fields = c.getDeclaredFields();
for (Field f : fields) {
Method method = c.getMethod("get" + f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1));
method.invoke(car);
}
}
}
-------------------------------------------------------
公有无参构造方法
汽车跑
汽车以60码的速度跑
getName方法
getColor方法
通过反射创建对象
- 获取Class对象
- 根据Class对象
getConstructor()
获得Constructor对象 - 根据Constructor对象的
newInstance()
获取反射类的对象 - 如果需要调用方法使用
getMethod()
获得Method对象 - 然后利用这个对象invoke()调用方法
反射的应用
JDBC 数据库连接
Spring框架
通过Xml加载Bean:
- 将Xml配置文件加载到内存中
- 解析文件中的内容
- 从配置文件中的类信息获取到这个类的Class对象
- 使用反射机制动态配置实例的属性
序列化&反序列化
序列化
Java对象—>字节序列
反序列化
字节序列—>Java对象
作用
- 便于在网络传输
- 本地保存和恢复,万一JVM停机了,通过反序列化可以恢复