注解分類
分為標(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處理
Step 1 新增注解類
新建Module來存放注解,取名為annotations
同時新增一個注解類
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
int value();
}
Step 2 編寫注解處理器
新建一個java library,命名為apt-processor
里面的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();
}
}