Improve code inspection with annotations


使用注解改进代码检查

[Improve code inspection with annotations]
使用代码检查工具(例如 Lint)可以帮助您找到问题并改进代码,不过,检查工具只能推断这么多信息[can only infer so much]。例如,Android 资源 ID 使用 int 标识字符串、图形、颜色和其他资源类型,因此,检查工具无法告诉您何时指定字符串资源以及应在什么地方指定颜色(因为他们都是用的 int 类型)。在这种情况下,您的应用可能无法正确渲染或根本无法运行,即使使用代码检查也是如此(因为代码检测工具无法检测这些问题)。

您可以使用注解向 Lint 之类的代码检查工具提供提示,帮助检测这些更细微的代码问题[more subtle code problems]。您可以将注解作为元数据标记[metadata tags]附加至变量、参数和返回值,用于检查方法返回值、传递的参数以及本地变量和字段。如果与代码检查工具搭配使用,注解可以帮助您检测问题,例如 null 指针异常和资源类型冲突。

Android 通过 Annotations Support Library 支持各种注解。您可以通过 android.support.annotation 软件包获取该库。

注意:如果模块依赖于注释处理器[annotation processor],则必须使用`annotationProcessor`依赖关系配置来添加该依赖关系。 要了解更多信息,请阅读 使用注释处理器依赖关系配置

向您的项目添加注解

[Add annotations to your project]
要在您的项目中启用注解,请向您的库或应用添加 support-annotations 依赖项。添加的任何注解都会在您随后运行代码检查或 lint 任务时进行检查。

添加支持注解库依赖项

[Add the support annotations library dependency]
Support Annotations library 是 Android Support Repository 的一部分。要向您的项目添加注解,您必须下载 support repository 并向 build.gradle 文件中添加 support-annotations 依赖项。
  • 点击工具栏中的  打开 SDK Manager,或者选择 Tools > Android > SDK Manager。
  • 点击 SDK Tools 标签,展开 Support Repository 并选中 Android Support Repository 复选框
  • 点击 OK,继续安装向导的说明操作,安装软件包。
  • 将以下代码行添加到 build.gradle 文件的 dependencies 块中,向您的项目添加 support-annotations 依赖项。您下载的库版本可能较高,因此,确保您在此指定的值与上面指定的版本匹配。然后在显示的工具栏或同步通知中,点击 Sync Now。
dependencies { implementation 'com.android.support:support-annotations:24.2.0' }
1
1
 
1
dependencies { implementation 'com.android.support:support-annotations:24.2.0' }

如果您在自己的 library 模块中使用注解,注解将作为 Android 归档 (Android Archive,AAR) 工件[artifact]的一部分以 XML 格式添加到 annotations.zip 文件中。添加 support-annotations 依赖项不会为您的库的任何下游用户[downstream users]引入依赖关系。

If you want to use annotations in a Gradle module that is not using the Android plugin for Gradle (com.android.application or com.android.library) but is using the Gradle Java plugin instead, you must include the SDK repository explicitly明确 because the Android support libraries are not available from the JCenter Java repository:
repositories {
  jcenter()
  maven { url '<your-SDK-path>/extras/android/m2repository' }
}
4
4
 
1
repositories {
2
  jcenter()
3
  maven { url '<your-SDK-path>/extras/android/m2repository' }
4
}
注:如果您使用 appcompat 库,则无需添加 support-annotations 依赖项。因为 appcompat 库已经依赖注解库,您可以访问相关注解。

要查看支持存储库中包含的完整注解列表,请查看 Support Annotations library reference,或者使用自动填充功能显示 import android.support.annotation. 语句的可用选项。

运行代码检查

[Run code inspections]
要使用 Android Studio 启动代码检查(包含验证注解和自动 Lint 检查),请从菜单栏中选择 Analyze > Inspect Code。Android Studio 将显示冲突消息,在您的代码与注解冲突的地方,标记潜在[potential]问题,并建议可能的解决方法。

您还可以通过  使用命令行运行 lint 任务 来强制注解。尽管这对标记 持续集成服务器遇到的问题可能有用,请注意,lint 任务并不会强制 nullness 注解(只有 Android Studio 会强制)。如需了解有关启用和运行 Lint 检查的详细信息,请参阅 使用 Lint 改进您的代码

