java注解的详解-适合java初学者

来源:互联网 发布:淘宝网天猫童鞋 编辑:程序博客网 时间:2024/05/17 05:02

概念:
java注解是jdk1.5 引入的新概念,其实注解是对java类的特殊标记,这些标记可以在编译、类加载、运行时这个三个阶段给读取,并执行相应的处理。
学会注解好处:
注解使用非常广泛,很多java框架【spring,hibernate,struts2】的配置都使用注解,如果你不先了解注解的用法,那么你在用这些java框架时你最多只会用,如果需要让你理解其底层的原理,剖析其源代码,你是做不到的。
常见的注解

  • jdk自带注解:

    限定重写父类方法 @Override
    标记已过时 @Deprecated
    抑制编译器警告 @SuppressWarnings

  • spring框架注解:
    springmvc 的web层注解@Controller
    spring 的bean注入 @Autowired

    注解的分类
    源码注解:注解只在源码中存在,编译成class文件后就不存在了
    编译时注解:在class文件中是存在的,比如jdk自带的注解都是编译时注解
    运行时注解:在运行时存在,会对程序的运行逻辑产生影响,一般框架 提供给开发者使用的都是自定义注解,我们开发者平时写的注解大多也是使用运行时注解。
    自定义注解的语法
    这里写图片描述

实例
下面以一个实例讲解注解的用法以及注解的用途
背景描述:
通常开发人员在数据库表设计时,会将一些字典数据以编码的形式存入在表字段中;日期格式为了方便计算,一般都以时间戳的类型存储,因此,前端在做数据展示时需要,需要将数据从数据库中读取并且通过程序按照一定的逻辑翻译成正常的数据格式展示。

下面以代码直接讲解传统的做法以及使用注解的方式的做法
传统做法

  1. 创建人员实体类
package com.zjc.anno.test1;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;/** *   *  传统做法,不使用注解 * */public class Person {    private String name;    private String birthday;    private String sex;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    //假设数据库里存放的数据是时间戳,传统的获取生日的方法是这样获取的    public String getBirthday() {        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");        return df.format(new Date(Long.parseLong(birthday)));    }    public void setBirthday(String birthday) {        this.birthday = birthday;    }    //假设数据库里关于性别的的值得存储是 0代表 男, 1 代表女 ,则传统的写法是这样的    public String getSex() {        if ("0".equals(sex)) {            return "男";        }        else if ("1".equals(sex)) {            return "女";        }        else{            return sex;        }    }    public void setSex(String sex) {        this.sex = sex;    }   }
  1. 创建动物实体类
package com.zjc.anno.test1;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;/** *   *  传统做法,不使用注解 * */public class Animal {    private String name;    private String birthday;    private String sex;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    //假设数据库里存放的数据是时间戳,传统的获取生日的方法是这样获取的    public String getBirthday() {        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");        return df.format(new Date(Long.parseLong(birthday)));    }    public void setBirthday(String birthday) {        this.birthday = birthday;    }    //假设数据库里关于性别的的值得存储是 0代表 男, 1 代表女 ,则传统的写法是这样的    public String getSex() {        if ("0".equals(sex)) {            return "男";        }        else if ("1".equals(sex)) {            return "女";        }        else{            return sex;        }    }    public void setSex(String sex) {        this.sex = sex;    }}
  1. 创建展示类
package com.zjc.anno.test1;public class PersonTest1 {    public static void main(String[] args) {        Person p = new Person();        p.setName("James Zheng");        p.setSex("0");        p.setBirthday("1304854541123");        System.out.println("姓名:"+p.getName());        System.out.println("生日:"+p.getBirthday());        System.out.println("性别:"+p.getSex());        System.out.println("------------------------");        Animal animal = new Animal();        animal.setBirthday("142234545543");        animal.setName("pipi");        animal.setSex("1");        System.out.println("姓名:"+animal.getName());        System.out.println("生日:"+animal.getBirthday());        System.out.println("性别:"+animal.getSex());    }}

程序输出结果:

姓名:James Zheng 生日:2011-05-08 性别:男

姓名:pipi 生日:1974-07-05 性别:女

使用注解的方式

创建注解类

package com.zjc.anno.test2;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.METHOD,ElementType.FIELD})//表示这个注解类的注解可以用在类方法或者类成员变量上@Retention(RetentionPolicy.RUNTIME) //表示这个注解是运行时注解@Inherited  //表示使用了此注解的类,这个注解在其子类上也生效@Documentedpublic @interface DicAnno {       //注解的字段,日期转换格式设置    String pattern()default "yyyy-MM-dd HH:mm:SS";      String type();}

