dede视频网站,阿里巴巴运营教程,房产网站设计公司,制作可以赚钱的网站几周前#xff0c;我写了一个博客#xff0c;说开发人员学习新语言是因为它们很酷。 我仍然坚持这个主张#xff0c;因为关于Java 8的事情真的很酷。 毫无疑问#xff0c;该节目的明星是添加了Lambdas以及将函数提升为一等变量#xff0c;而我目前最喜欢的是默认方法。 这… 几周前我写了一个博客说开发人员学习新语言是因为它们很酷。 我仍然坚持这个主张因为关于Java 8的事情真的很酷。 毫无疑问该节目的明星是添加了Lambdas以及将函数提升为一等变量而我目前最喜欢的是默认方法。 这是因为它们是在不破坏旧代码的情况下向现有接口添加新功能的一种巧妙方法。 实现很简单采用一个接口添加一个具体方法并将关键字default附加为修饰符。 结果是接口的所有现有实现突然都可以使用此代码。 在第一个简单示例中我添加了默认方法该方法返回接口1的版本号。 public interface Version { /** * Normal method - any old interface method: * * return Return the implementing classs version */ public String version(); /** * Default method example. * * return Return the version of this interface */ default String interfaceVersion() { return 1.0; } } 然后您可以在任何实现类上调用此方法。 public class VersionImpl implements Version { Override public String version() { return My Version Impl; }
} 您可能会问为什么这很酷 如果采用java.lang.Iterable接口并添加以下默认方法则会使for循环失效。 default void forEach(Consumer? super T action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } forEach方法采用实现ConsumerT接口作为参数的类的实例。 ConsumerT可以在新的java.util.function包中找到它是Java 8所谓的功能接口 该接口仅包含一个方法。 在这种情况下方法accept(T t)接受一个参数并且返回一个void 。 java.util.function软件包可能是Java 8中最重要的软件包之一。它包含一堆描述通用函数类型的单一方法或函数接口。 例如 ConsumerT包含一个接受一个参数并返回void的函数而PredicateT是一个包含一个接受一个参数并返回boolean的函数的接口通常用于编写过滤lambda。 该接口的实现应包含您先前在for循环括号之间编写的内容。 那么您可能会想这给了我什么 如果不是Java 8那么答案是“不多”。 要在Java 8之前使用forEach…方法您需要编写如下代码 ListString list Arrays.asList(new String[] { A, FirsT, DefaulT, LisT }); System.out.println(Java 6 version - anonymous class); ConsumerString consumer new ConsumerString() { Override public void accept(String t) { System.out.println(t); } }; list.forEach(consumer); 但是如果将其与lambda表达式或方法引用结合使用则可以编写一些看起来很酷的代码。 使用方法引用前面的示例变为 list.forEach(System.out::println); 您可以使用lambda表达式执行相同的操作 list.forEach((t) - System.out.println(t)); 所有这些似乎都与Java 8背后的一个重要思想保持一致让JDK为您完成工作。 用政治家和连环友约翰·肯尼迪John F Kennedy的话来形容“不要问您对JDK可以做什么请问您的JDK可以为您做什么” 2 。 默认方法的设计问题 那是编写无处不在的for循环的一种很酷的新方法但是在接口中添加默认方法是否存在问题如果是的话它们是什么Java 8项目中的人如何修复它们 首先要考虑的是继承。 当您拥有一个扩展了另一个接口的接口并且两个接口都具有带有相同签名的默认方法时会发生什么 例如如果您拥有由MiddleInterface扩展的SubInterface和由SuperInterface扩展的MiddleInterface SubInterface怎么SubInterface public interface SuperInterface { default void printName() { System.out.println(SUPERINTERFACE); }
}public interface MiddleInterface extends SuperInterface { Override default void printName() { System.out.println(MIDDLEINTERFACE); }
}public interface SubInterface extends MiddleInterface { Override default void printName() { System.out.println(SUBINTERFACE); }
}public class Implementation implements SubInterface { public void anyOldMethod() { // Do something here } public static void main(String[] args) { SubInterface sub new Implementation(); sub.printName(); MiddleInterface middle new Implementation(); middle.printName(); SuperInterface sup new Implementation(); sup.printName(); }
} 无论用哪种方式剪切 printName()都将始终打印“ SUBINTERFACE”。 当您具有包含相同方法签名的类和接口时会出现相同的问题哪个方法在运行 答案是“阶级胜利”法则。 接口默认方法将始终被类方法所忽略。 public interface AnyInterface { default String someMethod() { return This is the interface; }
}public class AnyClass implements AnyInterface { Override public String someMethod() { return This is the class - WINNING; } } 运行上面的代码将始终打印出“这是课程-WINNING” 最后如果一个类实现两个接口并且都包含具有相同签名的方法会发生什么 这是古老的C 钻石问题 您如何解决歧义 运行哪种方法 public interface SuperInterface { default void printName() { System.out.println(SUPERINTERFACE); }
}public interface AnotherSuperInterface { default void printName() { System.out.println(ANOTHERSUPERINTERFACE); }
} 在Java 8的情况下答案都不是。 如果您尝试同时实现这两个接口则会收到以下错误 Duplicate default methods named printName with the parameters () and () are inherited from the types AnotherSuperInterface and SuperInterface. 在绝对必须实现两个接口的情况下解决方案是调用“类获胜”规则并覆盖实现中的歧义方法。 public class Diamond implements SuperInterface, AnotherSuperInterface { /** Added to resolve ambiguity */ Override public void printName() { System.out.println(CLASS WINS); } public static void main(String[] args) { Diamond instance new Diamond(); instance.printName(); } }何时使用默认方法 从纯粹的角度来看默认方法的添加意味着Java接口不再是接口。 接口被设计为用于拟议/预期行为的规范或合同实施类必须履行的合同。 添加默认方法意味着接口和抽象基类之间实际上没有区别3 。 这意味着他们容易受到滥用因为一些经验不足的开发人员可能认为从其代码库中删除基类并用基于默认方法的接口替换它们很酷–只是因为它们可以而其他人可能只是将抽象类与实现默认值的接口混淆了方法。 我目前建议仅将默认方法用于其预期的使用情况在不破坏现有代码的情况下改进传统接口。 虽然我可能会改变主意。 1它不是很有用但是它说明了一点…… 2肯尼迪John F Kennedy的就职演说1961年1月20日。 3抽象基类可以具有构造函数而接口则不能。 类可以具有私有实例变量即状态。 接口不能。 翻译自: https://www.javacodegeeks.com/2014/08/default-methods-java-8s-unsung-heros.html