请注意,尽管注解冲突会生成警告,但这些警告不会阻止您的应用编译。

Nullness 注解

添加 @Nullable 和 @NonNull 注解,以检查给定变量、参数或返回值的 nullness。 @Nullable 注解指示可以为 null 的变量、参数或返回值,而 @NonNull 则指示不可为 null 的变量、参数或返回值。

例如,如果一个包含 null 值的局部变量作为已附加 @NonNull 注解的参数传递到某个方法,则构建代码将生成一个指示非 null 冲突的警告。另一方面,对于通过 @Nullable 标记的方法的结果,如果不先检查其是否为 null,那么在尝试引用它时将生成 nullness 警告。只有在每次使用方法时都应明确检查是否为 null 的情况下,才应对方法返回值使用 @Nullable。

下面的示例会将 @NonNull 注解附加到 context 与 attrs 参数,以检查传递的参数值是否不为 null。它还会检查 onCreateView() 方法本身是否不会返回 null:
import android.support.annotation.NonNull;

@NonNull //检查 onCreateView() 方法本身是否不会返回 null,如果有可能返回 null,则提示
@Override
public View onCreateView(String name, @NonNull Context context, @NonNull AttributeSet attrs) {
    ...
}
7
7
 
1
import android.support.annotation.NonNull;
2
3
@NonNull //检查 onCreateView() 方法本身是否不会返回 null,如果有可能返回 null,则提示
4
@Override
5
public View onCreateView(String name, @NonNull Context context, @NonNull AttributeSet attrs) {
6
    ...
7
}

Nullability 分析

Android Studio 支持通过运行 nullability 分析,在您的代码中 自动推断和插入 nullness 注解。Nullability 分析会在您代码的 整个方法层次结构中[throughout the method hierarchies]扫描协定类,以检测:
  • 可返回 Null 的调用方法
  • 不会返回 Null 的方法
  • 可以为 Null 的变量,如字段、局部变量和参数
  • 不能为 Null 值的变量,如字段、局部变量和参数
然后,此分析将自动在已检测到的位置[detected locations]插入相应的 null 注解。

要在 Android Studio 中运行 nullability 分析,请选择 Analyze > Infer Nullity。Android Studio 会在代码中已检测到的位置插入 @Nullable 和 @NonNull 注解。运行 null 分析后,最好验证一下插入的这些注解。

注:当添加 nullness 注解时,自动填充可能会建议您添加 IntelliJ 的 @Nullable 和 @NotNull 注解而不是 Android 的 null 注解,并且可能会自动导入相应的库。不过,Android Studio Lint 检查器仅会查找 Android null 注解。验证您的注解时,请确认您的项目使用 Android null 注解,以便 Lint 检查器可以在代码检查期间正确通知您。

Nullability 案例

例如,如下两个方法:
private void testNullable(String text) {
	Log.i("bqt", "" + (text == null ? 0 : text.length()));
}

private void test(String text) {
	Log.i("bqt", "" + text.length());
}
7
7
 
1
private void testNullable(String text) {
2
    Log.i("bqt", "" + (text == null ? 0 : text.length()));
3
}
4
5
private void test(String text) {
6
    Log.i("bqt", "" + text.length());
7
}
1、调用时如果传入null,则IDE可能就会有如下提示:
testNullable(null);
test(null);
2
2
 
1
testNullable(null);
2
test(null);

按照提示修改后 test 方法就是这样:
private void test(@Nullable String text) {
	Log.i("bqt", "" + text.length());
}
3
3
 
1
private void test(@Nullable String text) {
2
    Log.i("bqt", "" + text.length());
3
}
然而接下来就会有新的提示:
按照提示修改其实就是修改成和 testNullable 类似的样子。

2、不对上述两个方法进行任何修改,这时如果 运行检测,检测后会提示你 testNullable 这个方法可以添加  @Nullable 注解,而  test 方法并没有提示
点击下面的 infer... 
这时会将 testNullable 修改成下面的样子:
private void testNullable(@Nullable String text) {
	Log.i("bqt", "" + (text == null ? 0 : text.length()));
}
3
3
 
