win8风格手机网站模板五大电商平台都有哪些
2026/1/9 21:25:44 网站建设 项目流程
win8风格手机网站模板,五大电商平台都有哪些,凡科可以做视频网站吗,为了 门户网站建设目录 1、Java注解 1.1、介绍 1.2、注解的元注解 1.3、高级特性 1.4、框架中的典型应用 1.5、自定义注解 2、注解原理 2.1、注解如何存储 2.2、JVM 加载阶段 2.3、反射读取原理 2.4、default的实现机制 3、生命周期阶段 3.1、生命周期 3.2、保留策略 4、注意事项 …目录1、Java注解1.1、介绍1.2、注解的元注解1.3、高级特性1.4、框架中的典型应用1.5、自定义注解2、注解原理2.1、注解如何存储2.2、JVM 加载阶段2.3、反射读取原理2.4、default的实现机制3、生命周期阶段3.1、生命周期3.2、保留策略4、注意事项前沿注解Annotation的未来一、历史回溯注解的三次进化浪潮1.1 第一代编译期辅助2004–2010代表Override,SuppressWarnings特点仅作用于编译器无运行时语义局限无法参与程序逻辑1.2 第二代运行时反射驱动2010–2020代表Spring Component,JPA Entity核心Retention(RUNTIME) 反射问题启动慢大量反射解析内存占用高代理对象无法用于 GraalVM Native Image1.3 第三代编译时代码生成2020–至今代表Lombok, MapStruct, Micronaut突破Retention(SOURCE) 注解处理器Annotation Processor优势零运行时开销兼容 AOT 编译类型安全趋势“运行时注解 → 编译时注解” 是云原生时代的必然选择。1、Java注解1.1、介绍元数据的载体它本身不执行任何操作但可以被工具、编译器、框架读取并触发相应行为。注解 不改变程序逻辑的“标记”示例常见注解Override // 编译期检查是否重写了父类方法 Deprecated // 标记过时方法 SuppressWarnings(unchecked) // 抑制编译警告 RestController // Spring标识这是一个 REST 控制器编译器生成的特殊接口注解在编译后是一个继承自java.lang.annotation.Annotation的接口所有注解成员方法 接口中的抽象方法使用注解的地方 生成一个匿名内部类实现该接口1.2、注解的元注解元注解Meta-Annotations 用来注解其他注解的注解。Java 提供了 5 个元注解作用Retention指定注解生命周期SOURCE/CLASS/RUNTIMETarget指定注解可用的位置类、方法、字段等Documented是否包含在 JavaDoc 中Inherited是否可被子类继承仅对类有效Repeatable允许同一位置重复使用注解Java 8示例Target 可选值Target({ ElementType.TYPE, // 类、接口、枚举 ElementType.METHOD, // 方法 ElementType.FIELD, // 字段 ElementType.PARAMETER, // 参数 ElementType.CONSTRUCTOR, // 构造函数 ElementType.LOCAL_VARIABLE, // 局部变量 ElementType.ANNOTATION_TYPE // 注解类型 })1.3、高级特性1.Inherited —— 注解继承限制仅对类上的注解有效且只继承一级Inherited Retention(RetentionPolicy.RUNTIME) interface ParentAnno {} ParentAnno class Parent {} class Child extends Parent {} // Child 自动拥有 ParentAnno⚠️ 注意只对类继承有效接口/方法/字段不继承2. Repeatable —— 重复注解Java 8Retention(RetentionPolicy.RUNTIME) Repeatable(Authors.class) public interface Author { String name(); } Retention(RetentionPolicy.RUNTIME) public interface Authors { Author[] value(); } // 使用 Author(name Alice) Author(name Bob) public class Book {}实际字节码Authors({ Author(name Alice), Author(name Bob) }) class Book {}JVM 如何知道要“展开”Author 注解上标记了 Repeatable(Authors.class)反射 API 特殊处理// getAnnotationsByType(Author.class) 会自动展开 Author[] authors Book.class.getAnnotationsByAssistant(Author.class);3. 注解成员类型限制注解的成员只能是以下类型基本类型int,boolean 等StringClass枚举其他注解以上类型的数组不能是Object, List, 自定义对象等1.4、框架中的典型应用框架注解示例保留策略作用SpringComponent,AutowiredRUNTIME依赖注入、Bean 管理JPAEntity,ColumnRUNTIMEORM 映射JUnitTest,BeforeEachRUNTIME单元测试LombokData,BuilderSOURCE编译时生成代码SwaggerApiOperationRUNTIMEAPI 文档生成1.5、自定义注解自定义注解接口// 源码 Retention(RetentionPolicy.RUNTIME) public interface MyAnno { String value() default hello; int count() default 0; }编译后等价 Java 代码// MyAnno.class 反编译后 public interface MyAnno extends Annotation { String value(); // 注意没有 default int count(); }为什么没有 default默认值由注解使用处的字节码或反射 API在运行时提供不在接口中。步骤 1定义注解使用 interfaceimport java.lang.annotation.*; Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD, ElementType.TYPE}) // 可用在类和方法上 Documented // 注解会包含在 JavaDoc 中 public interface ApiVersion { String value() default 1.0; // 成员变量带默认值 boolean deprecated() default false; }步骤 2使用注解ApiVersion(value 2.0, deprecated true) public class UserService { ApiVersion(3.0) public void createUser() { ... } }步骤 3通过反射读取运行时// 读取类上的注解 ApiVersion classAnno UserService.class.getAnnotation(ApiVersion.class); System.out.println(classAnno.value()); // 输出: 2.0 // 读取方法上的注解 Method method UserService.class.getMethod(createUser); ApiVersion methodAnno method.getAnnotation(ApiVersion.class); System.out.println(methodAnno.value()); // 输出: 3.02、注解原理2.1、注解如何存储Java 编译器javac会将注解信息写入 .class 文件的属性表Attributes中。1. 类/方法/字段上的注解存在对应结构的 RuntimeVisibleAnnotations 属性中示例带注解的类MyAnno(value test, count 5) public class Demo {}字节码结构简化ClassFile { ... attributes_count: 2 attributes[0]: SourceFile attributes[1]: RuntimeVisibleAnnotations { ← 关键 num_annotations: 1 annotation { type_index: #MyAnno // 指向常量池 num_element_value_pairs: 2 element_value_pairs[0]: { namevalue, valuetest } element_value_pairs[1]: { namecount, value5 } } } }2. 保留策略决定是否写入字节码Retention是否写入.class属性名SOURCE不写入—CLASS写入RuntimeInvisibleAnnotationsRUNTIME写入RuntimeVisibleAnnotationsJVM 规范规定RuntimeVisibleAnnotations → 运行时可通过反射访问RuntimeInvisibleAnnotations → 仅工具可读如 ASM2.2、JVM 加载阶段注解如何进入内存当 JVM 加载 .class 文件时步骤 1解析常量池将 MyAnno 的全限定名存入运行时常量池步骤 2创建 java.lang.Class对象如果注解是 RUNTIME 策略JVM 会解析 RuntimeVisibleAnnotations 属性不立即创建注解实例而是保存原始数据name-value pairs将这些数据关联到 Class/Method/Field 对象的内部字段关键源码OpenJDK// java.lang.Class private volatile AnnotationData annotationData; // 注解数据懒加载 private AnnotationData getAnnotationData() { if (annotationData null) { // 从 JVMTI 或字节码解析注解 annotationData createAnnotationData(); } return annotationData; }注解是懒加载的只有第一次调用 getAnnotation() 时才解析2.3、反射读取原理当你调用MyAnno anno clazz.getAnnotation(MyAnno.class);JVM 并不会返回一个真实的MyAnno实例而是返回一个动态代理对象内部实现简化版// sun.reflect.annotation.AnnotationParser static A extends Annotation A annotationForMap( final ClassA type, final MapString, Object memberValues ) { return (A) Proxy.newProxyInstance( type.getClassLoader(), new Class?[] { type }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { // 1. 如果是 annotationType()返回 type if (method.getName().equals(annotationType)) return type; // 2. 否则从 memberValues 中取值 String member method.getName(); Object value memberValues.get(member); // 3. 处理默认值如果 value 为 null if (value null) { value method.getDefaultValue(); // ← 关键 } return value; } } ); }为什么用代理节省内存不需要为每个注解创建真实对象支持默认值通过method.getDefaultValue() 动态填充类型安全代理实现了目标注解接口2.4、default的实现机制问题默认值存在哪里不在注解接口中不在使用处的字节码中而是在注解定义的.class文件的AnnotationDefault属性中示例public interface MyAnno { String value() default hello; // 默认值 hello }字节码中的 AnnotationDefaultMethod: value() attributes[0]: AnnotationDefault { default_value: hello }反射读取时如何获取默认值// 当 memberValues 中没有 value 键时 Object defaultValue method.getDefaultValue(); // ← 从 AnnotationDefault 读取这就是为什么 method.getDefaultValue() 能返回默认值3、生命周期阶段3.1、生命周期Java 注解的生命周期分为三个阶段通过 Retention(RetentionPolicy.XXX)指定。如下所示保留策略RetentionPolicy生命周期能否被反射读取典型用途SOURCE仅存在于源码中编译后丢弃否Override, SuppressWarningsCLASS存在于 .class文件中JVM 加载时不加载到内存否默认值字节码分析工具如 LombokRUNTIME存在于.class 中JVM 运行时可通过反射读取是Spring, MyBatis, JUnit 等框架关键点只有Retention(RUNTIME)的注解才能在运行时通过getAnnotation()获取3.2、保留策略1. RetentionPolicy.SOURCE作用仅给编译器看编译完就扔例子Override public String toString() { ... }编译器检查你是否真的重写了父类方法生成的 .class 文件中没有Override2. RetentionPolicy.CLASS默认作用保留在字节码中但 JVM 不加载到运行时用途供字节码处理工具使用如 ASM、Lombok例子Lombok 的 DataData // 编译时生成 getter/setter运行时看不到这个注解 public class User { private String name; }3. RetentionPolicy.RUNTIME作用全程保留运行时可通过反射获取这是框架最常用的策略Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) public interface LogExecutionTime {} // 使用 LogExecutionTime public void process() { ... } // 反射读取 Method method obj.getClass().getMethod(process); if (method.isAnnotationPresent(LogExecutionTime.class)) { // 执行 AOP 逻辑 }4、注意事项1.推荐做法优先使用RUNTIME除非明确不需要运行时访问提供默认值减少使用者负担String value() default ;用Documented让注解出现在 API 文档中命名清晰如 EnableCaching 比CacheOn 更直观2.避免陷阱不要滥用注解过度使用会让代码难以理解注意性能反射读取注解有开销可缓存线程安全注解对象是不可变的天然线程安全参考文章1、一篇文章彻底明白重要概念——注解

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询