自定义注解的步骤如下:
**1. 定义注解**
```java
/**
* 1. 注解使用@interface来声明
* 2. 修饰符只能是public
* 3. 自定义注解会自动继承java.lang.annotation.Annotaion接口
*/
//定义该注解只有在运行时起作用
@Retention(RetentionPolicy.RUNTIME)
//定义该注解可以用在类、接口、枚举、属性、方法上
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface CustomAnnotation {
/**
* 注解的属性规则
* 1. 注解只有属性,没有方法
* 2. 属性的类型可以是:8种基本数据类型、String、类、接口、注解、以及它们对应的数组
* 3. 属性可以通过default关键字来设定默认值
* 4. 如果你的注解只有一个属性,请用value关键字来命名
*/
String value() default ""; //虽然value()看似方法,但请注意它是一个属性
String description() default ""; // 提供默认值
int[] num() default 0;
String elementType() default "";
}
```
**2. 应用注解**
```java
@CustomAnnotation(description = "狗对象", elementType = "现在是用在类上", num = {1, 2})
public class Dog {
@CustomAnnotation(description = "狗的属性-品种", elementType = "现在是用在属性上")
private String verity;
@CustomAnnotation(description = "狗的属性-性别", elementType = "现在是用在属性上")
private String sex;
@CustomAnnotation(description = "狗的行为", elementType = "现在是用在方法上")
public void eat() {
System.out.println("狗喜欢吃骨头!");
}
}
```
**3. 根据反射获取注解**
```java
@Test
public void test() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
//反射Dog类
Class<Dog> cls = (Class<Dog>) Class.forName("com.learn.annotation01.model.Dog");
//判断该类是否使用注解CustomAnnotation
if (cls.isAnnotationPresent(CustomAnnotation.class)) {
//获取Dog类上的注解
CustomAnnotation customAnnotation = cls.getAnnotation(CustomAnnotation.class);
System.out.println("description: " + customAnnotation.description()
+ ", elementType: " + customAnnotation.elementType());
//description: 狗对象, elementType: 现在是用在类上
}
//获取Dog类的所有属性
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
//判断当前属性是否使用注解CustomAnnotation
if (field.isAnnotationPresent(CustomAnnotation.class)) {
//获取当前属性上的注解
CustomAnnotation customAnnotation = field.getAnnotation(CustomAnnotation.class);
System.out.println("description: " + customAnnotation.description()
+ ", elementType: " + customAnnotation.elementType());
//description: 狗的属性-品种, elementType: 现在是用在属性上
//description: 狗的属性-性别, elementType: 现在是用在属性上
}
}
//获取Dog类的eat方法
Method eatMethod = cls.getDeclaredMethod("eat");
//判断当前方法是否使用了注解
if (eatMethod.isAnnotationPresent(CustomAnnotation.class)) {
CustomAnnotation customAnnotation = eatMethod.getAnnotation(CustomAnnotation.class);
System.out.println("description: " + customAnnotation.description()
+ ", elementType: " + customAnnotation.elementType());
//description: 狗的行为, elementType: 现在是用在方法上
}
}
```
- 网络通信
- 网络协议
- 端口和套接字
- TCP网络程序
- UDP网络程序
- 多线程聊天室
- 多线程
- 线程相关概念
- 线程实现方式
- 中断线程
- 线程生命周期
- 线程优先级
- 优先级规则
- 案例演示
- 线程同步机制
- 线程同步机制
- synchronized关键字
- ReentrantLock类
- Condition类
- 监视器概念
- volatile关键字
- final变量
- 死锁
- 线程局部变量
- 读/写锁
- 原子类
- 阻塞队列
- 工作规则
- 案例演示
- 常用阻塞队列
- 线程安全集合
- 高效的映射/集/队列
- 并发集视图
- 写数组的拷贝
- Arrays类的并行数组算法
- 同步包装器
- Callable与Future
- 执行器
- 线程池
- 预定执行
- 控制任务组
- Fork-Join框架
- 同步器
- 同步器
- 信号量
- CountDownLatch类
- CyclicBarrier类
- Exchanger类
- SynchronousQueue类
- 线程与Swing
- Swing与线程问题
- 两个原则
- Swing工作线程
- 单一线程规则
- 文件IO
- File类
- 文件输入输出
- ZIP压缩文件
- 集合
- 集合框架
- 集合接口
- 集合实现类
- 线程安全集合
- 集合算法
- 迭代器
- 集合排序
- JDBC
- JDBC是什么
- JDBC-ODBC桥
- JDBC驱动程序类型
- JDBC常用类与接口
- 数据库操作
- 连接数据库
- 增/删/改/查/预处理
- 事务
- 批处理
- commons-dbutils工具
- 安全问题
- Jedis
- 使用Jedis操作Redis数据库
- JSON转换
- 使用连接池
- 案例
- 单例破坏
- 单例定义
- 单例实现方式
- 懒汉式实现单例
- 饿汉式实现单例
- 单例破坏
- 类的单例破坏
- 枚举的单例破坏
- 克隆
- 克隆是什么
- 浅克隆
- 深克隆
- 注解
- 注解是什么
- 三大注解
- 内置注解
- 元注解
- 自定义注解
- NIO
- 相关概念
- BIO/NIO/AIO
- 多线程编程
- 线程同步
- 线程通信
- NIO
- NIO三大核心组件
- NIO网络编程
- NIO文件读写
- AIO
- Java8新特性
- Lambda表达式
- 方法引用
- 函数式接口
- 默认方法
- 什么是默认方法
- 默认方法语法格式
- 多个同名的默认方法问题
- 静态默认方法
- 默认方法实例
- Stream
- Stream是什么
- Stream示例
- Optional容器
- 新的日期时间API
- Base64
- SPI
- SPI是什么
- SPI与API的区别
- 常见场景
- 使用SPI需遵循的约定
- SPI使用步骤