1
private void testNullable(@Nullable String text) {
2
    Log.i("bqt", "" + (text == null ? 0 : text.length()));
3
}

资源注解

验证资源类型可能非常有用,因为 Android 对资源(例如 drawable and string 资源)的引用以整型形式传递。需要参数来引用特定类型资源(例如 drawable)的代码可以作为预计的引用类型 int 传入,不过实际可能会被引用不同类型的资源,例如 R.string 资源。

例如,如下两个方法:
private void test(int resId) {
	Log.i("bqt", "" + resId);
}

private void testResource(@StringRes int resId) { //添加 @StringRes 注解会检查资源参数是否包含 R.string 引用
	Log.i("bqt", "" + resId);
}
7
7
 
1
private void test(int resId) {
2
    Log.i("bqt", "" + resId);
3
}
4
5
private void testResource(@StringRes int resId) { //添加 @StringRes 注解会检查资源参数是否包含 R.string 引用
6
    Log.i("bqt", "" + resId);
7
}
如果这样使用:
test(R.string.app_name);
test(R.drawable.icon);
testResource(R.string.app_name);
testResource(R.drawable.icon);//在代码检查期间,如果参数中未传入 R.string 引用,注解将生成警告
4
4
 
1
test(R.string.app_name);
2
test(R.drawable.icon);
3
testResource(R.string.app_name);
4
testResource(R.drawable.icon);//在代码检查期间,如果参数中未传入 R.string 引用,注解将生成警告
会有如下的提示:

其他资源类型的注解(例如 @DrawableRes、@DimenRes、@ColorRes 和 @InterpolatorRes)可以使用相同的注解格式添加并在代码检查期间运行。如果您的参数支持多种资源类型,您可以在给定参数上添加更多注解。使用 @AnyRes 能够指示注解的参数可为任意类型的 R 资源。

尽管您可以使用 @ColorRes 指定某个参数应为颜色资源,但是颜色整型(RRGGBB 或 AARRGGBB 格式)无法识别为颜色资源。请改用 @ColorInt 注解指示某个参数必须为颜色整型。构建工具会标记不正确代码,该代码会将颜色资源 ID(例如 android.R.color.black)而不是颜色整型传递到已注解方法。
private void testColorInt(@ColorInt int color) {
	Log.i("bqt", "" + color);
}

private void testColorRes(@ColorRes int resId) { //
	Log.i("bqt", "" + resId);
}
7
7
 
1
private void testColorInt(@ColorInt int color) {
2
    Log.i("bqt", "" + color);
3
}
4
5
private void testColorRes(@ColorRes int resId) { //
6
    Log.i("bqt", "" + resId);
7
}
testColorInt(0xff00ff);
testColorInt(0xffaa00ff);
testColorRes(R.color.color_aabbcc);
testColorRes(R.color.color_aabbccdd);
4
4
 
1
testColorInt(0xff00ff);
2
testColorInt(0xffaa00ff);
3
testColorRes(R.color.color_aabbcc);
4
testColorRes(R.color.color_aabbccdd);
以下两种引用方式则会提示:
testColorInt(R.color.color_aabbccdd);
testColorRes(0xff00ff);
2
2
 
1
testColorInt(R.color.color_aabbccdd);
2
testColorRes(0xff00ff);

线程注解

线程注解可以检查某个方法是否从特定类型的线程调用。支持以下线程注解:
@MainThread
@UiThread
@WorkerThread
@BinderThread
@AnyThread
5
5
 
1
@MainThread
2
@UiThread
3
@WorkerThread
4
@BinderThread
5
@AnyThread
注:构建工具会将 @MainThread 和 @UiThread 注解视为可互换,因此,您可以从 @MainThread 方法调用 @UiThread 方法,反之亦然。不过,如果系统应用在不同线程上带有多个视图,UI 线程可与主线程不同。因此,您应使用 @UiThread 标注与应用的视图层次结构关联的方法,使用 @MainThread 仅标注与应用生命周期关联的方法。

如果某个类中的所有方法具有相同的线程要求,您可以向该 添加一个线程注解,以验证该类中的所有方法是否均从相同类型的线程调用。
线程注解的一个常见用途是验证 AsyncTask 类中的方法覆盖[validate method overrides],因为此类会执行后台操作并将结果仅发布到 UI 线程上。

