参考资料
[1]. 疯狂Java讲义(第三版) 李刚
基本Annotation
限定重写父类方法:@Override
@Override就是用来指定方法覆载的,它可以强制一个子类必须覆盖父类的方法。
public class Fruit
{
public void info()
{
System.out.println("水果的info方法...");
}
}
class Apple extends Fruit
{
// 使用@Override指定下面方法必须重写父类方法
@Override
public void inf0()
{
System.out.println("苹果重写水果的info方法...");
}
}
标示已过时:@Deprecated
@Deprecated用于表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告。
class Apple
{
// 定义info方法已过时
@Deprecated
public void info()
{
System.out.println("Apple的info方法");
}
}
public class DeprecatedTest
{
public static void main(String[] args)
{
// 下面使用info方法时将会被编译器警告
new Apple().info();
}
}
抑制编译器警告:@SuppressWarnings
@SuppressWarnings指示被该Annotation修饰的程序元素(以及该程序元素中的所有子元素)取消显示指定的编译器警告。@SuppressWarnings会一直作用于该程序元素的所有子元素,例如,使用@SuppressWarnings修饰某个类取消显示某个编译器警告,同时又修饰该类里的某个方法取消显示另一个编译器警告,那么该方法将会同时取消显示这两个编译器警告。
// 关闭整个类里的编译器警告
@SuppressWarnings(value="unchecked")
public class SuppressWarningsTest
{
public static void main(String[] args)
{
List<String> myList = new ArrayList(); // ①
}
}
Java 7 的“堆污染”警告与@SafeVarargs
List list = new ArrayList<Integer>();
// 添加元素时引发unchecked异常
list.add(20);
// 下面代码引起“未经检查的转换”的警告,编译、运行时完全正常
List<String> ls = list;
// 但只要访问ls里的元素,如下面代码就会引起运行时异常
System.out.println(ls.get(0));
Java 把引发这种错误的原因称为“堆污染”(Heap pollution),当把一个不带泛型的对象赋给一个带泛型的变量时,往往就会发生这种“堆污染”。
public class ErrorUtils
{
@SafeVarargs
public static void faultyMethod(List<String>... listStrArray)
{
// Java语言不允许创建泛型数组,因此listArray只能被当成List[]处理
// 此时相当于把List<String>赋给了List,已经发生了“擦除”
List[] listArray = listStrArray;
List<Integer> myList = new ArrayList<Integer>();
myList.add(new Random().nextInt(100));
// 把listArray的第一个元素赋为myList
listArray[0] = myList;
String s = listStrArray[0].get(0);
}
}
如果想要抑制上面的“警告”,可以采用下面的方式
1. 使用@SafeVarargs修饰引发该警告的方法或构造器。
2. 使用@SuppressWarnings(value=”unchecked”)修饰。
3. 编译时使用-Xlint:varargs 选项。
函数式接口与@FunctionalInterface
@FunctionalInterface是用来在接口中指定该接口必须是函数式接口,也就是只能包含一个抽象方法。
@FunctionalInterface
public interface FunInterface
{
static void foo()
{
System.out.println("foo类方法");
}
default void bar()
{
System.out.println("bar默认方法");
}
void test(); // 只定义一个抽象方法
void abc();
}
JDK的元Annotation
使用@Retention
@Retention只能用于修饰Annotation定义,用于指定被修饰的Annotation可以保留多长时间,@Retention包含一个RetentionPolicy类型的value成员变量,所以使用@Retention时必须为该value成员变量指定值。
value成员变量的值只能是如下三个:
- RetentionPolicy.CLASS,注解将会被保留在Class文件中,但在运行时并不会被VM保留。这是默认行为,所有没有用Retention注解的注解,都会采用这种策略。
- RetentionPolicy.RUNTIME,保留至运行时。所以我们可以通过反射去获取注解信息。
- RetentionPolicy.SOURCE,被编译器忽略
@Retention(RetentionPolicy.SOURCE)
public @interface SourceLevel {
}
@Retention(RetentionPolicy.CLASS)
public @interface ClassLevel {
}
@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimeLevel {
}