我有一个接口,我想在其中提供默认方法来序列化继承的类。我使用一个JsonSerializer<T>类来进行序列化。
该方法如下所示:
public interface A
{
public default String write()
{
new JsonSerializer</*Inherited class type*/>();
// I've tried new JsonSerializer<this.getClass()>(); - Doesn't work
}
}
public class AX implements A
{
}
Run Code Online (Sandbox Code Playgroud)
所以当我实例化AX时,我想使用write方法来序列化AX
AX inst = new AX();
String instSerialized = inst.write();
Run Code Online (Sandbox Code Playgroud)
我需要将 AX 的类型传递给 A 中的 write 方法。这可能吗?
与这个问题一样,我想知道为什么Java团队没有为Lock接口添加一些默认方法,如下所示:
public default void withLock(Runnable r) {
lock();
try {
r.run();
} finally {
unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
这将允许程序员这样做
public class ThreadSafe {
// Object requiring protection
private final List<String> l = new ArrayList<>();
private final Lock lock = new ReentrantLock();
public void mutate(String s) {
lock.withLock(() -> l.add(s));
}
public void threadSafeMethod {
lock.withLock(() -> { System.out.println(l.get(l.size())); });
}
}
Run Code Online (Sandbox Code Playgroud)
代替
public void threadSafeMethod {
lock.lock();
try {
System.out.println(l.get(l.size()));
} finally {
lock.unlock();
}
}
Run Code Online (Sandbox Code Playgroud) 我想@ServiceActivator在Java 8默认接口方法上使用注释.此默认方法将根据业务规则委托此接口的另一个方法.
public interface MyServiceInterface {
@ServiceActivator
public default void onMessageReceived(MyPayload payload) {
if(payload.getAction() == MyServiceAction.MY_METHOD) {
...
myMethod(...);
}
}
public void myMethod(...);
}
Run Code Online (Sandbox Code Playgroud)
然后,此接口由Spring @Service类实现:
@Service
public class MyService implements MyServiceInterface {
public void myMethod(...) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
执行代码时,这不起作用!
我只能让它@ServiceActivator从默认方法中删除注释,并覆盖我的@Service类中的默认方法并委托给super方法:
@Service
public class MyWorkingService implements MyServiceInterface {
@ServiceActivator
@Override
public void onMessageReceived(MyPayload payload) {
MyServiceInterface.super.onMessageReceived(payload);
}
public void myMethod(...) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
覆盖默认方法会忽略默认方法的用途.
是否有其他方式以干净的方式实现此方案?
我知道Inteface 中的所有字段都是隐式静态和最终的.这在Java 8之前就有意义了.
但是随着默认方法的引入,接口也具有抽象类的所有功能.因此,非静态和非最终字段也是必要的.
但是当我尝试正常声明一个字段时,它默认变为静态和最终.
有没有办法在Java 8中的Interface中声明非静态和非final字段.
或者我在这里完全误解了什么?
考虑以下情况,
interface IFace1 {
default void printHello() {
System.out.println("IFace1");
}
}
interface IFace2 {
void printHello();
}
public class Test implements IFace1, IFace2 {
public static void main(String[] args) {
Test test = new Test();
test.printHello();
IFace1 iface1 = new Test();
iface1.printHello();
IFace2 iface2 = new Test();
iface2.printHello();
}
@Override
public void printHello() {
System.out.println("Test");
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,我得到了非常期待的输出.
Test
Test
Test
Run Code Online (Sandbox Code Playgroud)
我一直在阅读有关Java-8默认方法的内容,特别是有关扩展包含默认方法的接口的内容
2 nd bullet:重新声明默认方法,使其成为抽象方法.
在上面的例子中,我有这有相同名称的默认方法两个接口,当我实现了这两个我才能够达到执行printHello的Test是指IFace2.
我对此几乎没有疑问, …
在java网站的教程页面上的这个例子中.两个接口定义相同的默认方法startEngine().类FlyingCar实现两个接口,并且必须覆盖,startEngine()因为存在明显的冲突.
public interface OperateCar {
// ...
default public int startEngine(EncryptedKey key) {
// Implementation
}
}
public interface FlyCar {
// ...
default public int startEngine(EncryptedKey key) {
// Implementation
}
}
public class FlyingCar implements OperateCar, FlyCar {
// ...
public int startEngine(EncryptedKey key) {
FlyCar.super.startEngine(key);
OperateCar.super.startEngine(key);
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么,from FlyingCar,super用于指代startEngine()in OperateCar和FlyCarinterfaces的两个版本.据我所知,startEngine()没有在任何超类中定义,因此不应该被称为居民.我也没有看到super和实现的两个接口之间有任何关系FlyingCar
Java 8 在接口上引入了默认方法,为集合接口的实现提供向后兼容性,以避免遗留库上出现 MethodNotFound 错误。
即具有List 的java 7 实现的库将不会实现stream() 方法。如果 java 8 代码使用此库,则默认实现会提供后备方案。
我在实践中看到的是,许多开发人员过度热衷于使用此功能以类似于 scala 特征的风格来模拟混合和多重继承。
我担心的一个问题是,这种编程风格模糊了接口(即契约)及其实现之间的界限,因此引入了隐藏的紧密耦合并违反了控制反转,迫使我使用后门通过覆盖默认实现来测试代码。我的单元测试,以抑制不应出现在单元测试级别的行为。
使用默认方法是一种反模式,还是只有我一个人怀疑这一点?
anti-patterns inversion-of-control mixins java-8 default-method
我有一个具有以下默认方法的接口:
default Integer getCurrentYear() {return DateUtil.getYear();}
Run Code Online (Sandbox Code Playgroud)
我还有一个实现此接口的控制器,但它不会覆盖该方法.
public class NotifyController implements INotifyController
Run Code Online (Sandbox Code Playgroud)
我试图从我的xhtml访问此方法,如下所示:
#{notifyController.currentYear}
Run Code Online (Sandbox Code Playgroud)
但是,当我打开屏幕时,会出现以下错误:
The class 'br.com.viasoft.controller.notify.notifyController' does not have the property 'anoAtual'
Run Code Online (Sandbox Code Playgroud)
如果我从我的控制器的实例访问此方法,它返回正确的值,但是当我尝试从我的xhtml访问它作为"属性"时,它会发生此错误.
有没有办法从我的控制器的引用访问此接口属性,而无需实现该方法?
根据接口隔离原则
不应该强迫客户端实现不需要的接口方法
...因此我们应该定义接口以进行逻辑分离。
但是defaultJava 8 中引入的方法提供了在 Java 接口中实现方法的灵活性。似乎 Java 8 提供了增强接口的可行性,使其具有一些与其核心逻辑无关的方法,但具有一些默认或空的实现。
它不违反ISP吗?
java solid-principles default-method interface-segregation-principle
我有一个从 Android 继承的接口,TextWatcher仅用于实现afterTextChanged方法。我在我的项目中启用了 Java 8 支持,并在build.gradle文件中添加了源和目标兼容性选项,但即使它在调试版本中运行完美,它在我测试的每台设备上的发布版本中都失败了。我首先在 Play Console 的预发布报告中注意到了它,并在 Firebase 的测试实验室中再次进行了测试,但仍然是每次设备抛出AbstractMethodError后都会崩溃。
这是我的AfterTextChangedListener:
import android.text.Editable;
import android.text.TextWatcher;
public interface AfterTextChangedListener extends TextWatcher {
@Override
default void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Do nothing
}
@Override
default void onTextChanged(CharSequence s, int start, int before, int count) {
// Do nothing
}
@Override
void afterTextChanged(Editable s);
}
Run Code Online (Sandbox Code Playgroud)
这是使用此接口的代码部分:
mSomeEditText.addTextChangedListener((AfterTextChangedListener) editable -> {
// Logic using 'editable'.
});
Run Code Online (Sandbox Code Playgroud)
这是崩溃的 …
default-method ×10
java ×7
java-8 ×7
android ×1
el ×1
generics ×1
interface ×1
interface-segregation-principle ×1
jsf ×1
locking ×1
mixins ×1
spring ×1
super ×1
textwatcher ×1