8 注解 枚举 反射
8.1 注解
自定义注解
- 自定义注解
// 水果名称注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
String value() default "";
}
- 自定义注解处理器
// 注解处理器
public class FruitInfoHandler {
public static void getFruitInfo(Class<?> clazz){
String strFruitName = " 水果名称: ";
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
if(field.isAnnotationPresent(FruitName.class)) {
//获取水果名
FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
strFruitName = strFruitName + fruitName.value();
System.out.println(strFruitName);
}
}
}
}
- 使用自定义注解
public class Apple {
@ FruitName("Apple")
private String appleName;
public String getAppleName() {
return appleName;
}
public void setAppleName(String appleName) {
this.appleName = appleName;
}
}
- 测试结果
public class test {
public static void main(String[] args) {
FruitInfoHandler.getFruitInfo(Apple.class);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VPqtS2W0-1677208988263)(images/HwNCzZZtyU7aaUfg-bpLt3haRQ62twfROTcfodKPi0E.png)]
https://blog.csdn.net/weixin_45565886/article/details/127136969
元注解
元注解(Retention, Target, Documented, Inherited)是用于修饰其他注解的注解。
- Retention:指定修饰那个Annotation的生命周期;
- Target:用于指定被修饰的Annotation能用于修饰哪些程序元素(如:CONSTRUCTOR, METHOD等)
- Documented:用于指定被该元注解修饰的注解类将被javadoc工具提取成文档;
- Inherited:被它修饰的Annotation将具有继承性。
8.2 枚举
枚举定义
public enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER;
}
常用方法
- String seasonName = season.toString() 获取对象名字
- Season[] values = Season.values() 获取枚举类数组
- Season autumn1 = Season.valueOf(“AUTUMN”) 通过对象名字获取这个枚举对象
public static void main(String[] args) {
// 1
Season autumn = Season.AUTUMN;
System.out.println(autumn);
// 2
Season[] values = Season.values();
for(Season s:values){
System.out.println(s);
}
// 3
//注意:对象的名字必须传正确,否则抛出异常
Season autumn1 = Season.valueOf("AUTUMN");
System.out.println(autumn1);
}
枚举类实现接口
- 定义接口方法
public interface TestInterface {
public void show();
}
- 枚举类中重写接口方法
public enum Season implements TestInterface {
SPRING{
public void show() {
System.out.println("这是春天。。。");
}
},
SUMMER{
public void show() {
System.out.println("这是夏天。。。");
}
},
AUTUMN {
public void show() {
System.out.println("这是秋天。。。");
}
},
WINTER{
public void show() {
System.out.println("这是冬天。。。");
}
};
}
- 应用
public static void main(String[] args) {
Season autumn = Season.AUTUMN;
autumn.show();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-twey6dOt-1677208988264)(images/wEdXj-JDSefahbo7-aPedGR3HJ6h3OZiRr6l8rrrxgE.png)]
8.3 反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。
获取字节码信息的四种形式
- getClass()
- 内置class属性
- 调用Class类提供的静态方法forName⭐
- 利用类加载器
class Scratch {
public static void main(String[] args) throws ClassNotFoundException {
// 1
Animal p = new Animal();
Class c1 = p.getClass();
System.out.println(c1);
// 2
Class c2 = Animal.class;
System.out.println(c2);
System.out.println(c1==c2);
// 3
Class c3 = Class.forName("test.Animal");
// 4
ClassLoader loader = Scratch.class.getClassLoader();
Class c4 = loader.loadClass("test.Animal");
}
}
获取构造器和创建对象
获取属性和对属性进行赋值
获取方法和调用方法
获取类的接口,所在包,注解
创建Person的对象,以后用new Person()创建,还是用反射创建?
需要体现程序的动态性的时候使用反射来创建对象;不知道是创建那个对象,只有在运行的时候才知道是创建那一个对象,比如说我们在点外卖的时候选择支付方式,可以微信支付、支付宝支付、或者是美团支付只有在用户选择后我们才知道去创建那个对象,这个时候我们就需要修改反射来创建对象。
反射是否破坏了面向对象的封装性?
破坏了面向对象的封装性,但是二者并不冲突。对象的封装主要是解决安全性,反射的提出主要是为了解决程序的动态性。 对象的privte修饰的属性、方法是就明确的告诉就不要使用这里的属性和方法; 但反射确实是调用到或者使用到private修饰的方法或属性。一般来说是不建议使用这里对象里面的private修饰的属性或者方法。因此这里说他们是不冲突的。
https://blog.csdn.net/qq_26896085/article/details/122290070