📚
handbook
  • Introduction
  • 1.前言
    • 前言
    • 鸣谢
  • 2.环境篇
    • 工具部署和使用
      • 团队协作工具
        • Confluence
      • 开发工具
        • Docker
          • 镜像导入导出
          • 安装
        • Docker Compose
      • 持续集成工具
        • Gerrit
        • Sonarqube
          • 分析参数设定
          • Prerequisite
          • 服务端设置
        • Ubuntu Ci Deploy
          • ubuntu使用docker部署jenkins+sonarqube
        • 持续集成部署
      • 文本编辑工具
        • Gitbook相关注意事项
        • Markdown快速入门
      • 版本控制
        • Git
          • 1.基础
            • Git基础(一)
            • Git基础(二)
            • Git基础(三)
            • Git基础(四)
            • Git基础(五)
          • 2.命令详解
            • 命令速查
          • 3.进阶技巧
            • git技巧
      • 自动化测试工具
        • Appium
          • capability参数配置
          • 安装
          • 简介
      • 项目管理工具
        • Jira
    • 开发环境配置
      • 通用
        • Homebrew安装与使用
        • Git服务器添加SSH Key
        • koroFileHeader使用
        • nodejs与npm的安装
        • npm更换国内源
        • pip使用相关
        • PostgreSQL安装与使用
        • proxychain安装与使用
        • shell配置环境变量
        • snapd安装与使用
        • terminal走代理
    • 快捷键速查
      • shell常用快捷键
  • 3.语言篇
    • C
      • 代码规范
      • 语言技巧
    • Cpp
      • 代码规范
      • 基础知识
        • 理解C++中的左值和右值
      • 语言技巧
        • 并发编程
          • 简单的线程池实现
    • Golang
      • 代码规范
        • 避免使用转义字符串
        • 避免参数语义不明确
        • 嵌套式结构体
        • 函数的分组与顺序
        • 函数命名
        • 声明一致性
        • 导入别名
        • 使用字段名初始化结构体
        • 本地变量声明
        • map初始化
        • nil用法
        • 包命名
        • 命名Printf样式的函数
        • 减少嵌套
        • 缩小变量作用域
        • struct引用初始化
        • 测试表声明
        • 顶层变量声明
        • 不必要的else
      • 环境配置
        • 代码检查格式化工具
          • Go Fmt
          • Goimports
          • Golint
          • Go Vet
        • go mod详解
        • golang安装
        • Golang开发环境
        • Troubleshooting
      • 语言技巧
        • 如何分包
    • Java
      • 代码规范
      • 语言技巧
        • 注解编程
        • 动态代理
    • Js
      • 语言技巧
        • Rollup
    • Kotlin
      • 基础知识
        • 写给开发者Kotlin指引(一)
        • 写给开发者Kotlin指引(二)
    • Python
      • 语言技巧
        • Best Practice Of Python S Project Structure
  • 4.规范篇
    • Git message规范
  • 5.技术篇
    • Android技术
      • Hook
        • EdXposed例子
        • Android 10 上安装Magisk和EdXposed
      • Tinker
        • 1.Tinker及其使用
      • 准备
        • ADB连接设备步骤及注意事项
        • adb连接设备
        • aosp编译
      • 基础
        • Binder接口调用的鉴权方法
        • Make 及 Android 编译系统介绍
        • 使用Content Provider为其他应用提供数据
      • 源码阅读
        • Framework源码分析 Looper Handler
        • Framework源码分析 启动流程 ServiceManager的初始化
        • Framework源码分析 启动流程 Zygote启动SystemServer
    • JS Bridge
      • JSBridge初探
    • Kernel技术
      • kallsyms子系统
    • Test技术
      • 软件测试
        • jnekin+sonar 部署 问题总结
        • 性能测试基础
        • 软件测试的背景
        • 测试基础
        • 测试人员的核心竞争力
    • 操作系统原理
      • 处理器如何实现原子操作
Powered by GitBook
On this page
  • 注解
  • 元注解
  • 举个栗子
  • 注解编程
  • 举个栗子
  • 结果

Was this helpful?

  1. 3.语言篇
  2. Java
  3. 语言技巧

注解编程

注解

注解是JDK 1.5之后引入的一个语言特性,一般用于对类,方法,属性的修饰。主要的目的在于简化java中的配置,用注解代替配置。 下面是几个Java底层内置的几个注解

  • @Override: 只适用于方法,表示重写父类中的方法

  • @Deprecated: 表示某各类或方法已过时

  • @SuppressWarnings: 抑制编译器的警告

元注解

