Android 在接口中调用方法会导致空指针异常

Android 在接口中调用方法会导致空指针异常,android,interface,Android,Interface,出于解耦的原因,我想调用由类Foo实现的接口,但该接口总是返回null。这里有一个过于简单的例子来说明我在做什么。在实际项目中,有一个presenter类在其构造函数中接受计算接口,然后使用dagger 2调用方法来更新我的主要活动中的视图。在本例中,我无法在presenter类或主活动中初始化接口。我知道这是可行的,但我不知道怎么做 //Interface that has a couple abstract methods public Interface Computation{ publ

出于解耦的原因,我想调用由类Foo实现的接口,但该接口总是返回null。这里有一个过于简单的例子来说明我在做什么。在实际项目中,有一个presenter类在其构造函数中接受计算接口,然后使用dagger 2调用方法来更新我的主要活动中的视图。在本例中,我无法在presenter类或主活动中初始化接口。我知道这是可行的,但我不知道怎么做

//Interface that has a couple abstract methods
public Interface Computation{
public double add(double somenumber, double anothernumber);
public int multiply(int somenumber, int somenumber);
}

public class Foo implements Computation{
@Override
public double add(double somenumber, double anothernumber){
return somenumber + anothernumber;
};

@Override
public int multiply(int somenumber, int anothernumber){
return somenumber * anothernumber;
};
}

//main class
public class MainClass extends Activity{
private TextView tv;
Computation mComputation;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
tv = findviewById(R.id.textview);
tv.setText(mComputation.multiply(4, 9))//here mComputation is null always
}
}

发生
NullPointerException
是因为
计算
尚未实例化,因此它仍然为null

接口,如果你把它们当作一个对象来使用,就像你在这里做的一样,必须被实例化,因为你把它当作一个对象来对待

有几种解决方案可供您选择:

1) 您可以使用创建的
Foo
对象简单地实例化
Computation

public class MainClass extends Activity{
    private TextView tv;
    Computation mComputation = new Foo();
    ...
}
这将起作用,因为您正在使用
Foo
的一个实例,通过使用它的默认构造函数来实例化
Computation

2) 对于您心目中的方法,您可以简单地使用静态方法。这避免了创建接口实例的需要

public interface Computation{
    public static double add(double somenumber, double anothernumber){
        return somenumber + anothernumber;
    }    
    public static int multiply(int somenumber, int anothernumber){
        return somenumber * anothernumber;
    }
}
然后在您的主要活动中这样使用它:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv = findviewById(R.id.textview);
    tv.setText(Computation.multiply(4, 9))
}
您不需要
计算mComputation=newfoo()对象

3) 实际上,您可以只使用默认的接口方法,不需要创建
Foo

public interface Computation{
    default double add(double somenumber, double anothernumber){ 
        return somenumber + anothernumber;
    }
    default int multiply(int somenumber, int anothernumber){
        return somenumber * anothernumber;
    }
}
然后在你的主要活动中:

public class MainClass extends Activity implements Computation{
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findviewById(R.id.textview);
        tv.setText(multiply(4, 9))
    }
}

使用此解决方案,您只需实现
计算
接口,并可以简单地调用
乘法()
添加()
方法。如果您的方法足够简单,并且每个实现的方法功能都相同,那么使用默认方法有助于减少大量代码

我感谢你的快速回答。我会接受它,因为解决方案1是有效的。但是您需要更多关于解决方案2和3的澄清。因为我知道Java中不能有静态接口,也不能在Java中的接口中添加方法体。解决方案#2和#3实际上是Java 8中的新特性,因为Java 8带来了在接口中使用
静态
默认
方法的能力。这里有一个更详细的链接:另外,如果您想在Android应用程序中使用Java8功能,这里有Android的官方文档:在解决方案3中,您不允许在第二个方法中使用第一个默认方法中使用的相同参数名。