值约束注解

[Value constraint annotations]
使用 @IntRange、@FloatRange 和 @Size 注解可以验证传递的参数的值。在应用到[applied to]用户可能弄错其范围的参数时,@IntRange 和 @FloatRange 都非常有用。

@IntRange 注解可以验证整型或长整型参数值是否位于指定范围内。下面的示例可以确保 alpha 参数值在 0 至 255 范围内:
public void setAlpha(@IntRange(from=0,to=255) int alpha) { … }
1
1
 
1
public void setAlpha(@IntRange(from=0,to=255) int alpha) {  }

@FloatRange 注解可以检查 float or double 参数值是否位于指定的浮点值范围内。下面的示例可以确保 alpha 参数值在 0.0 至 1.0 范围内:
public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}
1
1
 
1
public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}

@Size 注解可以检查集合或数组的大小,以及字符串的长度。@Size 注解可用于验证以下 qualities:
  • 表示最小大小,例如 @Size(min=1) 可以检查某个集合是否不为空(至少包含一个元素)
  • 表示最大大小,例如 @Size(max=2)
  • 表示确切大小,例如 @Size(3) 可以验证某个数组是否刚好包含三个值
  • 表示大小必须为数字的倍数,例如 @Size(multiple=2)

权限注解

使用 @RequiresPermission 注解可以验证方法调用方的权限。要检查有效权限列表中是否存在某个权限,请使用 anyOf 属性。要检查是否存在一组权限,请使用 allOf 属性。下面的示例会标注 setWallpaper() 方法,以确保方法的调用方拥有 permission.SET_WALLPAPERS 权限:
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;
2
2
 
1
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
2
public abstract void setWallpaper(Bitmap bitmap) throws IOException;

此示例要求 copyFile() 方法的调用方同时具有外部存储空间的读写权限:
@RequiresPermission(allOf = {
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, String source) 
4
4
 
1
@RequiresPermission(allOf = {
2
    Manifest.permission.READ_EXTERNAL_STORAGE,
3
    Manifest.permission.WRITE_EXTERNAL_STORAGE})
4
public static final void copyFile(String dest, String source) 

对于 intent 上的权限,请将权限要求添加到定义 intent 操作名称的字符串字段上:
@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
2
2
 
1
@RequiresPermission(android.Manifest.permission.BLUETOOTH)
2
public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";

对于您需要单独[separate]读写权限的内容提供程序的权限,请在 @RequiresPermission.Read 或 @RequiresPermission.Write 注解中包含每个权限要求:
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
3
3
 
1
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
2
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
3
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");

间接权限

[Indirect permissions]
如果权限依赖于提供给方法参数的特定值[the specific value supplied to a method's parameter],请对参数本身使用 @RequiresPermission,而不用列出具体权限。例如, startActivity(Intent) 方法会对传递到方法的 intent 使用间接权限:
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle) {...}
1
1
 
1
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle) {...}

在您使用间接权限时,构建工具将执行 数据流分析[data flow analysis]以检查传递到方法的参数是否具有 any @RequiresPermission 注解。随后,它们会对方法本身强制参数的任何现有注解[They then enforce any existing annotations from the parameter on the method itself]。在 startActivity(Intent) 示例中,当一个不具有相应权限的 intent 传递到方法时,Intent 类中的注解会针对 startActivity(Intent) 的无效使用生成警告:

构建工具会在 startActivity(Intent) 上从 Intent 类中相应 intent 的 action 名称的注解生成警告:
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";
3
3
 
1
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
2
@RequiresPermission(Manifest.permission.CALL_PHONE)
3
public static final String ACTION_CALL = "android.intent.action.CALL";
如果需要,在标注方法的参数时,您可以将 @RequiresPermission 替换为 @RequiresPermission.Read 和/或 @RequiresPermission.Write。不过,间接权限 @RequiresPermission 不应与读取或写入权限注解搭配使用。

返回值注解

