文章目录
离不开的知识:反射机制🤪
java反射快速入门👩💻
写一个注解,从而理解它😎
总结🍭
离不开的知识:反射机制🤪
Java开始是静态强类型语言,类型是静态的。
优点
避免了程序在运行时发生变量类型相关的错误,代码更健壮,
提前知道类型,编译器可以针对这些信息进行优化,从而提升程序的执行速度。
缺点
程序员要注意变量的类型,变量的声明会使得代码量增加。
Java语言为了使用社会需求,Java在静态的基础之上引入了反射机制使得自己具有一定的动态性,这使得Java语言更加灵活,也因此诞生了大名鼎鼎的spring框架等等。
java反射快速入门👩💻
提一个需求,要求不修改源码,通过配置文件决定实例化哪个对象,Ok
bean.properties配置文件
bean=com.liu.annotation_.Dog
Dog类
package com.liu.annotation_; public class Dog { private Integer id = 1; private String name = "小猫"; }
Cat类
package com.liu.annotation_; public class Cat { private Integer id = 1; private String name = "小狗"; }
Test类
package com.liu.annotation_; import java.io.IOException; import java.util.Properties; public class Test { private static Properties properties; static { properties = new Properties(); try { /*通过类加载器获取将资源转化为流的方法,加载配置文件*/ properties.load(Test.class.getClassLoader().getResourceAsStream("bean.properties")); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception{ /*获取配置文件的bean*/ String bean = properties.getProperty("bean"); /*获取实例的类名forName,getInstance是创建实例,返回值是一个对象 * 因为我们知道他的实际类型,因此可以通过多态强制转换,也可以通过getClass获取实际类型*/ Object o = Class.forName(bean).newInstance(); System.out.println(o.getClass()); /*class com.liu.annotation_.配置文件的类型*/ } }
当配置文件是bean=com.liu.annotation_.Dog时,输出
当配置文件是bean=com.liu.annotation_.Cat时,输出
这就完成了在不修改源码的情况下,动态改变了实例化的对象,使得程序变得更灵活……
它也是很多框架的基础,其中注解也有用到它哦,下面开始注解的解析
写一个注解,从而理解它😎
自定义MyComponent 注解
package com.liu.annotation_; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /*程序运行时注解生效*/ @Retention(RetentionPolicy.RUNTIME) /*给谁添加*/ @Target(ElementType.TYPE) public @interface MyComponent { }
自定义MyValue 注解
package com.liu.annotation_; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface MyValue { String value(); }
给cat类添加自定义注解
package com.liu.annotation_; @MyComponent public class Cat { @MyValue("0") private Integer id; @MyValue("招财猫") private String name; @Override public String toString() { return "Cat{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
使用我们自定义的注解 核心
package com.liu.annotation_; import java.lang.reflect.Field; public class TestMyAnnotation { public static void main(String[] args) throws Exception { /*获取类对象*/ Class<Cat> catClass = Cat.class; /*通过getAnnotation()方法获取我们自定义的注解的类对象*/ MyComponent annotation = catClass.getAnnotation(MyComponent.class); /*判断*/ if(annotation != null){ System.out.println("添加了 MyComponent 注解"); /*创建对象*/ Cat cat = Cat.class.newInstance(); /*开始赋值*/ System.out.println(cat); Field[] declaredFields = catClass.getDeclaredFields(); for (Field declaredField : declaredFields) { MyValue valueAnnotation = declaredField.getAnnotation(MyValue.class); if(valueAnnotation != null){ System.out.println(valueAnnotation + "添加了 value 注解"); /*拿到注解对象的值*/ String value = valueAnnotation.value(); System.out.println("注解添加的值是:" + value); /*私有属性要想赋值可以使用反射爆破*/ declaredField.setAccessible(true); /*类型判断并赋值*/ if(declaredField.getType().getName().equals("java.lang.Integer")){ Integer val = Integer.parseInt(value); declaredField.set(cat,val); }else{ declaredField.set(cat,value); } } } System.out.println("最终效果---------------"); System.out.println(cat); }else{ System.out.println("没有添加 MyComponent 注解"); /*不赋值*/ } } }
运行结果,成功赋值
添加了 MyComponent 注解 Cat{id=null, name='null'} @com.liu.annotation_.MyValue(value=0)添加了 value 注解 注解添加的值是:0 @com.liu.annotation_.MyValue(value=招财猫)添加了 value 注解 注解添加的值是:招财猫 最终效果--------------- Cat{id=0, name='招财猫'}
总结🍭
利用反射机制以及提供的getAnnotation()方法可以获取我们自定义的注解对象,再经过简单判断是否添加,如果添加了@MyComponent,就创建对象,如果没有则不添加,再经过反射机制获取所有字段以及通过getAnnotation()方法循环判断是否添加了自定义的@MyValue注解,如果有就给它赋值,但是有一个问题,字段是私有属性,按理说是无法直接赋值的,确实如此,不过,我们可以通过Java提供的反射爆破,越过检查,从而完成私有属性的直接赋值,只需要一行代码declaredField.setAccessible(true);
即可,另外在赋值时判断一下待赋值的字段的类型,然后再根据类型分别赋值就🆗了,其实也是很简单的,但是这种思想真的很有意思,值得思考和借鉴,因此,我相信你对Java中神奇的注解有了初步的了解,这对你学习框架很有帮助