最后引用“阿里工程师的自我修养”手册里面的一句话结尾:对我们来说,想要没有焦虑,想要人生变得踏实,就需要管理好你的时间、收起你的浮躁,并且相信 " 慢慢来,成长最快 "。
案例一 : 不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
public class ReflectTest {
public static void main(String[] args) throws Exception {
//1.加载配置文件
//1.1创建Properties对象
Properties pro = new Properties();
//1.2加载配置文件,转为一个集合
//1.2.1获取class目录下的配置文件
【思考:】这里为什么不用传统的方式加载
//因为我们项目发布的是web目录下的文件 所以src文件并不存在, 所以路径不存在src项目
// FileInputStream fileInputStream=new FileInputStream("/day01/src/pro.properties")
//所以选择类加载器生产
//获得类加载器
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
pro.load(is);
//2.获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法对象
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
}
//配置文件:
className=cn.itcast.domain.Student
methodName=sleep
方法二 通过注解和反射实现
//定义了属性,在使用时需要给属性赋值
【
定义了属性,在使用时需要给属性赋值
1. 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
2. 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。
3. 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略】
@Pro(className = "cn.itcast.annotation.Demo1",methodName = "show")
public class ReflectTest {
public static void main(String[] args) throws Exception {
/*
前提:不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
*/
//1.解析注解
//1.1获取该类的字节码文件对象
Class<ReflectTest> reflectTestClass = ReflectTest.class;
//2.获取上边的注解对象
//其实就是在内存中生成了一个该注解接口的子类实现对象
/*
public class ProImpl implements Pro{
public String className(){
return "cn.itcast.annotation.Demo1";
}
public String methodName(){
return "show";
}
}
*/
Pro an = reflectTestClass.getAnnotation(Pro.class);
//3.调用注解对象中定义的抽象方法,获取返回值
String className = an.className();
String methodName = an.methodName();
System.out.println(className);
System.out.println(methodName);
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法对象
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
}
Demo1类
public class Demo01 { public void show(){ System.out.println("demo01 show....."); } }
pro自定义注解
/** * 描述需要执行的类名,和方法名 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Pro { String className(); String methodName(); }
案例二:不能改变该类的任何代码。可以为任意类的对象的成员变量,赋任意值
private static void setProperty(Object object,String name,Object value) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//方式一:
/*
//根据参数object获取字节码文件对象
Class<?> aClass = object.getClass();
//根据字节码文件获取任何权限的成员变量
Field field = aClass.getDeclaredField("name");
//采用暴力反射机制,对私有变量进行赋值
field.setAccessible(true);
field.set(object,value);*/
//方式二
//根据参数object获取字节码文件对象
Class<?> aClass = object.getClass();
//根据字节码文件获取任何权限的成员变量
Field field = aClass.getDeclaredField("name");
//获得参数类型
Class<?> type = field.getType();
//由于我们知道成员变量生产的setxxx()方法的命名规则 例如 name->setName();
//由于存在重载 所以在 aClass.getMethod();方法中参数应该方法名 和 类型
Method method = aClass.getMethod("set" + name.substring(0, 1).toUpperCase().concat(name.substring(1)), type);
//加载方法
method.invoke(object,value);
}
public static void main(String[] args) throws Exception {
Student student=new Student();
setProperty(student,"name","张三");
System.out.println(student);
}
学生类这里就不写上来了