学习java 8的默认方法.这个链接 就像互联网上的任何其他资源一样
在"最严格的意义上",默认方法是向后退一步,因为它们允许您使用代码"污染"您的接口.但它们提供了最优雅和实用的方式来允许向后兼容.它使Oracle更容易更新所有Collections类,并让您更新Lambda的现有代码.
我的理解是java 8 dev/designer在接口中提供了默认方法,因此所有实现类都不必不必要地覆盖相同的行为,因此提供向后兼容性.例如: - 如果ForEach方法不是默认方法,则实现类的每个集合都必须实现它.同意.
为了克服这个问题,我们可以让一个类提供这些默认方法的实现,然后实现类似arraylist等类可以扩展它.通过这种方式,我们可以对java基础知识(即可重用性和抽象性)进行统计,即保持界面污染较少
我相信java 8开发/设计师已经考虑过这一点,因为他们学到的东西更多,我在这里缺少一些东西.有人可以在这里帮助我们开发人员也可以作为这一重大变化吗?
访问者模式(双分派)是在其自己的权利非常有用的模式,但它经常被仔细检查是否有新的成员加入到继承层次,这是一个有效点突破的接口.
但是在Java 8中引入默认方法之后,现在我们可以在接口中定义默认实现,客户端接口不会中断,客户端可以适当地优雅地采用更改的接口.
interface Visitor{
public void visit(Type1 type);
public void visit(Type2 type);
//added after the first version of visitor is released
default public void visit(NewType type){
//some default implementation
}
}
Run Code Online (Sandbox Code Playgroud)
现在使用默认方法,如果NewType将来引入新类型,则不会再破坏客户端代码.
这是否使访问者更容易接受和有用?
Java 8引入了默认方法的概念.请考虑以下具有默认方法的接口:
public interface IDefaultMethod {
public abstract void musImplementThisMethod();
public default void mayOrMayNotImplementThisMethod() {
System.out.println(" This method is optional for classes that implement this interface ");
}
}
Run Code Online (Sandbox Code Playgroud)
以及实现此接口的类:
public class DefaultMethodImpl implements IDefaultMethod {
@Override
public void musImplementThisMethod() {
System.out.println("This method must be implementd ");
}
@Override
public void mayOrMayNotImplementThisMethod() {
// TODO Auto-generated method stub
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
我对以下调用的可读性有疑问mayOrMayNotImplementThisMethod:
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
Run Code Online (Sandbox Code Playgroud)
我理解在上面的调用中明确指定接口名称的原因是为了避免在类实现的多个接口具有相同方法的情况下混淆.我不明白的是super这个上下文中关键字的含义.当我们说IDefaultMethod.super,我们究竟指的是什么?不会IDefaultMethod.mayOrMayNotImplementThisMethod()比IDefaultMethod.super.mayOrMayNotImplementThisMethod()更具可读性吗?删除super关键字使其更具可读性,代价是区分静态或非静态方法调用.
我在IntelliJ IDEA中编码.在调试我的应用程序时,我无法在Watches中使用某些默认方法实现.
这是一个简洁的例子:
public class Friendship {
interface Friend {
default void sayHiTo(Friend friend) {
System.out.println("Hi, " + friend.hashCode());
}
default int amountOfHands() {
return 2;
}
}
public static class BasicFriend implements Friend {
int numberOfFaces() {
return 1;
}
}
public static void main(String[] args) {
System.out.println("Put a breakpoint here");
}
}
Run Code Online (Sandbox Code Playgroud)
在main()方法中我放了一个断点并设置了三个手表:
// Default interface method with dependency
new BasicFriend().sayHiTo(new BasicFriend())
// Default interface method without dependency
new BasicFriend().amountOfHands()
// Class method
new …Run Code Online (Sandbox Code Playgroud) 我目前想知道是否可以通过使用 JPA 存储库内的默认接口方法来优雅地解决特定用例。
假设我们有以下实体和支持类型:
public enum Status {
STATUS_1,
STATUS_2,
STATUS_3
}
@Entity
@Getter // from lombok
@Setter // from lombok
public class SomeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "status")
private Status status;
}
Run Code Online (Sandbox Code Playgroud)
我需要能够查询SomeEntity基于Status枚举值组合的列表。
使用 Spring JPA,其各自的存储库可能如下所示:
@Repository
public interface SomeRepository extends JpaRepository<SomeEntity, Integer> {
@Query("select s.id, ... from SomeEntity s where s.status in (:statuses)")
List<SomeEntity> getByStatuses(@Param("statuses") List<Status> statuses);
}
Run Code Online (Sandbox Code Playgroud)
然而,必须传递的特定状态组合在很大程度上取决于 的域SomeEntity,并且我想在存储库调用中“烘焙”这些状态。为什么在存储库中——当前多个服务使用同一个存储库,并且SomeEntity作为处理根据服务的具体情况一起更新的其他实体的事务的一部分进行更新。所有服务的特定getByStatuses调用都是相同的,并且我们有重复的代码片段,大致如下所示:
List<Status> statuses …Run Code Online (Sandbox Code Playgroud) 在Java 8中创建默认方法时,某些Object方法无法在默认方法中调用.例如:
interface I {
default void m() {
this.toString(); // works.
this.clone(); // compile-time error, "The method clone() is undefined for the type I"
this.finalize(); // same error as above.
}
}
Run Code Online (Sandbox Code Playgroud)
似乎clone()并且finalize()是唯一的方法Object是不允许的.巧合的是,这些是Object受保护的唯一方法,但这个问题特别关注默认方法,因为它们将由扩展的类继承java.lang.Object.这是什么原因?
我必须为分层实体设计一个接口:
interface HierarchicalEntity<T extends HierarchicalEntity<T>> {
T getParent();
Stream<T> getAncestors();
}
Run Code Online (Sandbox Code Playgroud)
以前者将返回所有祖先的方式实现默认 getAncestors()方法非常容易.getParent()Stream
实施示例:
default Stream<T> getAncestors() {
Stream.Builder<T> parentsBuilder = Stream.builder();
T parent = getParent();
while (parent != null) {
parentsBuilder.add(parent);
parent = parent.getParent();
}
return parentsBuilder.build();
}
Run Code Online (Sandbox Code Playgroud)
但是我还需要包含this在流中,这里出现问题.以下行不正确,因为this它是类型HierarchicalEntity,而不是T:
parentsBuilder.add(this); // type mismatch!
Run Code Online (Sandbox Code Playgroud)
如何重新设计界面以使getAncestors()包含this到结果中?
给定接口(非常大并且由语言定义生成):
interface VisitorA {
default void visit(ASTA1 node) {...}
...
default void visit(ASTA2000 node) {...}
}
interface VisitorB extends VisitorA {
default void visit(ASTB1 node) {...}
...
default void visit(ASTB1000 node) {...}
// due to language embedding all visit methods of VisitorA
// must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
@Override
default void visit(ASTA2000 node) {...}
}
interface VisitorC extends VisitorA {
default void visit(ASTC1 node) {...}
...
default void visit(ASTC1000 node) {...}
// due to language …Run Code Online (Sandbox Code Playgroud) 我知道Inteface 中的所有字段都是隐式静态和最终的.这在Java 8之前就有意义了.
但是随着默认方法的引入,接口也具有抽象类的所有功能.因此,非静态和非最终字段也是必要的.
但是当我尝试正常声明一个字段时,它默认变为静态和最终.
有没有办法在Java 8中的Interface中声明非静态和非final字段.
或者我在这里完全误解了什么?
我有一个从 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 ×9
java-8 ×6
interface ×3
android ×1
compile-time ×1
debugging ×1
hierarchical ×1
oop ×1
spring ×1
textwatcher ×1