Android studio 防止Android Studio Inspection将Java流链标记为包含可能的NullPointerException
我正在编写一个实用方法来提取包装的不可分割对象数组:Android studio 防止Android Studio Inspection将Java流链标记为包含可能的NullPointerException,android-studio,intellij-idea,nullpointerexception,java-stream,intellij-inspections,Android Studio,Intellij Idea,Nullpointerexception,Java Stream,Intellij Inspections,我正在编写一个实用方法来提取包装的不可分割对象数组: 公共接口不可拆分持有者{ @可为null的U getUnparcelable(); } 公共最终类FragmentUtil{ @可空 公共静态列表GetUnparableHolderListArgument( @非空片段片段, @非Null类unparcelableHolderClass, @非空字符串键 ) { @可为null的最终束参数=fragment.getArguments(); if(参数==null){ 返回null; }否则{
公共接口不可拆分持有者{
@可为null的U getUnparcelable();
}
公共最终类FragmentUtil{
@可空
公共静态列表GetUnparableHolderListArgument(
@非空片段片段,
@非Null类unparcelableHolderClass,
@非空字符串键
) {
@可为null的最终束参数=fragment.getArguments();
if(参数==null){
返回null;
}否则{
@可为空的最终Parcelable[]parcelableArray=参数。getParcelableArray(键);
如果(parcelableArray==null){
返回null;
}否则{
返回数组
.溪流(地块阵列)
.filter(unparcelableHolderClass::isInstance)
.map(unparcelableHolderClass::cast)
.filter(对象::非空)
.map(UnparcelableHolder::getUnparcelable)
.filter(对象::非空)
.collect(Collectors.toList());
}
if(不可拆分的持有者类别isInstance(可打包)){
@非Null最终不可拆分持有者不可拆分持有者=
对象.requirennoull(不可拆分的持有者类.cast(可打包));
返回unparcelableHolder.getUnparcelable();
}否则{
返回null;
}
}
}
}
Android Studio警告我,我的.map(UnparcelableHolder::getUnparcelable)
调用可能导致NullPointerException
。这应该是不可能的,因为我前面的过滤器(Objects::nonNull)
调用。我如何告诉Android Studio的检查员我的代码是干净的
这是安卓Studio 3.4 beta 2的内置版本:
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);
}
}
package com.github.hborders.streamsnoulljsr305;
导入android.support.v7.app.AppActivity;
导入android.os.Bundle;
导入java.util.array;
导入java.util.List;
导入java.util.Objects;
导入java.util.stream.collector;
导入javax.annotation.Nonnull;
导入javax.annotation.Nullable;
公共类MainActivity扩展了AppCompatActivity{
福班{
@非空
私有最终字符串;
Foo(@Nonnull字符串){
this.string=string;
}
@非空
字符串getString(){
返回字符串;
}
}
分类栏{
@可空
私人决赛福福;
条(@Nullable Foo Foo){
this.foo=foo;
}
@可空
Foo getFoo(){
返回foo;
}
}
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
最终条形图1=新条形图(新Foo(“Foo”));
最终棒2=新棒(空);
最终钢筋[]钢筋=新钢筋[]{
无效的
bar1,
bar2,
};
最终列表字符串=数组
.溪流(巴)
.map(Bar::getFoo)
.filter(对象::非空)
.map(Foo::getString)
.collect(Collectors.toList());
System.out.println(“字符串:“+strings”);
}
}
同样的问题也发生在
.map(Foo::getString)
调用上。具有讽刺意味的是,Android studio并没有抱怨我的.map(Bar::getFoo)
调用,尽管它确实抛出了一个NullPointerException
这是Android studio的一个bug,因为Android studio的建议在这里都不起作用
没有警告:
应用建议并获得警告:
它还建议插入.filter(Objects::nonNull)
步骤(如果已经存在)
所以这是一个明确的错误
这是本期真正的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);
}
}
getUnparcelable()
的签名是什么?我在上面的代码片段中声明了它,但我刚刚注意到我在转录它时把可空性搞错了。我编辑了这篇文章。这是签名:public interface unparcelable holder{@Nullable U getUnparcelable();}
我不确定它是否抱怨getUnparcelable()
在null
对象上被调用,或者getUnparcelable()
可能返回null
对象。尝试将签名临时更改为@NotNull U getUnparcelable()代码>并查看林特警告是否更改。如果是,则它会抱怨getUnparcelable()
的返回值。如果没有,那么您可能只是遇到了Lint限制,因为它无法知道在您的情况下,filter()
恰好返回了非null
对象。我认为它在抱怨getUnparbelable()
在null
上被调用,因为.map(UnparcellabelHolderClass::cast)
也可以返回null
,它不会对此抱怨。在什么地方可以提交此错误?