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

Java学习打卡-Day25-注解和反射、Class类

注解(JDK5引入)

什么是注解?
  • Java注解(Annotation),也叫元数据。一种代码级别的说明,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
作用
  • 不是程序,但能对程序做出解释。
  • 还可以被其他程序读取。
格式
  • @+注释名。还可以添加一些参数。
  • 如:@SuppressWarnings(value="unchecked")
如何使用
  • 可以附加在 package、 class、 method、 field 等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问。
内置注解(预定义的注解)
  • 以下注解都是java.lang包下的,也就是Java提供的基础注解,我们在使用的时候是不需要导包的!
    • @Override:标记一个方法,该方法打算重写超类中的某一方法。如果被标记的方法并没有实际重写超类中的方法,则编译器会发出错误警告。
    • @Deprecated:可以用在方法,属性,类上,表示不推荐程序员使用,因为有风险或存在更好的选择。
    • @SuppressWarnings:取消一些编译器产生的警告,需要添加参数才能正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了。
    • @SafeVarargs:在声明具有模糊类型(如泛型)的可变参数构造函数或方法时,Java编译器会报unchecked警告。鉴于这些情况,如果程序员断定声明的构造函数和方法的主体不会对其varargs参数执行潜在的不安全的操作,可使用@SafeVarargs进行标记,这样的话,Java编译器就不会报unchecked警告。注意:方法必须是由static或者final修饰的方法!只能用于标记构造函数和方法!只能用在可变长参数的方法上!
      @SafeVarargs
      public static <T> T useVarargs(T... args) {  
          return args.length > 0 ? args[0] : null;  
      } 
      
    • @FunctionalInterface:被@FunctionalInterface注解标记的类型表明这是一个函数接口。从概念上讲,函数接口只有一个抽象方法。一旦不满足函数接口,就会报错。
元注解
  • 以下注解都来源于java.lang.annotation,元注解只能用来注解其他注解。
    • @Target:用于描述注解的使用范围。如@Target({ElementType.TYPE, ElementType.METHOD}),就代表着其修饰的注解可以用在 接口、类、枚举、注解上、还可以用在方法上!

      @Target(ElementType.TYPE) —— 接口、类、枚举、注解
      @Target(ElementType.FIELD) ——字段、枚举的常量
      @Target(ElementType.METHOD) —— 方法
      @Target(ElementType.PARAMETER) —— 方法参数
      @Target(ElementType.CONSTRUCTOR) —— 构造函数
      @Target(ElementType.LOCAL_VARIABLE) —— 局部变量
      @Target(ElementType.ANNOTATION_TYPE) —— 注解
      @Target(ElementType.PACKAGE) —— 包

    • @Retention:用于描述注解的生命周期,表示需要在什么级别保存该注解信息。

      RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;也就是编译时有效。
      RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;加载时被抛弃。
      RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;一直有效!

    • @Documented:说明该注解将被包含在javadoc中。如果一个注解@A被@Documented标注,那么被@A修饰的类,生成文档时,就会显示该注解@A。

    • @Inherited:如果一个类用上了@Inherited修饰的注解@A,那么其子类也会继承这个注解@A。

自定义注解
  • 使用关键字@interface来声明一个注解。
  • 访问修饰符必须为public,不写默认为pubic。
  • 配置参数:返回类型+参数名+()。返回类型只能是基本类型、Class、String、enum。
  • 注解参数必须要有值,可以通过default来声明参数的默认值。如果没有默认值,则必须赋值。
  • 如果只有一个参数成员,一般参数名为value。

反射

什么是反射?
  • Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。Java注解一旦离开了反射就什么都不是!!!
  • 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了完整的类的结构信息。这个对象就像一面镜子,透过这个镜子我们可以看到类的结构,所以我们形象的称之为反射。
  • Class对象照镜子后可以得到的信息:某个类的属性、方法、构造器,实现了哪些接口。
功能
  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时获取泛型信息。
  • 在运行时调用任意一个对象的成员变量和方法。
  • 在运行时处理注解。
  • 生成动态代理。
优缺点
  • 优点:体现出灵活性,可以实现动态创建和使用对象。
  • 缺点:对性能有影响,使用反射基本上是一种解释操作,这类操作总是慢于直接执行相同的操作。
