7

我使用 IntelliJ 的空值检查机制来防止空指针崩溃。我已使用答案成功将所有 Java 方法参数默认设置为 @NonNull。

在创建用于在 Java中定义包注释的package-info.java之后。作为该包的直接后代的所有 java 文件在我的 Android Studio 项目中都有带有默认 @NonNull 参数的方法。

在此处输入图像描述

明显的问题是我需要为该包中的所有 Java 类定义@ParametersAreNonnullByDefault,即包括所有子包

如何定义 @ParametersAreNonnullByDefault 以便它向下传播到所有子包 java 文件?我希望我的所有内部代码的方法默认都用 @NonNull 注释。

在此处输入图像描述

/**
  * File: package-info.java
  * Make all method parameters @NonNull by default
  */
  @ParametersAreNonnullByDefault
  package com.intive.nearbyplaces.main;

  import javax.annotation.ParametersAreNonnullByDefault;
4

1 回答 1

9

问题是我不能强制 Android Studio 在所有子包中尊重@ParametersAreNonnullByDefault(即递归地用于com.company.name中的所有 java 文件)

但是,我编写了一个gradle 脚本来检查是否在每个子包文件夹中生成了package-info.java文件,并在必要时创建它。该脚本在assembleDebug任务之前运行。

因此,可以在项目中的所有 java 类上强制使用 @ParametersAreNonnullByDefault注释。

在此处下载源代码。请记住将第 19 行替换为您的包名

用法:

apply plugin: 'com.android.application'
apply from: 'nonnull.gradle'

android {
   compileSdkVersion 24
   buildToolsVersion "24.0.2"

   [...]
}

记得在.gitignore中包含package-info.java文件

//File: .gitignore 

package-info.java

检查样式规则:

<module name="JavadocPackage"/>

检查 package-info.java 是否包含在每个子包中。

来源:

/**
 *  File: nonnull.gradle
 *
 *  Generates package-info.java for appropriate packages
 *  inside src/main/java folder.
 *
 *  This is a workaround to define @ParametersAreNonnullByDefault for all Java classes in a package
 *  i.e. including all subpackages (note: edit package name in line no. 19).
 */
task generateNonNullJavaFiles(dependsOn: "assembleDebug", type: Copy) {
    group = "Copying"
    description = "Generate package-info.java classes"

    def infoFileContentHeader = getFileContentHeader();
    def infoFileContentFooter = getFileContentFooter();

    def sourceDir = file( "${projectDir}" + File.separatorChar + "src" + File.separatorChar +
            "main" + File.separatorChar + "java" + File.separatorChar +
            "com" + File.separatorChar + "company" + File.separatorChar + "name" )
    sourceDir.eachDirRecurse { dir ->
        def infoFilePath = dir.getAbsolutePath() + File.separatorChar + "package-info.java"

        if (!file(infoFilePath).exists()) {
            def infoFileContentPackage = getFileContentPackage(dir.getAbsolutePath());
            new File(infoFilePath).write(infoFileContentHeader +
                    infoFileContentPackage + infoFileContentFooter)
            println "[dir] " + infoFilePath + "  created";
        }
    }
    println "[SUCCESS] NonNull generator: package-info.java files checked"
}

def getFileContentPackage(path) {
    def mainSrcPhrase = "src" + File.separatorChar + "main" + File.separatorChar +
            "java" + File.separatorChar
    def mainSrcPhraseIndex = path.indexOf(mainSrcPhrase)
    def output = path.substring(mainSrcPhraseIndex)

    // Win hotfix
    if (System.properties['os.name'].toLowerCase().contains('windows')) {
        output = output.replace("\\", "/")
        mainSrcPhrase = mainSrcPhrase.replace("\\", "/")
    }

    return "package " + output.replaceAll(mainSrcPhrase, "").replaceAll(
            "/", ".") + ";\n"
}

def getFileContentHeader() {
    return  "/** javadoc goes here \n */\n" +
            "@ParametersAreNonnullByDefault\n" +
            "@ReturnValuesAreNonnullByDefault\n"
}

def getFileContentFooter() {
    return  "\n" +
            "import javax.annotation.ParametersAreNonnullByDefault;\n" +
            "\n" +
            "import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault;"
}

可以在这里找到为 src main、test 和 androidTest 文件夹生成包信息文件的扩展版本。

Findbugs 和皮棉:

确实适用于 findbugs & lint。

于 2016-10-17T16:34:23.757 回答