使用 @CheckResult 注解可以验证实际使用的是方法的结果还是返回值。添加 annotation 来阐明[clarify] 可能令人困惑的方法 [ potentially confusing methods ]的结果,而不是使用 @CheckResult annotating 每个 non-void 方法。例如,新 Java 开发者经常误认为 String.trim() 会移除原始字符串中的空格。使用 @CheckResult 标注方法会在调用方未对方法返回值作任何处理的地方标记 String.trim() 的使用。

下面的示例会标注 checkPermissions() 方法,以确保实际引用方法的返回值。它还会将 enforcePermission() 方法指定为要向开发者建议的替换方法:
@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);
2
2
 
1
@CheckResult(suggest="#enforcePermission(String,int,int,String)")
2
public abstract int checkPermission(@NonNull String permission, int pid, int uid);

CallSuper 注解

使用 @CallSuper 注解可以验证替换方法是否会调用方法的超类实现。下面的示例会标注 onCreate() 方法,以确保任何替换方法实现都会调用 super.onCreate():
@CallSuper
protected void onCreate(Bundle savedInstanceState) { ... }
2
2
 
1
@CallSuper
2
protected void onCreate(Bundle savedInstanceState) { ... }

Typedef 注解

使用 @IntDef 和 @StringDef 注解,以便能够创建整型和字符串集的 枚举注解[enumerated annotations]来验证其他类型的代码引用[validate other types of code references]。Typedef 注解可以确保 特定的[particular] 参数、返回值或字段 引用一组特定的常量集[a specific set of constants]。它们还使代码 完成能够自动提供[completion to automatically offer]允许的常量。

Typedef 注解使用 @interface 声明新的枚举注解类型[declare the new enumerated annotation type]。@IntDef 和 @StringDef 注解与 @Retention 一起[along with]可以标注新注解[annotate the new annotation],并且是定义枚举类型所必需的[are necessary in order to define the enumerated type]。@Retention(RetentionPolicy.SOURCE) 注解可以告知编译器不将枚举的注解数据存储在 .class 文件中。

下面的示例说明了创建注解的具体步骤,此注解可以确保作,为方法参数传递的值引用一个定义的常量[a value passed as a method parameter references one of the defined constants]:
import android.support.annotation.IntDef;

public abstract class ActionBar {
    //定义 NavigationMode 注解能接受的常量列表
    @Retention(RetentionPolicy.SOURCE) //告知编译器不将枚举的注解数据存储在 .class 文件中
    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) //标注新注解
    public @interface NavigationMode {} //声明新的枚举注解类型

    //声明常量
    public static final int NAVIGATION_MODE_STANDARD = 0;
    public static final int NAVIGATION_MODE_LIST = 1;
    public static final int NAVIGATION_MODE_TABS = 2;

    @NavigationMode //使用注释装饰目标方法
    public abstract int getNavigationMode();
    public abstract void setNavigationMode(@NavigationMode int mode); //Attach the annotation
}
17
17
 
1
import android.support.annotation.IntDef;
2
3
public abstract class ActionBar {
4
    //定义 NavigationMode 注解能接受的常量列表
5
    @Retention(RetentionPolicy.SOURCE) //告知编译器不将枚举的注解数据存储在 .class 文件中
6
    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) //标注新注解
7
    public @interface NavigationMode {} //声明新的枚举注解类型
8
9
    //声明常量
10
    public static final int NAVIGATION_MODE_STANDARD = 0;
11
    public static final int NAVIGATION_MODE_LIST = 1;
12
    public static final int NAVIGATION_MODE_TABS = 2;
13
14
    @NavigationMode //使用注释装饰目标方法
15
    public abstract int getNavigationMode();
16
    public abstract void setNavigationMode(@NavigationMode int mode); //Attach the annotation
17
}
在您构建此代码时,如果 mode 参数不引用一个定义的常量,则会生成警告。
您还可以组合[combine...and] @IntDef 和 @IntRange,以指示整型可以是给定的常量集或某个范围内[within a range]的值。

允许将常量与标志相结合

