系统注解
使用@标记,后面跟上注解的名称。系统注解主要包含三种注解:@Override、@Deprecated、@SuppressWarnings。
@Override
@Override 用来修饰一个方法, 这个方法必须是对父类中的方法的重写。 如果一个方法没有重写父类中的方法, 在使用这个注解时编译器将提示错误。
package com.test;
public class SuperOverride {
public void method() {
System.out.println("父类方法");
}
}
package com.test;
class SubOverride extends SuperOverride {
@Override
public void method() {
System.out.println("子类方法");
}
}
package com.test;
public class Test {
public static void main(String[] args) {
//方法是否覆盖了父类的方法。
SuperOverride sover = new SubOverride();
sover.method();
}
}
输出:
子类方法
被@Override注解的方法必须在父类中有同样的方法,编译才会通过。
@Deprecated
@Deprecated 可以用来注解不再使用已经过时的类、 方法和属性。 如果代码使用了@Deprecated 注解的类、 方法和属性, 编译器会给出警告。
@SuppressWarnings
@SuppressWarnings 用来抑制编译器生成警告信息。 它修饰的元素为类、 方法、 方法参数、 属性和局部变量。 当一个方法调用了过时的方法或者进行不安全的类型转换时, 编译器会生成警告, 此时可以为这个方法增加@SuppressWarnings 注解, 从而抑制编译器生成警告。
自定义注解
在定义自定义注解时, 不可以继承其他的注解或接口。 @interface 只用来声明一个注解。
注解元素一定要有确定的值, 可以在定义注解时指定它的默认值, 也可以在使用注解时指定默认值,非基本类型的注解元素的值不能为 null。 因此, 经常使用空字符串或 0 作为默认值。
package com.test;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
@Retention(RetentionPolicy.RUNTIME)//元注解,运行时保留注解,必须有,否则注解值读不出
@interface ApplianceMaker {
//定义注解元素,都有缺省值
public String type() default "电视机";
public String id() default "001";
public String maker() default "TCL有限公司";
public String address() default "广东省惠州市";
}
@Retention(RetentionPolicy.RUNTIME)
@interface AppliancePrice//定义注解
{
//注解元素只有一个,名为value
public int value() default 1200;
}
@Retention(RetentionPolicy.RUNTIME)
@interface ApplianceSaler//定义注解
{
public String name() default "京东";
public String id() default "001";
public String address() default "北京";
}
class Appliance
{
//为域maker加注解,给部分元素赋值,其余用缺省值
//如果注解元素都用缺省值,则直接写@ApplianceMaker
@ApplianceMaker(type="电脑",id="201")
public String maker;
@ApplianceSaler(name="苏宁",id="222",address="南京")
public String saler;//域有注解
@AppliancePrice(999)//也可以写成"value=999",因为只有一个
public int price;//域有注解
public void setMaker(String m)
{
maker=m;
}
public String getMaker()
{
return maker;
}
public void setSaler(String saler)
{
this.saler=saler;
}
public String getSaler()
{
return saler;
}
public void setPrice(int price)
{
this.price=price;
}
public int getPrice()
{
return price;
}
}
public class Test
{
public static void main(String args[])
{
System.out.println(readAnnotation(Appliance.class));
}
//读注解信息
private static String readAnnotation(Class aClass)
{
String maker="制造商:";
String saler="销售商:";
String price="价格:";
Field fields[]=aClass.getDeclaredFields();//获取Appliance类的所有字段
for(Field aField :fields)//对每一个字段判断
{
//字段的注解是ApplianceMaker类型
if(aField.isAnnotationPresent(ApplianceMaker.class))
{
ApplianceMaker aMaker;//声明一个注解变量
//调用getAnnotation方法获得在aField域上的注解"实例"
aMaker=(ApplianceMaker)aField.getAnnotation(ApplianceMaker.class);
maker+=aMaker.type()+" ";//获取type元素的值,其余同
maker+=aMaker.id()+" ";
maker+=aMaker.maker()+" ";
maker+=aMaker.address()+"\n";
}
//字段的注解是ApplianceSaler类型
else if(aField.isAnnotationPresent(ApplianceSaler.class))
{
ApplianceSaler aSaler;
aSaler=(ApplianceSaler)aField.getAnnotation(ApplianceSaler.class);
saler+=aSaler.name()+" ";
saler+=aSaler.id()+" ";
saler+=aSaler.address()+"\n";
}
//字段的注解是AppliancePrice类型
else if(aField.isAnnotationPresent(AppliancePrice.class))
{
AppliancePrice thePrice;
thePrice=(AppliancePrice)aField.getAnnotation(AppliancePrice.class);
price+=thePrice.value();
}
}
return maker+saler+price;
}
}
运行:
制造商:电脑 201 TCL有限公司 广东省惠州市
销售商:苏宁 222 南京
价格:999
元注解
Java 5.0 API 的 java.lang.annotation 包中提供了 4 个标准的元注解类型, 即@Target、 @Retention、@Documented 和@Inherited。 它们的作用是对其他注解类型进行注解。
@Target
import java.lang.annotation.*;
//定义一个注解Method。该注解的值是ElementType.METHOD,因此该注解只能作用于方法上
@Target({ElementType.METHOD})
public @interface Method {}
//@Method 作用于类上,出错
public class TargetTest {
@Method // 作用于方法上,正确
public void testTarget() {
}
}
@Retention
import java.lang.annotation.*;
@Target({ElementType.FIELD}) //作用于字段,大括号表示可以有多个值
@Retention(RetentionPolicy.RUNTIME) //其值只允许有一个,因此不用大括号
public @interface Runtime {
}
@Retention 的作用是指定需要在什么级别保留该注释信息, 它用于描述注解的生命周期, 即被描述的注解在什么范围内有效。
@Documented
import java.lang.annotation.*;
@Target(ElementType.FIELD) //作用于字段
@Retention(RetentionPolicy.RUNTIME) //运行时有效
@Documented //生成文档
public @interface Document {
}
最后使用元注解@Documented说明注解Document 通过 javadoc 和类似的默认工具进行文档化。
@Inherited
默认情况下, 父类注解是不会被子类继承的, 只有使用元注解@Inherited 的注解才可以被子类继承。
多重注解
在注解前使用@Repeatable 允许同一类型的注解多次使用
import java.lang.annotation.Repeatable;
public @interface NewAnnos{
NewAnno[] value(); //定义放置NewAnno 注解的数组
}
@Repeatable(NewAnnos.class) //使用@ Repeatable 说明这个注解可以多次使用
@interface NewAnno { //定义NewAnno 注解
String value(); //定义注解的属性
}
函数式接口
Java 8.0 引入了 Lambda 表达式, 它在 Java 的类型系统中被当作只包含一个抽象方法的任意接口类型。在这个接口中需要添加@FunctionalInterface 注解, 编译器在发现标注这个注解的接口有不止一个抽象方法时会报错。
@FunctionalInterface
interface InterNew<String,Integer> {
Integer InterNew(String t);
}
public class FuncNew {
public static void main(String[] args){
//Lambda 表达式,使用函数式接口
InterNew<String, Integer> in = (t) -> Integer.valueOf(t);
Integer i = in.InterNew("25");
System.out.println("Lambda 表达式:String -> Integer:" + i);
}
}