【JAVA基礎篇】註解

一、什麼是註解?

註解是元數據,所謂元數據就是描述數據的數據。

在annotation誕生之前(jdk1.5誕生了註解),甚至之後,xml被廣泛的由於描述元數據。但是後來,有一些應用開發工程師和架構師覺得它越來越難以維護了,他們覺得需要一種和代碼緊耦合的東西,而不是xml配置和代碼是松耦合的(某些情況下甚至是完全分離的),於是annotation誕生了。

假如你想爲應用設置很多的常量或參數,這種情況下,XML是一個很好的選擇,因爲它不會同特定的代碼相連。如果你想把某個方法聲明爲服務,那麼使用Annotation會更好一些,因爲這種情況下需要註解和方法緊密耦合起來,開發人員也必須認識到這點。

目前,許多框架將XML和Annotation兩種方式結合使用,平衡兩者之間的利弊。

二、使用註解的好處

  1. 對代碼進行標記
  2. 生成文檔
  3. 編譯時進行語法檢查
  4. 減少XML配置

三、註解的分類

3.1、元註解

用來定義註解的註解,@interface、@Target、@Retention、@Inherited

註解 作用
@interface 定義註解
@Target 聲明註解的使用目標,說明這個可以在類型上使用,還是屬性、還是方法、還是參數
@Retention 註解應該如何去保留,是在源碼中保留,還是在字節碼文件中保留,還是在運行時保留
@Inherited 子類是否繼承父類在類上定義的註解

3.2、內置註解

jdk定義的一些註解,還有很多其他的,這裏只列舉一部分:@SuppressWarnings、@Deprecated、@Override、@Documented、@FunctionaInterface、@SafeVarargs、@version、@author、@param、@exception、@return

@SuppressWarnings 忽略警告
@Deprecated 棄用
@Override 說明此方法重寫父類的方法
@Documented 生成javadoc,生成javadoc時默認是不生成註解說明的,但是如果使用了@Documented來定義這個註解,那麼將會生成註解說明

3.3、自定義註解

使用@interface來自定義一個註解

四、註解使用示例

我們先來定義幾個註解

4.1、註解定義

package org.cc.annotation;

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 Controller {
	String value();
}
package org.cc.annotation;

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;

@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
	String value();
}
package org.cc.annotation;

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;

@Inherited
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Parameter {
	String value() default "";
}
package org.cc.annotation;

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;

@Inherited
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
	String value() default "root";
}
package org.cc.annotation;

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

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Required {
}

4.2、使用註解

package org.cc.annotation.use;

import org.cc.annotation.Controller;
import org.cc.annotation.Inject;
import org.cc.annotation.Parameter;
import org.cc.annotation.Permission;
import org.cc.annotation.Required;
/**
 * 定義一個類,來使用剛剛定義的註解
 * @author cc
 *
 */
@Controller("testController")
public class TestController {
	@Inject("injectStr")
	private String injectStr;
	
	@Permission("testPermission")
	public void test(@Parameter("param") @Required String param,String param2){
		
	}
}
package org.cc.annotation.use;

/**
 * TestController類的子類
 * @author cc
 *
 */
public class SubTestController extends TestController{
	private String injectStr;
	
	public void test(String param,String param2){
		
	}
}

4.3、解析註解

package org.cc.annotation.use;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

import org.cc.annotation.Controller;
import org.cc.annotation.Inject;

/**
 * 使用反射來解析註解
 * @author cc
 *
 */
public class JXAnnotation {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException {
		
		Class clazz = Class.forName("org.cc.annotation.use.TestController");
		Annotation[] annotations = clazz.getAnnotations();//得到指定類的所有註解
		for (Annotation a: annotations ) {
            System.out.println(a);
        }
		Controller c = (Controller)clazz.getAnnotation(Controller.class);//得到類特定的註解
		System.out.println(c.value());
		
		Field f = clazz.getDeclaredField("injectStr");
		Inject inject = f.getAnnotation(Inject.class);
		System.out.println(inject.value());
		
		Class clazz1 = Class.forName("org.cc.annotation.use.SubTestController");
		Controller c1 = (Controller)clazz1.getAnnotation(Controller.class);//得到類特定的註解
		System.out.println(c1);//因爲定義Controller時沒有使用Inherited元註解,所以子類SubTestController並不會繼承父類的註解Controller
		//注意僅僅針對類,成員屬性和方法不受此註釋影響,就是說子類方法上的註解一定會繼承父類的註解
		
	}

}

五、定義和使用註解需要注意的地方

1、自定義註解我們可以看到有一行String value() ,類似於定義一個方法,這行代碼表示使用註解時必須指定value屬性值,像這樣:@Controller("testController")或者這樣寫@Controller(value="testController"),不能這樣寫:@Controller(),編譯會報錯。如果非要這樣使用,那麼需要修改這個註解的定義,改成這樣String value() default "";或者直接將String value()這一行刪掉。

簡單描述就是:如果定義註解時定義了value屬性,那麼使用時必須設置value屬性值,或者提供默認的屬性值。

2、定義註解時屬性是什麼類型,那麼使用註解時設置的屬性值必須跟定義的類型相同。下面這種情況也是可以的:定義時屬性值類型爲字符串數組,然後使用時設置屬性值爲字符串。

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章