创建运行时类的对象
//创建运行时类的对象
@Test
public void test2() throws Exception {
Class<Car> carClass = Car.class;
//调用newInstance创建一个运行时类的对象,该方法内部实际上调用了运行时类的空参构造器
//这里如果把Car类的空参构造器屏蔽掉再运行,就会报NoSuchMethodException的错误;
//其次空参构造器的访问权限不能是private
Car obj = carClass.getDeclaredConstructor().newInstance();
System.out.println(obj);
}
对反射动态性的一个体会,编译时无法确定创建什么类,运行时才可确定。
@Test
public void test3() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
int i = new Random().nextInt(3);
String classPath = "";
switch (i) {
case 0:
classPath = "com.senior.reflect.Car";
break;
case 1:
classPath = "java.lang.Object";
break;
case 2:
classPath = "java.util.Date";
break;
}
Object instance = getInstance(classPath);
System.out.println(instance);
}
//通过反射得到一个类的对象
public Object getInstance(String classPath) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class aClass = Class.forName(classPath);
return aClass.getDeclaredConstructor().newInstance();
}
可以获取运行时类的所有属性及方法的完整结构
package com.senior.reflect;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* @author eden
* @Description
* @create projectTest-com.senior.reflect:2021-05-14-17:44
* @since
*/
public class RunTimeClassTest {
//获取运行时类的所有属性
@Test
public void test() throws ClassNotFoundException {
Class<?> clazz = Class.forName("com.senior.reflect.Person");
//getFields()获取当前运行时类及其父类声明为public的属性
// Field[] fields = clazz.getFields();
// for(Field f:fields)
// {
// System.out.println(f);
// }
//getDeclaredFields()获取当前运行时类(不包含父类)的所有属性,不分权限
Field[] fields1 = clazz.getDeclaredFields();
for(Field f:fields1)
{
System.out.println(f);
//1.权限修饰符
int modifiers = f.getModifiers();//具体数字表示什么可以看Modifier类
System.out.print(Modifier.toString(modifiers)+"\t");
//2.数据类型
Class type = f.getType();
System.out.print(type.getName()+"\t");
//3.变量名
String name = f.getName();
System.out.print(name+"\t");
System.out.println();
}
}
//获取运行时类的方法结构
@Test
public void test1() throws ClassNotFoundException {
Class aClass = Class.forName("com.senior.reflect.Person");
//getMethods()获取当前运行时类及其父类声明为public的方法
// Method[] methods = aClass.getMethods();
// for(Method m:methods)
// {
// System.out.println(m);
// }
//getDeclaredFields()获取当前运行时类(不包含父类)的所有方法,不分权限
Method[] declaredMethods = aClass.getDeclaredMethods();
for(Method f:declaredMethods){
System.out.println(f);
}
//可以获取运行时类的方法的各种结构,包括参数 返回值等等,这里不赘述
}
}
//Creature父类
public class Creature<T> implements Serializable {
private char gender;
public double weight;
private void breath()
{
System.out.println("呼吸");
}
public void eat(){
System.out.println("吃东西");
}
}
public class Person extends Creature<String> implements Serializable, Comparable<String> {
public String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private String showNation(String nation) {
System.out.println("我的国籍是:" + nation);
return nation;
}
public void show() {
System.out.println("Person{" +
"name='" + name + '\'' +
", age=" + age +
'}');
}
@Override
public int compareTo(String o) {
return o.compareTo(this.name);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
还可以获取构造器,获取方法抛出的异常,获取运行时类所在的接口,包,注解等等,这里不赘述,用到再说。
调用运行时类的指定属性/方法
public class RunTimeClassTest2 {
//操作运行时类的指定属性
@Test
public void testField() throws Exception {
//获取运行时类
Class<Person> clazz = (Class<Person>) Class.forName("com.senior.reflect.Person");
//创建运行时类的对象
Person person = clazz.getDeclaredConstructor().newInstance();
//获取指定的属性
Field name = clazz.getField("name");
name.set(person,"XDD");//设置当前属性值
System.out.println(person);
Field age = clazz.getDeclaredField("age");
age.setAccessible(true);//setAccessible为true,则可设置缺省权限和private权限的成员变量
age.set(person,30);//设置当前属性值
System.out.println(person);
}
//操作运行时类的指定方法
@Test
public void testMethod() throws Exception {
Class<Person> clazz = (Class<Person>) Class.forName("com.senior.reflect.Person");
Person person = clazz.getDeclaredConstructor().newInstance();
//调用类的私有方法
Method showNation = clazz.getDeclaredMethod("showNation", String.class);
showNation.setAccessible(true);
Object nation = showNation.invoke(person, "China");
System.out.println(nation.toString());
System.out.println("-------------如何调用静态方法-----------------");
Method show = clazz.getDeclaredMethod("show");
Object obj = show.invoke(person);
// Object obj = show.invoke(null);//也可
}
}
一般很少通过这种方式调用指定的构造器,操作流程与上述类似,不赘述。
该博客图片来源于尚硅谷宋老师教学课件