防止 Android Studio 检查将 Java 流链标记为包含可能的 NullPointerException
Posted
技术标签:
【中文标题】防止 Android Studio 检查将 Java 流链标记为包含可能的 NullPointerException【英文标题】:Prevent Android Studio Inspection from Flagging Java Stream chain as containing possible NullPointerException 【发布时间】:2019-06-18 23:27:44 【问题描述】:我正在编写一个实用方法来提取一组已包装的不可打包对象:
public interface UnparcelableHolder<U>
@Nullable U getUnparcelable();
public final class FragmentUtil
@Nullable
public static <U> List<U> getUnparcelableHolderListArgument(
@Nonnull Fragment fragment,
@Nonnull Class<UnparcelableHolder<U>> unparcelableHolderClass,
@Nonnull String key
)
@Nullable final Bundle arguments = fragment.getArguments();
if (arguments == null)
return null;
else
@Nullable final Parcelable[] parcelableArray = arguments.getParcelableArray(key);
if (parcelableArray == null)
return null;
else
return Arrays
.stream(parcelableArray)
.filter(unparcelableHolderClass::isInstance)
.map(unparcelableHolderClass::cast)
.filter(Objects::nonNull)
.map(UnparcelableHolder::getUnparcelable)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (unparcelableHolderClass.isInstance(parcelable))
@Nonnull final UnparcelableHolder<U> unparcelableHolder =
Objects.requireNonNull(unparcelableHolderClass.cast(parcelable));
return unparcelableHolder.getUnparcelable();
else
return null;
android Studio 警告我,我的.map(UnparcelableHolder::getUnparcelable)
调用可能会导致NullPointerException
。由于我之前的filter(Objects::nonNull)
电话,这不应该是可能的。如何告诉 Android Studio 的检查器我的代码是干净的?
这是使用 Android Studio 3.4 beta 2 构建的 MCVE is available on github:
build.gradle
:
apply plugin: 'com.android.application'
android
compileSdkVersion 28
defaultConfig
applicationId "com.github.hborders.streamsnonnulljsr305"
minSdkVersion 28
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
buildTypes
release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
compileOptions
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
dependencies
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
MainActivity.java
:
package com.github.hborders.streamsnonnulljsr305;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class MainActivity extends AppCompatActivity
class Foo
@Nonnull
private final String string;
Foo(@Nonnull String string)
this.string = string;
@Nonnull
String getString()
return string;
class Bar
@Nullable
private final Foo foo;
Bar(@Nullable Foo foo)
this.foo = foo;
@Nullable
Foo getFoo()
return foo;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Bar bar1 = new Bar(new Foo("foo"));
final Bar bar2 = new Bar(null);
final Bar[] bars = new Bar[]
null,
bar1,
bar2,
;
final List<String> strings = Arrays
.stream(bars)
.map(Bar::getFoo)
.filter(Objects::nonNull)
.map(Foo::getString)
.collect(Collectors.toList());
System.out.println("strings: " + strings);
.map(Foo::getString)
调用也会出现同样的问题。具有讽刺意味的是,Android Studio 并没有抱怨我的 .map(Bar::getFoo)
调用,尽管它肯定会抛出 NullPointerException
。
【问题讨论】:
getUnparcelable()
的签名是什么?
我在上面的 sn-p 中声明了它,但我只是注意到我在转录时弄错了可空性。我编辑了帖子。这是签名:public interface UnparcelableHolder<U> @Nullable U getUnparcelable();
我不确定它是抱怨 getUnparcelable()
被 null
对象调用,还是 getUnparcelable()
可能返回 null
对象。尝试暂时将签名更改为 @NotNull U getUnparcelable();
并查看 Lint 警告是否更改。如果是这样,那么它在抱怨来自getUnparcelable()
的返回值。如果没有,那么您可能只是遇到了 Lint 限制,因为它无法知道在您的情况下 filter()
恰好返回非null
对象。
我认为它抱怨getUnparcelable()
被null
调用,因为.map(unparcelableHolderClass::cast)
也可以返回null
,它不会抱怨。
【参考方案1】:
这是一个 Android Studios 错误,因为 Android Studios 的建议在这里都不起作用。
没有警告:
应用建议并收到警告:
它还建议在已经存在时插入.filter(Objects::nonNull)
步骤。
所以这是一个明确的 AS 错误。
这是针对此问题的真正 MCVE:
import android.support.annotation.Nullable; // or any nullable you care to use
import java.util.Arrays;
import java.util.Objects;
public class MCVE
class Foo
class Bar
@Nullable
private final Foo foo;
Bar(@Nullable Foo foo)
this.foo = foo;
@Nullable
Foo getFoo()
return foo;
public void mcve()
final Bar[] bars = new Bar[]
new Bar(new Foo()),
;
Arrays.stream(bars)
.map(Bar::getFoo)
.filter(Objects::nonNull)
.map(Foo::toString);
【讨论】:
提交此错误的合适位置是什么?以上是关于防止 Android Studio 检查将 Java 流链标记为包含可能的 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章