Java 8最有用的功能之一是default接口上的新方法.基本上有两个原因(可能还有其他原因)为什么会被引入:
Iterator.remove()Iterable.forEach()从API设计者的角度来看,我希望能够在接口方法上使用其他修饰符,例如final.在添加便捷方法时,这将非常有用,可防止在实现类时出现"意外"覆盖:
interface Sender {
// Convenience method to send an empty message
default final void send() {
send(null);
}
// Implementations should only implement this method
void send(String message);
}
Run Code Online (Sandbox Code Playgroud)
如果Sender是一个类,上面已经是常见的做法:
abstract class Sender {
// Convenience method to send an empty message
final void send() {
send(null);
}
// Implementations should only implement this method
abstract void send(String message);
}
Run Code Online (Sandbox Code Playgroud)
现在,default并final有明显矛盾的关键字,但默认关键字本身不会一直严格要求 …
从Java 9会允许我们定义private和private static方法太接口,这将是在剩下的差异interface和class?而且,Java是否正在慢慢走向多重继承?
我的项目中使用了某个库.该库有一个接口,有大约15种方法.
此接口的目的是使订阅库中生成的某些事件成为可能.应用程序中的侦听器类可以实现此接口,并将自身注册为库中的侦听器以接收事件.
此接口中的所有方法实际上都是事件.可以有听众只需要从界面中的许多事件中仅接收一个或两个事件.即使监听器只对少数事件感兴趣,监听器也必须在扩展接口时实现所有方法.
所以我要求这个库的开发人员在界面中的方法中添加空的默认实现.
但是库开发人员拒绝添加默认实现,声称它违反了Java最佳实践,并且在接口方法中使用默认实现违背了接口的目的.
但是,据我所知,此接口中的方法未指定此接口的实现者应该具有的某些操作.此接口中的方法确定了实现者可能感兴趣的事件.因此,我看不出没有添加默认实现的明确原因.
那么,在这个界面添加默认实现是否打破了java最佳实践?
在Java 8中,除了需要在具体类中实现的声明之外,我们还可以为接口中的方法提供默认实现.
在接口中使用默认方法是一个好的设计还是最佳实践,或者Java 8是否只是为了在旧的API上提供更多支持?我们应该从新的Java 8项目中使用默认方法开始吗?
请帮我详细了解这里的优秀设计.
Java 8 在接口上引入了默认方法,为集合接口的实现提供向后兼容性,以避免遗留库上出现 MethodNotFound 错误。
即具有List 的java 7 实现的库将不会实现stream() 方法。如果 java 8 代码使用此库,则默认实现会提供后备方案。
我在实践中看到的是,许多开发人员过度热衷于使用此功能以类似于 scala 特征的风格来模拟混合和多重继承。
我担心的一个问题是,这种编程风格模糊了接口(即契约)及其实现之间的界限,因此引入了隐藏的紧密耦合并违反了控制反转,迫使我使用后门通过覆盖默认实现来测试代码。我的单元测试,以抑制不应出现在单元测试级别的行为。
使用默认方法是一种反模式,还是只有我一个人怀疑这一点?
anti-patterns inversion-of-control mixins java-8 default-method
警告:我意识到这可能是对 spring bean 和/或 Java 8 的默认接口方法背后意图的滥用。我正在寻找的是对为什么这可能是一种我未能认识到的不安全方法的具体且合理的批评。
我定义了一个类,它使我可以静态访问正在运行的应用程序上下文:
@Component
public class BeanAccessor implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static <T> T getSingleton(Class<T> clazz){
return applicationContext.getBean(clazz);
}
public static <T> T getSingleton(String beanName, Class<T> clazz){
return applicationContext.getBean(beanName, clazz);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
BeanAccessor.applicationContext = applicationContext;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我可以在默认接口方法中使用这些 BeanAccessor 方法,以便从方法内部访问 spring 管理的 bean。
我意识到可以通过实现其他类和服务来实现此功能,而不是觉得需要将它混合到当前的类和服务中(至少对于下面的示例,我实际上并没有对“this”做任何事情)。这在一定程度上是一种“艺术”偏好,我相信我会继续寻找其他用例。
请注意,我并没有像这里描述的那样尝试保留每个实例的状态https://kerflyn.wordpress.com/2012/07/09/java-8-now-you-have-mixins/我确实认识到存在危险在这样做。
这是一个示例用法:
public interface ClientAware {
String TENANT_NAME = "TENANT_NAME";
default ClientDetails clientDetails() {
ClientDetailsService service …Run Code Online (Sandbox Code Playgroud) 所以我们有默认方法,也被称为防御方法和'虚拟扩展方法'.
虽然我很欣赏默认方法的巨大价值(在某些方面甚至比它们的C#对应物更强大)但我想知道什么是允许扩展现有接口而不访问其源代码的决定.
在他的一个答案中, Brian Goetz提到默认方法是为了方便和界面演变而设计的.因此,如果我们编写一个接口,我们可以在那里填充我们通常必须放在一个单独的类中的各种实用方法.那么为什么不加倍努力并允许它不受我们控制的接口?
最近我遇到了这段代码.
public interface CustomerQueryService {
default Customer getCustomerById(long id) {
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
后来,事实证明这是该项目的一般惯例.这被认为是一种好习惯吗?
我有类实现多个接口,它们具有相同的默认默认方法.我想知道如何从所有接口合成默认方法.例如:
interface IA {
default void doA() {}
default void process() {
// do something
}
}
interface IB {
default void doB() {}
default void process() {
// do something
}
}
interface IC {
default void doC() {}
default void process() {
// do something
}
}
// other similar interfaces
....
class MyClass implements IA, IB, IC, ... {
public void process() {
// question: how to avoid iterate all the interfaces?
IA.super.process();
IB.super.process();
IC.super.process();
...
} …Run Code Online (Sandbox Code Playgroud) 我知道这个问题已经被问过很多次了,我们在互联网上有很多文章,但我仍然无法完全理解,因为我使用的是 Java 15,我应该什么时候使用接口或抽象类。
大多数文章都讨论了之前的差异和用例Java 8,但当您基本上可以在接口中为您的方法提供主体时,这些文章是有意义的。
唯一的那对我有意义的事情是non-public和non-final限制。
如果有人能指出我需要在 Java 15 中的接口和抽象类之间进行选择的场景的 1-2 个示例,我将非常感激。此外,如果它可以用于现实生活项目而不是动物或形状,那就太好了类示例。
谢谢 !!
Java有计划default method替代 Abstract Class吗?我找不到使用默认方法而不是抽象的真实案例?