20.java自定義註解

1.註解
含義:註解是做用於類、方法和參數等前面的特定元素,爲這個方法增長的說明或功能,可自定義.
原理:經過反射機制獲取被檢查方法上的註解信息,而後根據註解元素的值進行特定的處理.
建立註解:在指定項目下點擊右鍵 new -- > Annotation --> 輸入註解名,如 public @interface Author{}
     在註解中建立參數,形式爲: 訪問修飾符 參數類型 參數名() [default 參數值],如 public String value()
     訪問修飾符只能使用public和默認權限修飾符.
     參數類型支持基本類型、String、Class、enum、Annotation、以上類型的數組.
     在註解前加上元註解@Retention、@Target、@Documented、@Inherited.
使用註解:經過@符號加上註解名,如@Author
     在註解名後的括號內輸入參數與參數值,多個參數用逗號隔開,如@Author(value = "yt",age=18)
     一個參數爲數組類型時,值用{值,值}的形式,如 @Author(hobby={"run","jump"})
     若是註解只有一個參數且名爲value,那麼在使用的時候能夠直接指定屬性值,如@Author("yt")
     註解參數必須有肯定的值,要麼在定義的時候給默認值,要麼在使用註解的時候指定參數值.

2.元註解:
@Retention 該註解的保留策略,參數值以下
  RetentionPolicy.SOURCE -- 註解僅存在於源碼中,在class字節碼文件中不包含
  RetentionPolicy.CLASS -- 默認的保留策略,註解會在class字節碼文件中存在,但運行時沒法得到
  RetentionPolicy.RUNTIME -- 註解會在class字節碼文件中存在,在運行時能夠經過反射獲取到
@Target 該註解的做用目標 ,參數值數組以下
  ElementType.TYPE -- 接口、類、枚舉、註解
  ElementType.FIELD -- 字段、枚舉的常量
  ElementType.METHOD -- 方法
  ElementType.PACKAGE -- 包
  ElementType.PARAMETER -- 方法參數
  ElementType.CONSTRUCTOR -- 構造函數
  ElementType.LOCAL_VARIABLE -- 局部變量
  ElementType.ANNOTATION_TYPE -- 註解
@Documented 該註解將包含在javadoc中
@Inherited 該註解能夠被繼承 java

3.註解解析器:用來解析自定義註解。數組

 

實例:自定義註解、使用、解析ide

Author.java
/**
 * 
 * @Descript TODO (做者註解)
 * @author Administrator
 * @date 2019年5月23日
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Documented
@Inherited
public @interface Author {
    public int age() default 0;
    public String name() default "";
    public String tel() default "";
    public SexType sex() default SexType.SECRET;
    public String[] hobby() default "";
    public String createDate() default "";
    public String address() default "湖南省長沙市嶽麓區";
}
SexType.java
public enum SexType {
    
    BOY,
    
    GIRL,
    
    SECRET
}
DefaultIntValue.java
/**
 * 
 * @Descript TODO (整型默認值註解)
 * @author Administrator
 * @date 2019年5月23日
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Documented
@Inherited
public @interface DefaultIntValue {
    int value();
}
DefaultStringValue.java
/**
 * 
 * @Descript TODO (字符串默認值註解)
 * @author Administrator
 * @date 2019年5月23日
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Documented
@Inherited
public @interface DefaultStringValue {
    String value();
}
CheckParameter.java
/**
 * 
 * @Descript TODO (校驗方法參數註解)
 * @author Administrator
 * @date 2019年5月23日
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Documented
@Inherited
public @interface CheckParameter {
    int maxLength();
    int minLength() default 0;
    String description() default "";
}

  Person.java函數

/**
 * 
 * @Descript TODO (註解做用的類)
 * @author Administrator
 * @date 2019年5月23日
 *
 */
public class Person {

    @DefaultStringValue("湯姆")
    private String name;
    
    @DefaultIntValue(2)
    private int age;
    
    @DefaultIntValue(56)
    private int weight;
    
    @DefaultIntValue(168)
    private int height;

    @Author(name="bushiren",age=18,tel="13787216345",createDate="2019-05-22 14:03:05",sex=SexType.BOY,hobby= {"籃球","LOL"})
    public void eat(String food) {
        System.out.println(new Date() + ":" + this.name + " is eating " + food);
    }
    