Class 类
  • Class 类就是一个类,同样继承自Object类。
  • Class 对象不是new出来的,而是由JVM创建的,通过ClassLoader加载某类的Class对象。我们只能通过反射得到。
  • 某个类在JVM中只能有一个Class对象,因为类只加载一次。
  • 一个Class对象对应的是加载到JVM的一个.class文件
  • Class类是反射的根源,任何你想动态加载、运行的类,唯有先获得对应的Class对象。通过Class对象可以得到一个类的完整结构,借助一系列API。
Class 类方法
String str ="com.hspedu.reflection.Person";
//获取到Class对象,?表示不确定的java类型
Class<?> clazz = Class.forName(str);

System.out.println(clazz);//输出该clazz是哪个类的Class对象->class com.hspedu.reflection.Person
System.out.println(clazz.getName());//全类名->com.hspedu.reflection.Person
System.out.println(clazz.getPackage().getName());//包名->com.hspedu.reflection
System.out.println(clazz.getClass());//运行类型->class java.lang.Class

Object obj= clazz.newlnstance(); //通过反射创建对象
Field field = clazz.getField("name"); //通过反射获取属性(只能获取公有)
System.out.println(field.get(obj));//输出

field.set(obj,"hspedu"); // 通过反射给属性赋值
System.out.println(field.get(obj));//输出

Field[] fields = clazz.getFields();//通过反射获取所有属性(只能获取公有)
for(Field f : fields){
	System.out.println(f.getName());//输出所有属性的名称
	System.out.println(f.get(obj));//输出所有属性的值
}
Class 对象的获取方式
  • 编译阶段:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException。如:Class cls1 = Class.forName( "java.lang.Cat"); 应用场景:多用于配置文件,读取类全路径,加载类。
  • 类加载阶段:已知具体的类,通过类的.class获取,该方式最为安全可靠,程序性能最高。如:Class cls2 = Cat.class; 应用场景:多用于参数传递,比如通过反射得到对应构造器对象。
  • 运行阶段:已知某个类的实例,调用该实例的getClass()方法获取Class对象。如:Class cls3 = 对象.getClass();应用场景:通过创建好的对象,获取Class对象。
  • 通过类加载器:(1)先得到类加载器 ClassLoader classLoader = 对象.getClass().getclassLoader();(2)通过类加载器得到Class对象Class cls4 = classLoader.loadclass(classAllPath);
  • 对于基本数据类型:Class cls5 = 基本数据类型.class;
  • 对于基本数据类型的包装类:Class cls6 = 包装类.TYPE;

相关文章:

  • 除了 `task_type=“SEQ_CLS“`(序列分类),还有CAUSAL_LM,QUESTION_ANS
  • 分布式系统-脑裂,redis的解决方案
  • 2025年蓝桥杯B组题解
  • 深度剖析:架构评估的常用方法与应用
  • 当Browser Use遇见A2A:浏览器自动化与智能体协作的“冰与火之歌“
  • WindowsPE文件格式入门06.手写最小PE
  • 向上取整,向下取整和四舍五入
  • 安卓AssetManager【一】- 资源的查找过程
  • 【Java学习】Spring AI集成指南
  • 深入理解 v-if 指令及其使用方法
  • C++在Linux上生成动态库并调用接口测试
  • 七、Qt框架编写的多线程应用程序
  • JDK的卸载与安装
  • 【JavaScript——页面渲染】课程列表(蓝桥杯真题-2457)【合集】
  • 《从零搭建Vue3项目实战》(AI辅助搭建Vue3+ElemntPlus后台管理项目)零基础入门系列第十二篇(完结篇):数据统计功能实现
  • Java高性能并发利器-VarHandle
  • 【sgSpliter】自定义组件:可调整宽度、高度、折叠的分割线
  • 【技术派部署篇】云服务器部署技术派
  • jeecg启动所需要安装的软件
  • GitHub Desktop 推送报错 Authentication Failed 身份验证失败
  • wordpress做购物网站/学新媒体运营最好的培训学校
  • 贵阳手机网站建设/seoul是什么意思
  • 开贴纸网站要怎么做/win10优化大师好用吗
  • wordpress主题 网站大全/今日国内新闻头条大事
  • 今日新开网站/百度统计app下载
  • 苏州营销型网站/百度人工投诉电话是多少