基于注解的人员实体类

package com.zjc.anno.test2;/** *   *  使用注解的做法 * */public class Person {    private String name;    @DicAnno(type="date",pattern="yyyy-MM-dd")     private String birthday;  //使用注解,直接通过注解表示当前的字段要翻译成日期格式    @DicAnno(type="sex")     private String sex;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getBirthday() {        return birthday;    }    public void setBirthday(String birthday) {        this.birthday = birthday;    }    public String getSex() {            return sex;    }    public void setSex(String sex) {        this.sex = sex;    }}

通过注解的方式创建动物实体类

package com.zjc.anno.test2;/** *   *  使用注解的做法 * */public class Animal {    private String name;    @DicAnno(type="date",pattern="yyyy-MM-dd")     private String birthday;//使用注解,直接通过注解表示当前的字段要翻译成日期格式    @DicAnno(type="sex")     private String sex;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getBirthday() {        return birthday;    }    public void setBirthday(String birthday) {        this.birthday = birthday;    }    public String getSex() {            return sex;    }    public void setSex(String sex) {        this.sex = sex;    }}

最关键的一步,编写注解的解析类

package com.zjc.anno.test2;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;public class AnnotationParse {    public static void parse(Object obj) throws Exception{        Class objClazz = obj.getClass();        Field [] fs = objClazz.getDeclaredFields();        for (Field f : fs) {            if (f.isAnnotationPresent(DicAnno.class)) {                DicAnno anno=f.getAnnotation(DicAnno.class);                f.setAccessible(true);                //处理性别的字典翻译的处理逻辑                if (anno.type().equals("sex")) {                    String sex = (String) f.get(obj);                    if ("0".equals(sex)) {                        f.set(obj, "男");                    }else if("1".equals(sex)) {                        f.set(obj, "女");                    }                }                //处理日期的翻译逻辑                if (anno.type().equals("date")) {                    String pattern = anno.pattern();                    String date = (String) f.get(obj);                    DateFormat df = new SimpleDateFormat(pattern);                    f.set(obj, df.format(new Date(Long.parseLong(date))));                }            }        }    }}

通过注解的方式的结果展示类

package com.zjc.anno.test2;public class PersonTest2 {    public static void main(String[] args) throws Exception {        Person p = new Person();        p.setName("James Zheng");        p.setSex("0");        p.setBirthday("1304854541123");        //这里必须调用这个方法,注解才会生效        AnnotationParse.parse(p);        System.out.println("姓名:"+p.getName());        System.out.println("生日:"+p.getBirthday());        System.out.println("性别:"+p.getSex());    System.out.println("------------------------");        Animal animal = new Animal();        animal.setBirthday("1422345455431");        animal.setName("pipi");        animal.setSex("1");        //这里必须调用这个方法,注解才会生效        AnnotationParse.parse(animal);        System.out.println("姓名:"+animal.getName());        System.out.println("生日:"+animal.getBirthday());        System.out.println("性别:"+animal.getSex());    }}

最后说明
运行两种方式的代码,你会发现结果是一样的。同时你也会发现使用注解的好处在于不管实体类的编写比较简洁,更易于维护。同时,不管有多少个实体类,只要它们的字段中有字段是用到同一种翻译模式的话【例子中人员类跟动物类都有日期格式翻译】,用传统代码方式的话,则需要编写重复代码,通过注解则只需要配置对应的注解方式即可。
开发注解的步骤
1,定义好注解类
2,编写注解的解析类,前提你要会使用java的反射知识
3,将注解用在需要使用注解的地方