    public void sing(@CheckParameter(minLength=5,maxLength = 100,description="歌曲名稱長度在5~100之間") String songName) {
        System.out.println(new Date() + ":" + this.name + " is singing " + songName);
    }

    @Author(name="woshiren",age=19,tel="13787216345",createDate="2019-05-23 14:03:05",sex=SexType.GIRL,hobby= {"看書","刷劇"})
    @Override
    public String toString() {
        return new Date() + ":" + "Person [name=" + name + ", age=" + age + ", weight=" + weight + ", height=" + height + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}
TestAnnantion.java
package com.wulss.annatation;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Date;

/**
 * 
 * @Descript TODO (模擬註解解析器)
 * @author Administrator
 * @date 2019年5月23日
 *
 */
public class TestAnnantion {

    public static void main(String[] args) {
        TestAnnantion test = new TestAnnantion();
        
        Person person = (Person)test.getObjectAndSetDefaultValue(Person.class, "把耳朵叫醒");
        
        System.out.println(person.toString());
        
    }
    
    /**
     * 構造一個對象,經過註解給屬性賦初值,並執行某些特定的方法
     * @param clazz 類
     * @param checkString 校驗的參數值
     * @return 返回一個對象
     */
    public Object getObjectAndSetDefaultValue(Class clazz,String checkString)  {
        DefaultIntValue defaultIntValue = null;
        DefaultStringValue defaultStringValue = null;
        Author author = null;
        CheckParameter checkParameter = null;
        
        try {
            //須要構造出該類的一個對象
            Constructor constructor = clazz.getDeclaredConstructor();
            Object object = constructor.newInstance();
            
            Field[] fields = clazz.getDeclaredFields();
            for(Field field:fields) {
                //默認是不能訪問到private修飾的屬性,因此經過setter方法給有註解的屬性賦值
                if(field.isAnnotationPresent(DefaultIntValue.class)) {
                    defaultIntValue = field.getAnnotation(DefaultIntValue.class);
                    
                    String setName = "set" + TestAnnantion.cap(field.getName());
                    Method setter = clazz.getDeclaredMethod(setName, field.getType());
                    setter.invoke(object, defaultIntValue.value());
                }
                
                if(field.isAnnotationPresent(DefaultStringValue.class)) {
                    defaultStringValue = field.getAnnotation(DefaultStringValue.class);
                    
                    String setName = "set" + TestAnnantion.cap(field.getName());
                    Method setter = clazz.getDeclaredMethod(setName, field.getType());
                    setter.invoke(object, defaultStringValue.value());
                }
            }
            
            Method[] methods = clazz.getDeclaredMethods();
            for(Method method:methods) {
                //將有做者註解的方法上的做者信息打印輸出
                if(method.isAnnotationPresent(Author.class)) {
                    author = method.getAnnotation(Author.class);
                    System.out.println(new Date() + ":" + method.getName()
                                    + "方法建立時間:" + author.createDate() + "," 
                                    + "做者姓名:" + author.name() + ","
                                    + "年齡:" + author.age() + ","
                                    + "性別:" + author.sex() + ","
                                    + "手機號:" + author.tel() + ","
                                    + "工做地址:" + author.address()
                                    );
                    
                }
                
                //校驗只且僅有一個帶有註解的參數的方法的參數註解上的值並執行該方法
                if(method.getParameters().length==1) {
                    Parameter parameter = method.getParameters()[0];

                    if(parameter.isAnnotationPresent(CheckParameter.class)) {
                        checkParameter = parameter.getAnnotation(CheckParameter.class);
                        
                        System.out.println(new Date() + ":" + "開始校驗" + method.getName() + "()方法中的參數,校驗值爲:" + checkString);
                        
                        if(checkString==null || checkString.length() < checkParameter.minLength() || checkString.length() > checkParameter.maxLength()) {
                            System.out.println(new Date() + ":" + "校驗不經過," + checkParameter.description());
                            
                        }else {
                            System.out.println(new Date() + ":" + "校驗經過,開始執行該方法");
                            method.invoke(object, checkString);
                        }
                    }
                }
            }
            
            return object;
            
        } catch (Exception e) {
            e.printStackTrace();
            
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 首字母大寫
     * @param name
     * @return
     */
    public static String cap(String name) {
        return name.substring(0, 1).toUpperCase() + name.substring(1);
    }
}

  執行結果:this

相關文章
相關標籤/搜索