当前位置: 首页 > news >正文

JavaSE学习——类加载器和注解

类加载器

BootClassLoader:加载JDK核心模块

PlatformClassLoader:加载平台相关的模块(扩展类),BootClassLoader是父类

AppClassLoader:加载Main,PlatformClassLoader是父类

一般来说,比如一个Main文件要被AppClassLoader加载,会先向上传递给PlatformClassLoader,再向上传递给BootClassLoader加载,上层加载不了再下一层传递。这样做是为了安全考虑(防止自己写一个java.lang.String替换掉 JDK 核心 String)

注解

@Override是注解,有一定的含义。注解也是一个类,可以被标注在任何地方,部分可以保留到运行时。注解 = 给类、方法、变量贴个 “标签”。它本身不干活,只是标记;需要反射去读取这个标签,然后做相应逻辑。

预设注解

JDK预设了下面的注解,作用于代码:

@Override用于检查这个方法是否重写了父类,如果变成publicvoidequals() { }就会编译器报错

public class Main { public static void main(String[] args){ }@Overridepublic boolean equals(Object obj) { return super.equals(obj); } }

@Deprecated用来标注某个方法是“过时的”,不推荐用。这个只是一个警告的作用,且会保留到运行时(.class文件里也会有)

@SuppressWarnings用于忽略一些不需要的警告,比如在底层实现一个arr数组的时候使用的是Object对象创建,在实际使用的时候是泛型T,这个时候比如get方法返回的是T泛型的内容需要强制类型转换,这个时候编译器会警告,只要使用@SuppressWarnings就不会警告了

public class Main<T> { Object[] arr; public static void main(String[] args){ } @SuppressWarnings("unchecked") public T get(int index){ return(T)arr[index]; } }

@FunctionalInterface接口用于表明是一个函数式接口(匿名函数),比如下面的代码使用了它的一个匿名函数,查看Supplier会发现有注解:

Supplier<String> supplier = ()->"";

元注解

“贴在注解上的注解”,专门用来控制注解的行为。主要有4 个标准元注解:

@Target规定注解能贴在什么地方(FIELD表示可以在变量上打标签)

@Retention规定注解保留到哪个阶段,Retention里面的参数有RetentionPolicy.SOURCE,CLASS,RUNTIME这三个。

@Documented标记这些注解是否包含在用户文档里

@Inherited让子类继承父类上的注解

@Repeatable代表一个注解可以打多次标签

举两个例子:

以override为例,Retention里面的参数RetentionPolicy.SOURCE代表在源代码里面保存,.class文件里面就没有了

自定义一个注解

先来定义一个简单的注解,限制注解保留到运行时且可以在类和方法上打这个注解的标签

import static java.lang.annotation.ElementType.*; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ TYPE, METHOD }) public @interface test { }
@test public class Main { @test public static void main(String[] args){ } }

使用这个注解

比如在注解里面定义一个方法,需要在方法后面加括号,且传入参数使用,这个参数不能是变量,只能是一个枚举类或者一个直接的值:

public @interface test {String value();//注解的属性要加括号 }
@test("lhw")public class Main { privatefinalstatic String str = "hxl"; @test(str) public static void main(String[] args){ } }

此外,如果不传参数使用,那个注解必须有默认值:

public @interface test { String value()default "a"; //注解的属性要加括号 }

数组类型的参数和使用(一个元素的时候,可以直接填值):

public @interface test { String[] value()default {"1","2"}; //注解的属性要加括号 }
@test({"lhw"}) public class Main { @test("hxl") public static void main(String[] args){ } }

如果注解里面有多个属性的时候,需要在使用的时候加上属性名称和值:

public @interface test { String[]value() default {"1","2"}; //注解的属性要加括号 intage(); }
@test(value = {"lhw"},age = 1) public class Main { @test(value ="hxl",age =2) public static void main(String[] args){ } }

因为注解也是一个类,所以也可以作为一个参数去使用:

public class Main { @test(value = "hxl",age = 2) public static void main(String[] args){ }private static void test(test t){ int a = t.age(); }}

但是注解类的实例化对象只能通过反射去拿到,不允许直接实例化。

反射获取注解

使用getAnnotation方法去获取一个注解的实例对象,需要使用到注解对应类的反射对象。

public @interface test { String value(); //注解的属性要加括号 }
@test(value = "hxl")public class Main { public static void main(String[] args){ Class<Main> mainClass =Main.class; test annotation = mainClass.getAnnotation(test.class); System.out.println(annotation.value()); } }

上面是关于类上的注解,还有关于方法的注解的获取:

public class Main { @test(value = "hxl") public static void main(String[] args) throws NoSuchMethodException { Class<Main> mainClass =Main.class;Method main = mainClass.getMethod("main", String[].class); test annotation = main.getAnnotation(test.class); System.out.println(annotation.value()); } }

关于参数的注解:

public class Main { public static void main(@test(value = "hxl") String[] args) throws NoSuchMethodException { Class<Main> mainClass = Main.class; Method main = mainClass.getMethod("main", String[].class); Annotation[][] parameterAnnotations = main.getParameterAnnotations(); System.out.println(Arrays.deepToString(parameterAnnotations)); } }

http://www.jsqmd.com/news/684295/

相关文章:

  • 解决STM32H723双CAN通信的MessageRAM冲突:FDCAN1与FDCAN2独立滤波与FIFO配置指南
  • SPE(单对以太网):重塑工业与汽车网络的轻量化连接方案
  • 技术深度解析:Beyond Compare 5 密钥生成机制与实战部署指南
  • TS-182快速打通Modbus干变温控箱与PROFINET PLC连---简化集成步骤 提升设备运行可靠性
  • nli-MiniLM2-L6-H768部署案例:国产昇腾910B平台适配与性能实测
  • 撕下“全能模型”的伪装:Anthropic 官方揭秘长周期 Agent 的“脚手架工程”与抗焦虑指南
  • 三步法高效配置WarcraftHelper:魔兽争霸III游戏优化与性能提升完整指南
  • 按键伤企频上热搜,我用这套舆情监测系统守住了公司品牌
  • Docker配置错误导致PLC通信中断?——工业现场紧急回滚的3个不可逆配置陷阱
  • Docker镜像层存储机制全解,从aufs到overlay2的演进真相及企业级迁移 checklist(含生产环境回滚预案)
  • Neo4j 超详细入门
  • 【路由原理与路由协议-BGP边界网关协议】
  • 阳澄湖大闸蟹礼卡怎么选怎么兑?避坑攻略看这里
  • 网络协议TCP-IP深入解析
  • 《识质存在(PRAGMATA)》v1.0 十二项修改器
  • 端侧AI爆发:让手机、电脑、汽车自己思考
  • 告别FileNotFoundError:Python文件路径检查与异常处理实战指南
  • 租赁商城小程序源码|ThinkPHP+UniApp双端开发|含手机租赁系统与完整部署教程
  • 微服务配置管理进阶
  • Nano-Banana场景应用:统一品牌视觉,建立系列化产品拆解档案
  • 别再只调sklearn了!用mlxtend给你的机器学习项目加个‘瑞士军刀’(附实战代码)
  • 分层聚类怎么做:SPSSAU软件操作步骤与结果解读
  • 3分钟学会FakeLocation:终极Android应用级虚拟定位完全指南
  • UVM验证中的‘幽灵任务’:如何优雅处理objection未结束导致的PH_TIMEOUT
  • 无人机飞控、游戏角色旋转:聊聊卡尔丹角顺序(Yaw-Pitch-Roll)的那些坑
  • D3KeyHelper:暗黑破坏神3智能自动化助手完全指南
  • 告别“面霸”与“误筛”:国内主流十大AI面试产品谁才是真正的“火眼金睛”?
  • 第 6 篇 Agent Skills 完全指南:从入门到进阶,手把手教你打造 Claude Skills
  • 如何快速掌握AMD Ryzen终极调试工具:SMUDebugTool完整使用指南
  • 基于视觉识别鱼肚鱼背相对位置的双路电机驱动控制系统设计