注解 反射

注解分類

分為標(biāo)準(zhǔn)注解和元注解

標(biāo)準(zhǔn)注解

  • @Override 對覆蓋超類中的方法進(jìn)行標(biāo)記
  • @Deprecated 標(biāo)記方法將被拋棄。如果某個類成員的提示中出現(xiàn)了個詞撞羽,就表示這個并不建議使用這個類成員
  • @SuppressWarnings 取消特定代碼中的警告

元注解

用來注解其他注解,有以下幾種

  • @Target 注解所修飾的對象范圍
  • @Inherited 表示注解的內(nèi)容可以被子類繼承
  • @Documented 表示這個注解應(yīng)該被JavaDoc工具記錄
  • @Retention 注解的保留策略

Target有以下取值范圍

ElementType 能修飾 說明
TYPE 類核行、接口或枚舉類型
FIELD 成員變量
METHOD 方法
PARAMETER 參數(shù)
CONSTRUCTOR 構(gòu)造器
LOCAL_VARIABLE 局部變量
ANNOTATION_TYPE 注解
PACKAGE

Retention 自定義注解的有效范圍

  • RetentionPolicy.SOURCE: 源碼級注解 只在源代碼中保留 一般都是用來增加代碼的理解性或者幫助代碼檢查之類的削茁,比如我們的Override;
  • RetentionPolicy.CLASS: 編譯時注解 默認(rèn)的選擇鲤嫡,能把注解保留到編譯后的字節(jié)碼class文件中骗污,僅僅到字節(jié)碼文件中着撩,運(yùn)行時是無法得到的诅福;
  • RetentionPolicy.RUNTIME: 運(yùn)行時注解,注解不僅 能保留到class字節(jié)碼文件中拖叙,還能在運(yùn)行通過反射獲取到氓润,這也是我們最常用的。

注解代替枚舉

通過View.VISIBLE的源碼,我們可以發(fā)現(xiàn)VISIBLE,INVISIBLE和GONE是用注解來實(shí)現(xiàn)枚舉的作用的

    @IntDef({VISIBLE, INVISIBLE, GONE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Visibility {}
    
    public static final int VISIBLE = 0x00000000;
    public static final int INVISIBLE = 0x00000004;
    public static final int GONE = 0x00000008;

Android注解

在android.support.annotation包中也提供了許多資源的注解

name exp
AnimRes 動畫
AnimatorRes animator資源類型
AnyRes 任何資源類型
ArrayRes 數(shù)組資源
AttrRes attr
BoolRes bool資源
ColorRes 顏色資源
DimenRes 尺寸資源
DrawableRes 圖片資源
IdRes id資源
InterpolatorRes 插值器資源
LayoutRes 布局資源
MenuRes 菜單資源
RawRes raw資源
StringRes 字符資源
StyleRes 風(fēng)格資源
StyleableRes styleable資源
TransitionRes transition資源類型
XmlRes xml資源

資源注解是為了防止我們在使用程序資源的時候薯鳍,錯誤傳遞資源類型給函數(shù)咖气,導(dǎo)致程序錯誤

Null注解

  • @NonNull:不能為空
  • @Nullable:可以為空

線程注解

  • @UiThread
  • @BinderThread只在綁定線程上
  • @WorkerThread子線程
  • @AnyThread任意

其他

  • IntDef
  • StringDef
  • LongDef
  • RequiresApi 表示注釋的元素只應(yīng)在給定API級別或更高級別上調(diào)用挨措。
  • RequiresPermission
   @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
   public abstract Location getLastKnownLocation(String provider);
   
   @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
   public abstract Location getLastKnownLocation(String provider);
 
  • IntRange
private void testDo(@IntRange(from = 1,to = 100)int s){
        Log.e("tag","-------->"+s);
    }
  • Size 表示注釋的元素應(yīng)該具有給定的大小或長度。注意“-1”的意思是“未設(shè)置”
  • floatRange
    可以在google文檔中查看

注解處理器

是javac的一個工具崩溪,用來掃描和處理注解浅役。就是在編譯時期,通過注解生成.java文件伶唯。針對運(yùn)行時觉既,采用反射機(jī)制。針對編譯時乳幸,注解會采用AbstractProcessor處理

1647e53e3d5d3365.jpg

Step 1 新增注解類

新建Module來存放注解,取名為annotations

1647def00161e26d.jpg

同時新增一個注解類

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
    int value();
}

Step 2 編寫注解處理器

新建一個java library,命名為apt-processor

1647df7689b1ffaf.jpg

里面的build.gradle跟android library的內(nèi)容有些不一樣,同時添加依賴apt-annotations

apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(':apt-annotations')   //implementation替代了之前的compile
}

sourceCompatibility = "1.7"
targetCompatibility = "1.7"

接著編寫注解處理器ClassProcessor,繼承自AbstractProcessor

