第十四节、轻松学Java_注解

系统注解

使用@标记,后面跟上注解的名称。系统注解主要包含三种注解:@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);
}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身影王座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值