Java包注解和package-info.java文件的作用和用法

2023-05-16

1 问题背景

博主最近在深入学习Java注解,其中就了解到注解可用于修饰包声明,因为@Target元注解的value元素数组可以包含ElementType.PACKAGE元素,接着博主就发现@Deprecated注解就支持修饰包声明:

package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

博主直接尝试在包声明或包引入的语句前加上包注解,Java编译器却直接报错了,甚至还导致java.util.List没有被正确引用:

//编译报错:Package annotations should be in file package-info.java,即包注解只能用于package-info.java文件中
@Deprecated
package com.example;

//编译报错:Package annotations should be in file package-info.java,即包注解只能用于package-info.java文件中
@Deprecated
import java.util.List;

public class TestClass {
    //编译报错:Cannot resolve symbol 'List'
    List list;
}

根据错误提示,我们了解到包注解不能修饰常规Java文件中包声明或包引入语句,而只能用于修饰package-info.java文件中的包声明语句(也不能修饰package-info.java文件中的包引入语句)。

那么,我们就自行创建一个package-info.java文件吧。但是我们需要注意的是,我们不能通过常规的方法来创建一个package-info.java文件。例如,通过对任意包文件夹鼠标右键再依次选中"New"-“Java”,这种是创建标准的Java类的方式,而Java类名的命名规范中不能有-符号,因此通过这种方式创建会报错:
在这里插入图片描述
我们应当对任意包文件夹鼠标右键再依次选中"New"-"File""New"-"package-info.java",这样既可成功创建一个package-info.java文件:
在这里插入图片描述
当我们通过"New"-"File"的方式创建一个名为package-info.java的空文件时,IDE会提示咱们这个文件缺少了包声明的语句:
在这里插入图片描述

因此我们应该在package-info.java文件中手动编码当前路径的包声明语句:

package com.exmaple2;

我们通过"New"-"package-info.java"的方式创建一个package-info.java文件时,IDE会自动为我们在该文件中编码当前路径的包声明语句,与上述手动编码的包声明语句是完全一致的。

接着我们用@Deprecated注解修饰package-info.java文件中的包声明语句:

@Deprecated
package com.exmaple2;

我们发现上述代码符合语法规范,并没有报错,IDE甚至贴心地将划线标识com.example包已经过时了并给予了编译警告:
在这里插入图片描述

以上就是包注解的简单用法,即包注解只能用于修饰package-info.java文件中的包声明语句。

如果你对package-info.java文件的作用和包注解的详细用法特别感兴趣的话,你还可以继续查阅本文后续的内容。

2 package-info.java文件

package-info.java文件是一个特殊的Java文件,它里面主要包含3类语句:包注释、包注解和包声明,它可以被放在任意Java包对应的路径下。

下图是安卓开源项目Telegram包含的其中一个package-info.java文件,你可以看到博主我额外为这个文件加上了包注释:
在这里插入图片描述

2.1 package-info.java文件的作用

其中 package-info.java文件主要有下述的作用:

2.1.1 提供包级别的注释(Comment)

我们都知道可以为类、变量、方法等元素编写注释,但是如果我们想给某个Java包编写注释怎么办?在Java5之前,需要在Java包对应的路径下创建一个package.html文件,并在其body标签中编写Javadoc注释。而在Java5及之后的版本中,我们在Java包对应的路径下创建一个package-info.java文件来存放包的包声明、包注释和包注解:

/**
 * 这是安卓Telegram项目中com.google.android.exoplayer2.analytics包的注释文档
 *
 * @version 1.0
 * @author ChayChan
 * @description: com.google.android.exoplayer2.analytics包的注释文档
 * @date 2021/8/31  15:44
 */
@NonNullApi
package com.google.android.exoplayer2.analytics;

import com.google.android.exoplayer2.util.NonNullApi;

接着,我们在Telegram项目的目录~/Telegram/TMessagesProj/src/main/java中执行下述JavaDoc命令来递归生成Telegram项目com包及其所有子包和子文件的JavaDoc文档:

javadoc -d ../../../../Telegram-JavaDoc -author -version -subpackages com

在这里插入图片描述

2.1.2 提供包级别的注解(Annotation)

在Java5及之后的版本中,我们可以在某个Java包对应路径下的package-info.java文件中用包注解来修饰包声明语句。例如我们想指定某个Spring项目的其中一个Java包中所有类和接口的成员变量都是非空的,就可以用的spring-core库的@NonNullFields注解,例如下述的代码:

@NonNullApi
@NonNullFields
package com.baeldung.nullibility;

import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

但是请注意,上述提到的@NonNullApi@NonNullFields都是Spring 5的spring-core库引入的 jsr-305注解,需要额外添加com.google.code.findbugs:jsr305:3.0.2依赖项,否则将无法使用这些注解。

《Spring官方文档-空安全》文章中也提到:

没有必要也不推荐将JSR-305依赖项添加到项目中来利用Spring空安全注释。只有像基于Spring的库的项目,即在代码库中使用空安全注释的项目才应该添加com.google.code.findbugs:jsr305:3.0.2依赖项来避免编译警告。

也就是说,如果我们的项目不是基于Spring的库的项目,例如Android项目就没必要为了这几个空安全注解来引入相关的依赖。Android项目有自己的注解支持库,可以参考《Android官方文档-利用注解改进代码检查》文章。

3 总结

以上就是Java中引入的package-info.java文件和包注释的作用和用法,如果你的项目中需要包级别的注释的注解,那么你可以考虑在你的项目中使用package-info.java文件和包注释,否则就不用费心去关注这块的知识点啦。


本文参考文献:

javadoc 命令生成类的解释文档

StackOverFlow-What is package-info.java and how can I add it to my project?

StackOverFlow-Eclipse Juno - What is the use of package-info.java?

StackOverFlow-Why is package-info.java useful?

Java学习系列:package-info.java的作用

PACKAGE-INFO.JAVA 作用及用法详解

Baeldung-The package-info.java File

Annotation attributes with type parameters

How do I add package level annotations or edit package-info.java?

What do Java annotation ElementType constants mean?

Spring Framework Documentation Null-safety

Spring 5 core 中的 @NonNull 是个什么鬼?!

安卓中的@Nullable和NotNull 注释

Android官方文档-利用注解改进代码检查

雷元流-善用注解降低犯错率

简书-javadoc 命令生成类的解释文档

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java包注解和package-info.java文件的作用和用法 的相关文章

随机推荐