Java面向对象系列[v1.0.0][注解]

自JDK5开始,Java增加了对元数据(MetaData)的支持,也就是注解(Annotation),它是代码里的特殊标记,在编译、类加载、运行时被读取,并执行相应的处理。通过使用注解,可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息,代码分析工具、IDE或者部署工具可以通过这些补充信息进行验证或者进行部署

基本注解

@Override 限定重写父类方法

@Override就是用来指定方法覆载的,他可以强制一个子类必须覆盖父类的方法,它告诉编译器检查这个方法,保证父类要包含一个被该方法重写的方法,否则就会编译出错;@Override主要是帮助程序员避免一些低级错误,例如重写父类方法的时候将方法名写错,编译和运行时没有任何错误,运行结果又得不到期望结果这样的低级错误,加上注解后,编译器就会自行检查了

import static java.lang.System.*;

public class Fruit
{
	public void info()
	{
		out.println("水果的info方法...");
	}
}
class Apple extends Fruit
{
	// 使用@Override指定下面方法必须重写父类方法
	@Override
	public void inf0()
	{
		out.println("苹果重写水果的info方法...");
	}
}

@Override只能修饰方法,不能修饰其他程序元素

@Deprecated

它用于表示某个程序元素已过时,当其他程序使用已过时的类、方法时编译器将会给出警告,@Deprecated在Java9里新增了两个属性forRemoval:该boolean类型的属性指定该API在将来是否会被删除;since:该String类型的属性指定该API从哪个版本被标记为过时的

import static java.lang.System.*;

class Apple
{
	// 定义info方法已过时
	// since属性指定从哪个版本开始,forRemoval指定该API将来会被删除
	@Deprecated(since = "9", forRemoval = true)
	public void info()
	{
		System.out.println("Apple的info方法");
	}
}
public class DeprecatedTest
{
	public static void main(String[] args)
	{
		// 下面使用info方法时将会被编译器警告
		new Apple().info();
	}
}

@Deprecated的作用于文档注释中的@deprecated标记作用基本相同,但前者是在JDK5之后支持的注解,无需放在文档注释(/**…*/)中

抑制编译器警告@SuppressWarnings

@SuppressWarnings意味着被该注解修饰的程序元素(以及该程序元素中的所有子元素)取消显示指定的编译器警告,@SuppressWarnings会一直作用于该程序元素的所有子元素
例如:使用@SuppressWarnings修饰某个类取消显示某个编译器警告,类中的某个方法取消显示另一个编译器警告,那么该方法会同时取消显示两个编译器警告
通常情况下,如果程序中使用没有泛型限制的集合将会引起编译器警告,为了避免这种编译器警告可以使用@SuppressWarnings修饰

import java.util.*;

// 关闭整个类里的编译器警告
@SuppressWarnings(value = "unchecked")
public class SuppressWarningsTest
{
	public static void main(String[] args)
	{
		List<String> myList = new ArrayList();     
	}
}

堆污染警告和Java9增强的@SafeVarargs

当把一个不带泛型的对象赋给一个带泛型的变量时,往往会发生堆污染(Heap pollution),对于形参个数可变的方法,该形参的类型又是泛型,就更容易导致Heap pollution

import java.util.*;

public class ErrorUtils
{
	@SafeVarargs
	public static void faultyMethod(List<String>... listStrArray)
	{
		// Java语言不允许创建泛型数组,因此listArray只能被当成List[]处理
		// 此时相当于把List<String>赋给了List,已经发生了“擦除”
		// 这里就发生了Heap pollution
		List[] listArray = listStrArray;
		List<Integer> myList = new ArrayList<>();
		myList.add(new Random().nextInt(100));
		// 把listArray的第一个元素赋为myList
		listArray[0] = myList;
		String s = listStrArray[0].get(0);
	}
}
import java.util.*;
import static java.lang.System.*;

public class ErrorUtilsTest
{
	public static void main(String[] args)
	{
		ErrorUtils.faultyMethod(Arrays.asList("Hello!"),
			Arrays.asList("World!"));     
	}
}

第二段代码在Java7之后的版本进行编译,都会引发Heap pollution

ErrorUtils.java:15:警告:[unchecked] 参数化 vararg类型List<String>的堆可能已受污染
				public static void faultyMethod(List<String>...listStrArray)
														^
一个警告

避免这个警告可以做如下处理:

  • 可以使用@SafeVarargs修饰引发该警告的方法或构造器,在Java9之后还可以使用该注解修饰私有实例方法
  • 可以使用@SuppressWarnings(“unchecked”)修饰
  • 编译时使用-Xlint:varargs选项

函数式接口与@FunctionalInterface

如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),该接口就是函数式接口,而@FunctionalInterface就是用来指定某个接口必须是函数式接口

@FunctionalInterface
public interface FunInterface
{
	static void foo()
	{
		System.out.println("foo类方法");
	}
	default void bar()
	{
		System.out.println("bar默认方法");
	}
	void test(); // 只定义一个抽象方法
	// void abc();
}

@FunctionalInterface会告诉编译器检查这个接口,保证该接口只能包含一个抽象方法,否则就会编译出错,该注解也是用来规避低级错误,例如如果放开上边的abc()方法,再进行编译就会报错

FunInterface.java:13:错误:意外的@FunctionalInterface注释
@FunctionalInterface
^
	FunInterface不是函数式接口
		在接口FunInterface中找到多个非覆盖抽象方法
1个错误
发布了207 篇原创文章 · 获赞 124 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/dawei_yang000000/article/details/105244884