JavaSE學習筆記28:註解
阿新 • • 發佈:2020-12-01
註解
- 註解,或者叫做註釋型別,英文單詞是Annotation
- 註解Annotation是一種引用資料型別,編譯之後也是生成xxx.class檔案
- 怎麼自定義註解
[修飾符列表] @interface 註解型別名{
}
package se7;
/*
自定義註解:MyAnnotation
*/
public @interface MyAnnotation {
//????????
}
如何使用,用在什麼地方?
-
註解使用時的語法格式:@註解型別名
-
註解可以出現在類上、屬性上、方法上、變數上等...
package se7; //預設情況下,註解可以出現在任意位置 @MyAnnotation public class AnnotationTest01 { @MyAnnotation private int no; @MyAnnotation public AnnotationTest01(){} @MyAnnotation public static void m1(){ @MyAnnotation int i = 100; } @MyAnnotation public void m2(@MyAnnotation String name,@MyAnnotation int k){ } } @MyAnnotation interface MyInterface{ } @MyAnnotation enum Season{ SPRING,SUMMER,AUTUMN,WINTER }
-
註解還可以出現在註解型別上
package se7; //註解修飾註解 @MyAnnotation public @interface OtherAnnotation { }
JDK內建註解
JDK內建了哪些註解?
java.lang包下的註釋型別:
掌握:Deprecated 用 @Deprecated 註釋的程式元素,表示已經過時,不鼓勵程式設計師使用這樣的元素,通常是因為它很危險或存在更好的選擇。
掌握:Override 表示一個方法宣告打算重寫超類中的另一個方法宣告。
不要掌握:SuppressWarnings 指示應該在註釋元素(以及包含在該註釋元素中的所有程式元素)中取消顯示指定的編譯器警告。
Override註解
package se7; /* 關於JDK lang包下的Override註解 原始碼: public @interface Override { } 標識性註解:給編譯器做參考的,編譯器看到方法上有這個註解的時候,編譯器會自動檢查該方法是否重寫了父類的方法,如果沒有重寫,報錯。 這個註解只是在編譯階段起作用,和執行期無關 */ //@Override這個註解只能註解方法 //Override這個註解是給編譯器參考的,和執行階段沒有關係 //凡是java中的方法帶有這個註解的,編譯器都會進行編譯檢查,如果這個方法不是重寫父類的方法,編譯器報錯。 public class AnnotationTest02 { @Override public String toString(){ return "toString"; } /* //方法名寫錯會報錯,提示你進行重寫 @Override public String toString2(){ return "toString"; } */ }
Deprecated註解
package se7;
//表示這個類已過時
@Deprecated
public class AnnotationTest03 {
public static void main(String[] args) {
AnnotationTest03 at = new AnnotationTest03();
at.doSome();
}
//表示這個方法已過時
@Deprecated
public void doSome(){
System.out.println("do Something!");
}
/*
Deprecated這個註解標註的元素已過時
這個註解主要是向其他程式設計師傳達一個資訊,告知已過時,有更好的解決方案存在
*/
@Deprecated
public static void doOther(){
System.out.println("do Other...");
}
}
class T{
public static void main(String[] args) {
AnnotationTest03 at = new AnnotationTest03();
at.doSome();
AnnotationTest03.doOther();
try {
Class c = Class.forName("java.util.Date");
Object obj = c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
註解當中的屬性
package se7.annotation;
public @interface MyAnnotation {
/**
* 通常在註解當中可以定義屬性,以下是MyAnnotation的name屬性
* 看著像一個方法,但實際上我們稱之為屬性name
* @return
*/
String name();
//顏色屬性
String color();
//年齡屬性
int age() default 78;//預設值是78,這裡寫了,測試程式可以不用寫
}
package se7.annotation;
public class MyAnnotationTest {
//報錯原因:如果一個註解當中有屬性,必須給屬性賦值
/*
@MyAnnotation
public void doSome(){}
*/
//@MyAnnotation(屬性名=屬性值,屬性名=屬性值)
@MyAnnotation(name="阿波",color = "黃色")//age因為指定了預設值,可以不寫
public void doSome(){
}
}
value屬性名省略
package se7.annotation2;
public @interface MyAnnotation {
/*
指定一個value屬性
*/
String value();
//String email();
}
package se7.annotation2;
public class MyAnnotationTest {
@MyAnnotation(value = "hehe")
public void doSome(){
}
/*
如果一個註解的屬性的名字是value,
並且只有一個屬性的話,在使用的時候,
該屬性名可以省略,如下所示。
*/
@MyAnnotation("haha")
public void doOther(){
}
}
註解中屬性的型別
package se7.annotation3;
public @interface MyAnnotation {
/*
註解當中的屬性可以是哪種型別?
可以是:byte short int long float double boolean char String Class 列舉型別,以及這些型別的陣列形式。
*/
int value1();
String value2();
int[] value3();
String[] value4();
Season value5();
Season[] value6();
Class parameterType();
Class[] parameterTypes();
}
package se7.annotation3;
public class OtherAnnotationTest {
//陣列是大括號
@OtherAnnotation(age = 25,email = {"阿波@123.com","波波@321.com"},seasonArray = {Season.SPRING,Season.SUMMER})
public void doSome(){
}
//如果陣列中只有1個元素,大括號可以省略
@OtherAnnotation(age = 25,email = "阿波@123.com",seasonArray = Season.WINTER)
public void doOther(){
}
}
package se7.annotation3;
public @interface OtherAnnotation {
int age();
//郵箱地址屬性,支援多個(陣列)
String[] email();
/**
* 季節陣列,Season是列舉型別
* @return
*/
Season[] seasonArray();
}
package se7.annotation3;
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER
}
元註解
用來標註“註解型別”的“註解”,稱為元註解
常見的元註解:Target、Retention
關於Target註解
這是一個元註解,用來標註 “註解型別” 的“註解“
這個Target註解用來標註“被標註的註解”可以出現在哪些位置上。
@Target(ElementType.METHOD)
//表示“被標註的註解”只能出現在方法上。
@Target(Value={CONSTRUCTOR},FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,NODUKE,PARAMETER,TYPE)
//這個表示該註解可以出現在:構造方法上、欄位上、區域性變數上、方法上...類上...
關於@Retention註解
這是一個元註解,這個Retention註解用來標註“被標註的註解”最終儲存在哪裡。
@Retention(RetentionPolicy.SOURCE)//表示該註解只能被保留在java原始檔中。
@Retention(RetentionPolicy.CLASS)//表示該註解被保留在class檔案中
@Retention(RetentionPolicy.RUNTIME)//表示該註解被儲存在class檔案中並且可以被反射機制所讀取
通過反射獲取註解
package se7.annotation4;
public class ReflectAnnotationTest {
public static void main(String[] args) throws Exception {
//獲取類
Class c = Class.forName("se7.annotation4.MyAnnotationTest");
//判斷類上面是否有@MyAnnotation
System.out.println(c.isAnnotationPresent(MyAnnotation.class));//true
if (c.isAnnotationPresent(MyAnnotation.class)){
//獲取該註解物件
MyAnnotation myAnnotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
System.out.println("類上面的註解物件" + myAnnotation);//類上面的註解物件@se7.annotation4.MyAnnotation()
//獲取註解物件的屬性,和調介面沒區別
String value = myAnnotation.value();
System.out.println(value);//上海浦東區,指定了新的值,不然還是預設值
}
//判斷String類上面是否存在這個註解
Class stringClass = Class.forName("java.lang.String");
System.out.println(stringClass.isAnnotationPresent(MyAnnotation.class));//false
}
}
package se7.annotation4;
@MyAnnotation("上海浦東區")//預設是廣州天河區,這裡指定了新的值
public class MyAnnotationTest {
//@MyAnnotation,報錯
int i;
//@MyAnnotation,報錯
public MyAnnotationTest() {
}
@MyAnnotation
public void doSome(){
//@MyAnnotation,報錯
int i;
}
}
package se7.annotation4;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//只允許該註解可以標註類、方法
@Target({ElementType.TYPE,ElementType.METHOD})
//希望這個註解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
/*
value屬性
*/
String value() default "廣州天河區";//預設值
}
獲取使用者名稱和密碼例子
package se7.annotation5;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
/*
username屬性
*/
String username();
/*
password屬性
*/
String password();
}
import java.lang.reflect.Method;
public class MyAnnotationTest {
@MyAnnotation(username = "admin",password = "123")
public void doSome(){
}
public static void main(String[] args) throws Exception {
//獲取MyAnnotationTest的doSome()方法上面的註解資訊
Class c = Class.forName("se7.annotation5.MyAnnotationTest");
//獲取doSome方法
Method doSomeMethod = c.getDeclaredMethod("doSome");
//判斷該方法上是否存在這個註解
if (doSomeMethod.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = doSomeMethod.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.username());//admin
System.out.println(myAnnotation.password());//123
}
}
}
註解在開發中的作用
需求:假設有這樣一個註解,叫做:@ID,這個註解只能出現在類上面,當這個類上有這個註解的時候,要求類中必須有一個int型別的id屬性,如果沒有這個屬性就包異常,如果有這個屬性則正常執行。
例子
package se7.annotation6;
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 Id {
}
//這個註解@ID用來標註類,被標註的類中必須有一個int型別的id屬性,沒有就報異常
package se7.annotation6;
@Id
public class User {
//int id;
String name;
String password;
}
package se7.annotation6;
/*
自定義異常
*/
public class HasNotIdPropertyException extends RuntimeException{
public HasNotIdPropertyException(){
}
public HasNotIdPropertyException(String s){
super(s);
}
}
package se7.annotation6;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
//獲取類
Class userClass = Class.forName("se7.annotation6.User");
//判斷類上是否存在ID註解
if (userClass.isAnnotationPresent(Id.class)){
//當一個類上面有ID註解的時候,要求類中必須存在int型別的id屬性
//如果沒有int型別的id屬性則報異常
//獲取類的屬性
Field[] fields = userClass.getDeclaredFields();
boolean isOk = false;//給一個預設的標記
for (Field field : fields){
if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){
//表示這個類是合法的類,有@ID註解,則這個類中必須有int型別的id
isOk = true;//表示合法
break;
}
}
//判斷是否合法
if (!isOk){
throw new HasNotIdPropertyException("被@ID註解標註的類中必須要有一個int型別的id屬性");
}
//若沒有id屬性,如下
//Exception in thread "main" se7.annotation6.HasNotIdPropertyException: 被@ID註解標註的類中必須要有一個int型別的id屬性
}
}
}