概念:相当于标签
概念:元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它的注解上面
元注解的种类
作用:解释/说明了注解的生命周期
取值如下:
RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中
作用:将注解的元素包含到javadoc文档中
作用:限定了注解作用的目标范围,包括累、方法等
取值如下
作用: 继承注解(如一个父类使用了该注解,那么它的子类没有进行其他注解的话,则会继承了父类的注解。)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface Test {}
//父类使用了Test注解
@Test
public class A {
}
//子类没有使用其他注解,则继承了父类的注解
public class B extends A {}
作用:可重复注解,即注解的值可以同时取多个
//1.
//定义Person的容器注解
@interface Persons {
Person[] value();
}
//2.
//定义Person的注解
//@Repeatable括号中的类是容器注解
@Repeatable(Persons.class)
@interface Person{
String role() default "";
}
//3.
//取多个值来修饰,即是艺术家也是厨师
@Person(role="artist")
@Person(role="chef")
public class SuperMan{
}
作用:用来标记过时的元素的。
作用:被标记的元素会阻止编译器发出的警告提醒
作用:子类要复写父类中被Override修饰的方法
作用:提醒开发者不要用参数做不安全的操作&阻止编译器产生unchecked警告
// 以下是官方例子
// 虽然编译阶段不报错,但运行时会抛出 ClassCastException 异常
// 所以该注解只是作提示作用,但是实际上还是要开发者自己处理问题
@SafeVarargs // Not actually safe!
static void m(List... stringLists) {
Object[] array = stringLists;
List tmpList = Arrays.asList(42);
array[0] = tmpList; // Semantically invalid, but compiles without warnings
String s = stringLists[0].get(0); // Oh no, ClassCastException at runtime!
}
作用:表示该接口为函数式。函数式接口=具有1个方法的普通接口
问题:为什么要用额外的函数式接口标记
答案:函数式接口很容易转化为Lambda表达式
比如
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface Runnable
is used
* to create a thread, starting the thread causes the object's
* run
method to be called in that separately executing
* thread.
*
* The general contract of the method run
is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
//通过@interface定义Test注解
public @interface Test{
}
注解的属性也叫成员变量。注解只有成员变量,没有方法
注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。
注意点:注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组
public @interface Test{
int id();
String msg();
}
我们在Test注解里定义了id和msg两个属性,在使用他们的时候我们应该进行赋值
@Test(id=5,msg = "hello")
public class AnnotationTest {
}
你也可以设置默认值
public @interface Test {
int id() default 10;
String msg() default "hello";
}
这样子id的默认值是10,msg的默认值是hello。因为有默认值所以可以在使用的时候括号里可以不填
直接@Test()。
还有一种情况就是注解内只有一个属性的时,可以直接注解括号里填写一个值@Test(10)
之前比喻了注解是标签,那现在获取标签然后检阅上面的内容信息。那怎么实现呢,通过反射
//判断是否应用了某注解
public boolean isAnnotationPresent(Class extends Annotation> annotationClass) {}
//获取注解在这个元素的指定注解的对象
public A getAnnotation(Class annotationClass) {}
//获取注解在这个元素的所有注解对象
public Annotation[] getAnnotations() {}
以下演示
注解类
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
String name() default "hello";
int age() default 10;
}
被注解的类
@Test(name = "class",age = 100)
public class Person {
@Test(name = "hey",age = 40)
private String name;
@Test(name = "hi",age = 20)
public void son(){
}
}
类注解获取:
Class aClass = Person.class;
//判断是否应用了该注解
boolean hasAnnotation = aClass.isAnnotationPresent(Test.class);
if (hasAnnotation) {
//拿到Annotation注解
Annotation annotation = aClass.getAnnotation(Test.class);
Test myAnnotation = (Test) annotation;
//获取name以及age
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.age());
}
//name:class
//age:100
方法注解获取:
Method method = null;
try {
//拿到该方法对象(son为该方法名)
method = Person.class.getDeclaredMethod("son");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Annotation annotationMethod = method.getAnnotation(Test.class);
Test myAnnotation = (Test) annotationMethod;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.age());
//name:hi
//age:20
变量注解获取
Class aClass = Person.class;
try {
Field field=aClass.getDeclaredField("name");
Test annotation=field.getAnnotation(Test.class);
System.out.print(annotation.name());
System.out.print(annotation.age());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
//name:hey
//age:40
JUnit 这个是一个测试框架,典型使用方法如下:
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
ButterKnife 是 Android 开发中大名鼎鼎的 IOC 框架,它减少了大量重复的代码。
public class MainActivity extends AppCompatActivity {
@BindView(R.id.tv_test)
TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
}
还有 Degger2以及Retrofit等等
之前整理的笔记借鉴了这位大神的文章
地址 https://blog.csdn.net/briblue/article/details/73824058