为什么要使用接口默认方法?

14

学习Java 8默认方法。 像互联网上的任何其他资源一样,此链接指出:

“在最严格的意义上”,默认方法是退步,因为它们允许你“污染”接口代码。但是它们提供了最优雅和实用的方式以允许向后兼容性。这使得Oracle更轻松地更新所有集合类,并使您能够为Lambda重新设计您现有的代码。

我的理解是,Java 8开发/设计人员提供了接口中的默认方法,以便所有实现类不必无谓地重写相同的行为,从而提供向后兼容性。例如:如果ForEach方法不是默认方法,则每个集合实现类都必须实现它。同意。

为了克服这一点,我们可以有一个类提供这些默认方法的实现,然后实现类如arraylist等可以扩展该类。通过这种方式,我们既可以满足Java的基础知识(即可重用性),也可以满足抽象化(即保持接口污染较少)

我相信Java 8开发/设计人员已经想到了这一点,因为他们更加博学,我在这里遗漏了一些东西。能否有人帮助,使我们开发人员也可以掌握这个重大的变化?


可能是Java 8中默认方法或防御者方法的目的的重复问题。 - roottraveller
3个回答

17
在Java 8之前,接口只能有抽象方法。这些方法的实现必须在另一个类中提供。因此,如果要在接口中添加新方法,则必须在实现相同接口的类中提供其实现代码。 为了克服这个问题,Java 8引入了默认方法的概念,允许接口具有带有实现的方法,而不影响实现该接口的类。 默认方法被引入是为了提供向后兼容性,以便现有接口可以使用lambda表达式,而无需在实现类中实现方法。默认方法也称为防御方法或虚拟扩展方法。

2
据我们所知,其中一位开发者说这正是默认方法被发明出来的原因,以保持向后兼容性。但这并不意味着它们应该在用户代码中随处使用。 - skyho
1
我不知道在“任何地方”使用它们,但这种向后兼容的形式可能不仅对JDK开发人员有用。只要不过度使用,我认为这没有大问题。显然,他们选择使该功能对开发人员可访问(甚至进行宣传)。 - Manius

14
为了解决这个问题,可以有一个类提供这些默认方法的实现,然后像ArrayList等实现类可以继承它。 您的建议只适用于标准JDK类(因为它们通常扩展一些基类,如AbstractCollection和AbstractList,其中可以添加新方法的实现)。 那么对于实现JDK接口的自定义类呢?例如,如果您有一个实现List但不扩展某个JDK List实现的类,则应该能够在不必在您的类中实现新方法的情况下切换到Java 8。 通过在List接口中使用默认的新方法实现,您无需修改自定义类。如果您对默认实现感到不满意,稍后可以添加自定义实现。

在这种情况下,自定义类也可以扩展实现forEach实现的通用类。但是,如果该类已经扩展了某个类,那么我的建议将不起作用。 - M Sach
使用列表接口中的默认方法实现,您无需更改自定义类。如果您对默认实现不满意,稍后可以添加自定义实现这些方法。同意。但是在某种程度上,我们在某种意义上向后退了一步,因为我们在某种程度上削弱了抽象化。 - M Sach
5
即使它没有扩展某个类,你也必须改变它的实现(即使只是添加一个 extends someClass 子句)。 - Eran
同意你最后的评论。 - M Sach

2
如果有向接口中添加新方法的需求,那些使用现有接口的客户端将被破坏,因为类需要实现接口中的所有方法。
在这种情况下,可以使用默认和静态方法。这些方法可以有主体,客户端不需要实现它们,因此现有实现可以在没有任何更改的情况下工作。
例如,如果您想增强接口以添加接受lambda表达式的方法,可以使用默认方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接