为什么在Java 8

时间:2018-06-16 22:00:39

标签: java-8 functional-interface

如果我们只有一个抽象方法的接口,它默认是功能接口。任何人都可以解释@FunctionalInterface注释带来的额外优势吗?

我知道如果我们添加@FunctionalAnnotation,它将不允许有人在界面中添加另一个抽象方法,因为它会产生编译错误,但我的观点是即使你不使用@FucntionalInterface注释,那么另外,如果有人会添加另一个抽象方法,它会破坏代码中所有现有的lambda表达式,编译器会抱怨。

例如:

如果我有以下界面:

public interface User {

    Integer fetchData(Integer userId);
}

以下实施:

public class UserImpl implements User{

    @Override
    public Integer fetchData(Integer userId) {
        return 1;
    }
}

以及以下用法:

公共类TestFunctionalInterface {

public static void main(String[] args) {
    User user = a -> a*2;
    System.out.println("FetchedData:"+user.fetchData(2));
}

}

现在,如果我尝试在界面中添加另一种方法,如下所示:

public interface User {

    Integer fetchData(Integer userId);

    Integer fetchLoginDetails(Integer userId);

}

编译器在下面的代码中抱怨:

public class TestFunctionalInterface {

    public static void main(String[] args) {
        User user = a -> a*2;
        System.out.println("FetchedData:"+user.fetchData(2));
    }

}

在线用户user = a - >一个* 2;

带有消息“此表达式的目标类型必须是有效的  接口”。

4 个答案:

答案 0 :(得分:2)

如果其他模块正在使用该接口,则不会发生编译错误,例如,如果该接口通过依赖项可用。有人使用你的模块可以安全地在lambda中使用该函数,而不用担心以后的更新会破坏他们的代码。

答案 1 :(得分:1)

功能界面只能有一个抽象方法。如果您有两种抽象方法,那么您的界面将不再起作用。

如果你有一个抽象方法,你可以使用lambda表达式。

如果你看到@FunctionalInterface注释,你知道你不应该添加任何新方法,因为它会破坏设计。

如果向任何java接口添加新的抽象方法,它将会破坏代码,因为您需要为具体类提供实现

答案 2 :(得分:1)

通过@functionalInterface保护接口的主要优点是使用lambda实例化它们。

Lambda声明只能声明一个代码块,所以如果你的接口没有保护,有些会添加一个抽象方法你的lambda没有更多的意义......

为什么强烈建议不要用lambda实现一些隐式功能接口。

因此,如果您想通过lambda方式实现此接口,我建议您添加一个安全性的注释。如果你不想要这种实现,或者如果你的界面会发生变化或者有改变的风险,那么就不要这样做了

答案 3 :(得分:0)

限制开发者

是的,这个@FunctionalInterface注解是为了确保开发者在这个接口中只写一个抽象方法,为什么?因为如果再有一个抽象类意味着 lambda 表达式 就失去了它的特性。

正确的例子

@FunctionalInterface
public interface TestFun {
     void test();
}

错误代码

@FunctionalInterface
public interface TestFun {
     void test();
     void m(); // new methods added will lost @FunctionalInterface it's feature 
}

这是什么想法?

让我们使用 TestFun 接口使用 lambda 表达式。

public class App {

    public static void main(String[] args) {
        TestFun t = () -> {System.out.println("I'm working"); };
    }
}

正如我们看到的使用 t = ()->{} 而不告诉我们的代码我们想使用直接使用的 void test(),这里我们的想法是,如果我们像第二个一样编写两个方法,这样我们就不能使用lambda 表达式在这种情况下我们应该使用 @FunctionalInterface 来限制开发人员只能使用一种抽象方法。

下面的代码是来自 Runnable 接口和 Thread 类的真实示例。

Thread 类:

public class Thread implements Runnable {
  *// .......* 
}

Runnable 界面:

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}