1、获取Class的三方式
要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取java.lang.Class实例?
方式 | 备注 |
---|---|
Class.forName(“完整类名带包名”) | 静态方法 |
对象.getClass() | |
任何类型.class |
注:以上三种方式返回值都是Class类型。
2、JDBC重点(Class.forName导致类加载)
如果你只是希望一个类的静态代码块执行,其它代码一律不执行,可以使用:
Class.forName("完整类名");
这个方法的执行会导致类加载,类加载时,静态代码块执行。
3.通过反射获取类的权限修饰符,类名,属性权限,类型,名称
Book实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}
/**
* 测试反射获取类的定义
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws NoSuchMethodException
*/
@Test
public void testReflect() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException {
//测试反射获取
Class<?> bookClass = Class.forName("com.jjh.pojo.Book");
StringBuilder sb = new StringBuilder();
sb.append(Modifier.toString(bookClass.getModifiers())+ " class " + bookClass.getSimpleName() + "{\n");
//获取属性
Field[] fields = bookClass.getDeclaredFields();
for (Field field : fields) {
sb.append("\t");
sb.append(Modifier.toString(field.getModifiers()));
if(field.getModifiers()!=0) sb.append(" ");
//获取属性的类型
sb.append(field.getType().getSimpleName());
sb.append(" ");
//获取属性的名称
sb.append(field.getName());
sb.append(";\n");
}
sb.append("}");
System.out.println(sb);
}
运行结果:
public class Book{ private Integer id; private String type; private String name; private String description; }
4.Fields通过反射给属性赋值
/**
* 通过反射给对象属性赋值
*/
@Test
public void setProperty() throws Exception{
Class<?> bookClass = Class.forName("com.jjh.pojo.Book");
Object book = bookClass.newInstance();
Field nameField = bookClass.getDeclaredField("name");
//设置暴力反射赋值
nameField.setAccessible(true);
nameField.set(book,"大话西游");
System.out.println(book);
}
运行结果:
Book(id=null, type=null, name=大话西游, description=null)
注意:
若类的属性使用了private修饰,则要使用setAccessible(true)方法暴力赋值
5.通过反射获取方法Methods
(1)反射获取方法的权限修饰符,返回值类型,参数列表
/**
* 测试通过反射获取方法
*/
@Test
public void testMethodsReflect() throws Exception{
Class<?> carClass = Class.forName("com.jjh.pojo.Car");
Method[] methods = carClass.getDeclaredMethods();
StringBuilder sb = new StringBuilder();
for (Method method : methods) {
//方法的权限修饰符
String modifier = Modifier.toString(method.getModifiers());
sb.append(modifier+" ");
//方法的返回值类型
String returnType = method.getReturnType().getSimpleName();
sb.append(returnType+" ");
//方法的名称
String name = method.getName();
sb.append(name+"(");
//参数列表
Class<?>[] parameterTypes = method.getParameterTypes();
for(int i=0;i<parameterTypes.length;i++){
sb.append(parameterTypes[i].getSimpleName());
if(i!=parameterTypes.length-1) sb.append(", ");
}
sb.append(")\n");
}
System.out.println(sb);
}
运行结果:
public String getName() public String toString() public void setName(String) public Integer getId() public void setLocalDateTime(LocalDateTime) public String buy(String) public void setId(Integer) public LocalDateTime getLocalDateTime()
(2)方法的四要素
-
要素1:对象 userService
-
要素2:login 方法名
-
要素3:实参列表
-
要素4:返回值
/**
* 测试反射调用方法
*/
@Test
public void testMethodInvoke() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class<?> carClazz = Class.forName("com.jjh.pojo.Car");
Object car = carClazz.newInstance();
Method buy = carClazz.getDeclaredMethod("buy", String.class);
Field idFiled = carClazz.getDeclaredField("id");
idFiled.setAccessible(true);
idFiled.set(car,1);
Field nameFiled = carClazz.getDeclaredField("name");
nameFiled.setAccessible(true);
nameFiled.set(car,"丰田");
Field localDateTimeFiled = carClazz.getDeclaredField("localDateTime");
localDateTimeFiled.setAccessible(true);
localDateTimeFiled.set(car,LocalDateTime.now() );
Object result = buy.invoke(car, "张三");
System.out.println(result);
}
运行结果:
用户:张三购买了id为:1的车,在2023-06-16T19:51:19.853653600
6.Constructor类反射获取构造方法
通过Constructor的newInstance()方法构建对象,可以传参数,也可以无参数
/**
* 通过反射构造方法创建对象
*/
@Test
public void testConstructor() throws Exception{
Class<?> carClazz = Class.forName("com.jjh.pojo.Car");
Constructor<?> constructor = carClazz.getDeclaredConstructor(Integer.class,String.class,LocalDateTime.class);
Object car = constructor.newInstance(1,"比亚迪",LocalDateTime.now());
System.out.println(car);
}
运行结果:
Car{id=1, name='比亚迪', localDateTime=2023-06-16T20:09:17.424101200}
7.获取一个类的父类以及实现的接口
两个方法【Class类中的】
public native Class<? super T> getSuperclass()
public Class<?>[] getInterfaces()
/**
* 获取一个类的父类和它实现的接口
*/
@Test
public void testGetSuperClassAndInterface() throws ClassNotFoundException {
Class<?> arryListClazz = Class.forName("java.util.ArrayList");
Class<?> superclass = arryListClazz.getSuperclass();
Class<?>[] interfaces = arryListClazz.getInterfaces();
System.out.println("ArrayList的父类是: "+superclass.getSimpleName());
System.out.println("ArrayList实现的接口有:");
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface);
}
}
运行结果:
ArrayList的父类是: AbstractList ArrayList实现的接口有: interface java.util.List interface java.util.RandomAccess interface java.lang.Cloneable interface java.io.Serializable