[Enable combining constants with flags]
如果用户可以将允许的常量与标志(例如 |  &  ^ 等等)相结合,则您可以通过 flag 属性定义一个注解,以检查某个参数或返回值是否引用了有效模式[references a valid pattern]。下面的示例将使用一组有效的 DISPLAY_ 常量创建 DisplayOptions 注解:
@IntDef(flag=true, value={ DISPLAY_USE_LOGO, DISPLAY_SHOW_HOME, DISPLAY_HOME_AS_UP, DISPLAY_SHOW_TITLE, DISPLAY_SHOW_CUSTOM })
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayOptions { ... }
3
3
 
1
@IntDef(flag=true, value={ DISPLAY_USE_LOGO, DISPLAY_SHOW_HOME, DISPLAY_HOME_AS_UP, DISPLAY_SHOW_TITLE, DISPLAY_SHOW_CUSTOM })
2
@Retention(RetentionPolicy.SOURCE)
3
public @interface DisplayOptions { ... }
在您使用注解标志构建代码时,如果经过修饰的参数或返回值不引用有效模式,则将生成警告。

Keep 注解

@Keep注释确保在构建过程中压缩代码时不会删除带注释的类或方法。 此注释通常添加到通过反射访问的方法和类中,以防止编译器将代码视为未使用。
有关如何缩小代码并指定不应删除哪些代码的详细信息,请参阅 Shrink Your Code and Resources

代码可访问性注解

[Code visibility annotations]
使用以下注解表示[denote]代码的特定部分[specific portions of code](例如方法,类,字段或包)的可见性。

使测试可见

[Make visible for testing]
@VisibleForTesting  注解表明, 注解方法比通常需要的方法更可见,以使该方法可测试。 此注释具有可选的 otherwise 参数,如果不是为了使测试可见,则可以指定方法的可见性。 Lint 使用 otherwise 参数来强制执行预期的可见性[intended visibility]。

在下面的示例中,myMethod()通常是私有的,但它对于测试来说是 package-private。 使用以下 VisibleForTesting.PRIVATE 指定,如果从私有访问允许的上下文(例如来自不同的编译单元)调用此方法,则lint将显示一条消息。
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) //private
void myMethod() { … } //package-private
2
2
 
1
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) //private
2
void myMethod() {  } //package-private
您还可以指定 @VisibleForTesting(otherwise = VisibleForTesting.NONE) 以指示仅存在用于测试的方法。此表单与使用 @RestrictTo(TESTS) 相同。他们都执行相同的lint检查。

限制API

[Restrict an API]
@RestrictTo 注解表明对带注解的API(包,类或方法)的访问受到如下限制。

  • 子类
使用注解  @RestrictTo(RestrictTo.Scope.SUBCLASSES) 仅限制 [ restrict ]对子类 API 访问。
只有扩展带注释类[extend the annotated class]的类才能访问此API。 Java 的 protected 修饰符不够严格[restrictive enough],因为它允许从同一个包中的不相关类[unrelated classes]进行访问。同样,在某些情况下,您希望将方法保持公开以用于将来的灵活性[future flexibility],因为您永远不能将以前 protected 和 overridden 方法公开,但是您希望提供该类用于 类或子类中的用法的提示[but you want to provide a hint that the class is intended for usages within the class or from subclasses, only]。


使用注解 @RestrictTo(RestrictTo.Scope.GROUP_ID) 仅限制[restrict]对库的API访问。
只有您的库代码才能访问带注释的API。 这使您不仅可以在任何所需的 包层次结构[package hierarchy]中组织代码[organize your code],还可以在一组相关库之间共享代码。 此选项已经可用于支持库,这些库具有许多 not meant for external use 的实现代码,但必须设为 public 以能在各种补充支持库[complementary support libraries]中共享。
注意: Android suport library 类和包现在使用 with @RestrictTo(GROUP_ID) 注解,这意味着如果您不小心[accidentally]使用这些实现类,lint会警告您 这样做是不鼓励[discouraged]的。

  • 测试
使用注解 @RestrictTo(RestrictTo.Scope.TESTS) 来阻止[prevent]其他开发人员访问您的测试API。
只有测试代码才能访问带注释的API。这可以防止其他开发人员使用API进行开发,而您的这些API仅用于测试目的。

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.
上次更新日期:四月 25, 2018

2018-7-30

猜你喜欢

转载自www.cnblogs.com/baiqiantao/p/9393244.html