Java 基于注释的空分析-警告仅与数组参数一起出现

Java 基于注释的空分析-警告仅与数组参数一起出现,java,eclipse,annotations,nullable,eclipse-jdt,Java,Eclipse,Annotations,Nullable,Eclipse Jdt,在使用涉及数组的基于注释的空分析时,我收到以下(令人困惑的)警告: Null类型安全性(类型注释):类型“int[]”的表达式需要未经检查的转换才能符合“int@Nullable[]”的要求。 当我将未注释的int[]传递给int@Nullable[]参数时,就会发生这种情况 这是令人惊讶的。通常,只有当您获取一个可为null的值并尝试将其传递给一个非null参数时,这才是一个问题,但我正在做相反的事情——获取一个已知的非null(尽管没有注释)数组并将其传递给一个接受null的方法(Array

在使用涉及数组的基于注释的空分析时,我收到以下(令人困惑的)警告:

Null类型安全性(类型注释):类型“int[]”的表达式需要未经检查的转换才能符合“int@Nullable[]”的要求。

当我将未注释的
int[]
传递给
int@Nullable[]
参数时,就会发生这种情况

这是令人惊讶的。通常,只有当您获取一个可为null的值并尝试将其传递给一个非null参数时,这才是一个问题,但我正在做相反的事情——获取一个已知的非null(尽管没有注释)数组并将其传递给一个接受null的方法(
Arrays.equals

另外,对于非数组对象,这似乎不是问题。通常,可以将一个变量或返回(未注记、非数组)类型
T
分配给
@Nullable T

所以我的问题是
T
是数组类型时,为什么会发生这种变化


我的类是一个haseab/Auto可比较的代理,它使用一个原生类,使用了<代码> int []/COD>(从C++函数中获取)作为唯一标识符。我的包使用基于注释的空分析,而第三方包(带有本机类)不使用

以下是显示问题的简化版本:

TagKey.java:

package example;

import java.util.Arrays;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;

import other.Tag;

import com.google.common.collect.Interner;
import com.google.common.collect.Interners;

public class TagKey {

    private TagKey(Tag tag) {
        this.tag = tag;
    }

    public static TagKey forTag(Tag tag) {
        TagKey candidateKey = new TagKey(tag);
        return INTERNER.intern(candidateKey);
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(this.tag.getUniqueIdentifier());
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (this == obj) {
            return true;
        } else if (obj == null) {
            return false;
        } else if (getClass() != obj.getClass()) {
            return false;
        } else {
            return ((TagKey) obj).hasMatchingIdentifier(this.tag.getUniqueIdentifier()); // Warning appears here
        }
    }

    public boolean hasMatchingIdentifier(int @Nullable[] id) {
        return Arrays.equals(this.tag.getUniqueIdentifier(), id);
    }

    @SuppressWarnings("null") // Guava cannot use type parameter annotations due to backward compatibility with Java 6
    private static final Interner<TagKey> INTERNER = Interners.newWeakInterner();

    private final Tag tag;

}
/**
 * @author finnw
 *
 */
@org.eclipse.jdt.annotation.NonNullByDefault
package example;
Tag.java:(部分)


我当前使用的变通方法: 我宁愿避免这些方法:

  • @SuppressWarnings(“null”)
    添加到
    TagKey
    或其
    equals
    方法(生产版本稍微复杂一些,并且有让NPE尴尬的高风险。)

注:

  • 我的JDT版本是3.10.0.v20140606-1215
  • 早些时候,我犯了一个错误,声明了
    @Nullable int[]id
    。令人惊讶的是,没有关于这一点的警告消息,即使它暗示原语
    int
    元素可能是
    null
    ,这显然是错误的
添加此方法:

@SuppressWarnings("null")
public static int @Nullable[] getUniqueIdentifier(Tag tag) {
    return tag.getUniqueIdentifier();
}
然后:


这就是为什么我会忽略“未经检查的非注释转换”警告,直到支持空值配置文件,否则您要么到处抑制空值警告(这违背了这一点),要么为每个库创建带注释的包装方法。

任何由数组检查的数组。equals可以处理空值。您之前说的@Nullable int[]id是正确的,因为@Nullable没有定义数组中的项可以为null,它定义了参数(对象引用)可以为null。equals(null,null)返回true

private int[] a = null; 
是完全合理的代码。因此,您要检查的是数组引用是否匹配,如果所有元素都相互匹配,或者如果两个引用都为null,则为true。如果变量声明为int[],根据定义,其内部成员不能为null。也就是说,上述代码是合法的,这不是:

a[0] = null;

如果它被定义为Integer[],当然会有所不同,但它不是。

谢谢,但我真的不想这样做,因为我不确定它是否比
hasMatchingIdentifier(@Nullable Object)
有所改进。你知道为什么数组和非数组对象的行为不同吗?+1反正我认为你是对的,ABNA还不够成熟,还不能用于生产代码。但是我想知道谁会自愿为整个JRE创建空性配置文件。空性配置文件,也称为外部注释,将在EclipseMars(4.5)中得到支持。没有人使用JRE的整个API——只添加几个外部注释通常会对完全空检查的项目大有帮助-
return ((TagKey) obj).hasMatchingIdentifier(getUniqueIdentifier(this.tag));
private int[] a = null; 
a[0] = null;