所谓元注解就是用于修饰注解的注解 @Target:指定注解使用的位置,@Target 中有一个 ElementType 数组,因此被 @Target 注解修饰的注解可以在多个位置上使用。下面是 ElementType 枚举中的一些属性(只列举一些常用的属性)

  • TYPE:能在类、接口(包含注解类型)和枚举类型上使用

  • FIELD:只能在属性上使用

  • METHOD:只能在方法上使用

@Retention:用于表示该注解可以保留的作用域,@Retention 注解包含一个 RetentionPolicy 属性,通过这个属性来设置注解的保留域。RetentionPolicy 是一个枚举,其中有 3 个属性,如下

  • SOURCE:只在源代码中显示,在编译成 .class 文件的时候会被丢弃

  • CLASS:编译器会把注解记录在 .class 文件中,当程序运行时,虚拟机不会保留该注解

  • RUNTIME:当程序运行时,也会被保留,因此可以通过反射技术获取该类型注解中的一些信息

@Documented:被该注解修饰的类可以使用 javadoc 工具生成文档,这里就不演示了

@Inherited:如果子类继承了被 Inherited 修饰的注解,则子类也自动拥有父类中的注解

举个栗子

package java.lang;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

/**
 * A program element annotated @Deprecated is one that programmers
 * are discouraged from using, typically because it is dangerous,
 * or because a better alternative exists.  Compilers warn when a
 * deprecated program element is used or overridden in non-deprecated code.
 *
 * @author  Neal Gafter
 * @since 1.5
 * @jls 9.6.3.6 @Deprecated
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

上面是Deprecated注解的实现,几个元注解的实际含义如下:

  • 表示可以被生成文档

  • 在程序运行时也会被保留

  • 可以使用在构造器,属性,方法,类或接口,包上等

注解编程

注解编程其实就是使用注解的特性进行编程的一个技巧,主要包含两个核心点:注解的定义,反射判断 注解的定义就是定义自己需要使用的注解 反射判断表示在适当的实际反射获取注解的值进行相应逻辑的处理

举个栗子

写一个通过注解自动生成SQL查询语句的例子

[src/anotations/Table.java]

package anotaions;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}
[src/anotations/Column.java]

package anotaions;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}
[src/Student.java]

import anotaions.Column;
import anotaions.Table;

@Table("student")
public class Student {
    @Column("id")
    private int id;
    @Column("user_name")
    private String username;
    @Column("age")
    private int age;
    @Column("city")
    private String city;
    @Column("phone")
    private String phone;

    public int getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public int getAge() {
        return age;
    }

    public String getCity() {
        return city;
    }

    public String getPhone() {
        return phone;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}
[src/DBDriver.java]

import anotaions.Column;
import anotaions.Table;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class DBDriver {
    public static String query(Student student) throws Exception {
        StringBuilder sb = new StringBuilder();
        Class<?> clazz = student.getClass();
        boolean tableAnnoExits = clazz.isAnnotationPresent(Table.class);
        // 判断 class 对象上是否有 @Table 注解
        if (!tableAnnoExits) {
            return null;
        }
        // 获取 @Table 注解中的表名,拼接 SQl
        Table table = clazz.getAnnotation(Table.class);
        String tableName = table.value();
        sb.append("SELECT * FROM " + tableName + " WHERE 1 = 1");

        // 获取 class 对象中的所有字段并遍历
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            boolean fieldAnnoExits = field.isAnnotationPresent(Column.class);
            // 判断字段上是否含有 @Column 注解
            if (!fieldAnnoExits) {
                continue;
            }
            // 获取注解中的字段名
            Column column = field.getAnnotation(Column.class);
            String columnName = column.value();
            // 通过 get() 方法获取传入的字段值
            String fieldName = field.getName();
            String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase()
                    + fieldName.substring(1);
            Method method = clazz.getMethod(getMethodName);
            Object fieldValue = method.invoke(student);

            if (fieldValue == null
                    || (fieldValue instanceof Integer && (Integer)fieldValue == 0)) {
                continue;
            }
            // 接着拼接 SQL 语句
            sb.append(" AND ").append(columnName).append(" = ");
            if (fieldValue instanceof String) {
                sb.append("'").append(fieldValue).append("'");
            } else if (fieldValue instanceof Integer) {
                sb.append(fieldValue);
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        Student student1 = new Student();
        student1.setUsername("张三");
        student1.setAge(18);
        student1.setCity("hangzhou");
        String s1 = query(student1);
        System.out.println(s1);

        Student student2 = new Student();
        student2.setUsername("李四");
        student2.setPhone("12345678977");
        String s2 = query(student2);
        System.out.println(s2);
    }
}

结果

Previous语言技巧Next动态代理

Last updated 4 years ago

Was this helpful?

结果