注解与反射
注解
什么是注解
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。放在Java源码的类、方法、字段、参数前的一种特殊“注释”:注释会被编译器直接忽略,注解则可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”。
内置注解
- @Override 检查该方法是否是重写方法
- @Deprecated - 标记过时方法
- @SuppressWarnings - 指示编译器去忽略注解中声明的警告
- @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
- @Documented - 标记这些注解是否包含在用户文档中
- @Target - 标记这个注解应该是哪种 Java 成员
- @Inherited - 标记这个注解是继承于哪个注解类
- @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
- @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
- @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次
其中 @Retention @Documented @Target @Inherited 为元注解(作用在其他注解上)
Annotation
我们来看一下源码
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
定义注解
import java.lang.annotation.*;
public class Hello {
@MyAnnotation(name = "qrrk")
public void sayHello(){
System.out.println("hello");
}
}
@Documented //添加到javadoc中
@Target(ElementType.METHOD) //指定MyAnnotation注解可以修饰什么
/*{
TYPE:类, 接口 (包括注解类型), 或者枚举
FIELD:字段声明(包括枚举常量)
METHOD:方法声明
PARAMETER:参数声明
CONSTRUCTOR:构造器声明
LOCAL_VARIABLE:局部变量声明
ANNOTATION_TYPE:
PACKAGE:注释类型声明
TYPE_PARAMETER:类型参数声明
TYPE_USE:类型使用
}*/
@Retention(RetentionPolicy.RUNTIME) //指定策略属性
/*{
SOURCE annotations are to be discarded by the compiler
CLASS Annotations are to be recorded in the class file by the compiler
but need not be retained by the VM at run time.
(This is the default behavior).
RUNTIME Annotations are to be recorded in the class file by the compiler
and retained by the VM at run time, so they may be read reflectively.
}*/
@interface MyAnnotation {
String name() default "";
}
判断某个注解是否存在于Class、Field、Method或Constructor:
Class.isAnnotationPresent(Class)
Field.isAnnotationPresent(Class)
Method.isAnnotationPresent(Class)
Constructor.isAnnotationPresent(Class)
反射
什么是反射
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。程序在运行期可以拿到一个对象的所有信息
一个类有多个组成部分,例如:成员变量、方法、构造方法等,反射就是加载类,并解剖出类的各个组成部分。
class类
以String类为例,当JVM加载String类时,它首先读取String.class文件到内存,然后,为String类创建一个Class实例并关联起来:
获取class
package com.qrrk;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Dog dog = new Dog();
Class c1 = dog.getClass();//460141958
Class c2 = Class.forName("com.qrrk.Dog");//460141958
Class c3 = Dog.class;//460141958
Class c4 = Integer.TYPE;
System.out.println(c1.hashCode()+"\n"+c2.hashCode()+"\n"+c3.hashCode());
}
}
class Dog{
String name;
Integer age;
public Dog() {
}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
实例化一个类的对象
Dog dog1 = (Dog) c1.newInstance();
Constructor constructor = c1.getConstructor(String.class,Integer.class);
Dog dog2 = (Dog) constructor.newInstance("qrrk", 3);
反射操作
//操作方法
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(dog1,"qrrk");
//操作属性
Field name = c1.getDeclaredField("name");
name.set(dog1,"小汪");
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~