public class ClassProcessor extends AbstractProcessor{

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return super.getSupportedAnnotationTypes();
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return super.getSupportedSourceVersion();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        return false;
    }
}
  • init
    初始化瞪讼。可以得到ProcessingEnviroment粹断,ProcessingEnviroment提供很多有用的工具類Elements, Types 和 Filer
  • process
    可以在這里寫掃描符欠、評估和處理注解的代碼,生成Java文件
  • getSupportedAnnotationTypes
    指定這個注解處理器是注冊給哪個注解的瓶埋,這里說明是注解BindView
  • getSupportedSourceVersion
    返回java版本希柿。通常返回SourceVersion.latestSupported

Step 3 注冊注解處理器

在processor中添加依賴

implementation 'com.google.auto.service:auto-service:1.0-rc4'

在注解處理器ClassProcessor中添加@AutoService(Processor.class)

Step 4 app依賴

dependencies {
    implementation project(':apt-annotation')
    annotationProcessor project(':apt-processor')
}

注解處理器只在編譯期間用到,處理完后沒有作用养筒,
使用apt插件可以減少引入不必要的文件曾撤。官方(Android)提供了annotationProcessor來代替android-apt

參考APT,里面寫了如何去生成一個java文件,可以通過javapoet工具

反射

Java反射機(jī)制是指在運(yùn)行狀態(tài)中
對于任意一個類闽颇,都能知道這個類的所有屬性和方法盾戴;
對于任何一個對象,都能夠調(diào)用它的任何一個方法和屬性兵多;
這樣動態(tài)獲取新的以及動態(tài)調(diào)用對象方法的功能就叫做反射尖啡。

1.獲取Clas的三種方法

Class c = Class.forName("java.lang.String");

Class c1 = String.Class;

String str = new String();
Class c2 = str.getClass();

2.獲取成員變量

Field[] fields = c.getDeclaredFields();

獲取字段的修飾符
int fieldValue = field.getModifiers();//如:private、static剩膘、final等

與某個具體的修飾符進(jìn)行比較
Modifier.isStatic(fieldValue)//看此修飾符是否為靜態(tài)(static)

獲取字段的聲明類型
field.getType()衅斩;//返回的是一個class

3.獲取類的方法

Method[] methods = c.getDeclaredMethods();

                方法                              含義        
      m.getParameterTypes()             獲取傳入?yún)?shù)類型Class<?>[]
        m.getReturnType()                獲取方法返回類型Class<?> 

c.getDeclaredMethod("方法名",類型.class...) 獲取特定的方法
c.getDeclaredConstructors() 獲取所有的構(gòu)造方法
c.getDeclaredConstructor(類型.class...) 獲取指定的構(gòu)造方法
c.getSuperclass() 獲取父類Class
c.getInterfaces() 獲取實(shí)現(xiàn)的接口Class<?>[]

運(yùn)行時注解,是通過反射獲取

public <T extends Annotation> T getAnnotation(Class<T> annotationClass)

如果存在于此元素怠褐,則返回該元素注釋指定的注釋類型畏梆,否則返回為null

@Retention(RetentionPolicy.RUNTIME)
//Retention注解決定MyAnnotation注解的生命周期
@Target( { ElementType.METHOD, ElementType.TYPE })
public @interface MyAnnotation {
    String color() default "blue";//為屬性指定缺省值
}

private void ResolveClass(String className) {
        try {
            Class<?> clazz = classLoader.loadClass(className);
            Class<?> aClass = classLoader.loadClass(MyAnnotation .class.getName());
            System.out.println(clazz.getName());
            MyAnnotation annotation = clazz.getAnnotation(MyAnnotation .class);
            if(annotation != null) {
                System.out.println(annotation.color());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市奈懒,隨后出現(xiàn)的幾起案子奠涌,更是在濱河造成了極大的恐慌,老刑警劉巖磷杏,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溜畅,死亡現(xiàn)場離奇詭異,居然都是意外死亡极祸,警方通過查閱死者的電腦和手機(jī)慈格,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門怠晴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浴捆,你說我怎么就攤上這事蒜田。” “怎么了选泻?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵冲粤,是天一觀的道長。 經(jīng)常有香客問我滔金,道長色解,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任餐茵,我火速辦了婚禮,結(jié)果婚禮上述吸,老公的妹妹穿的比我還像新娘忿族。我一直安慰自己,他們只是感情好蝌矛,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布道批。 她就那樣靜靜地躺著,像睡著了一般入撒。 火紅的嫁衣襯著肌膚如雪隆豹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天茅逮,我揣著相機(jī)與錄音璃赡,去河邊找鬼。 笑死献雅,一個胖子當(dāng)著我的面吹牛碉考,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挺身,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼侯谁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了章钾?” 一聲冷哼從身側(cè)響起墙贱,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贱傀,沒想到半個月后蟋座,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秽誊,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年空猜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锡足。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出榄笙,到底是詐尸還是另有隱情,我是刑警寧澤祷蝌,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布茅撞,位于F島的核電站,受9級特大地震影響巨朦,放射性物質(zhì)發(fā)生泄漏米丘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一糊啡、第九天 我趴在偏房一處隱蔽的房頂上張望拄查。 院中可真熱鬧,春花似錦棚蓄、人聲如沸堕扶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稍算。三九已至,卻和暖如春役拴,著一層夾襖步出監(jiān)牢的瞬間糊探,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工河闰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留科平,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓淤击,卻偏偏與公主長得像匠抗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子污抬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容