Java8新特性系列-默认方法和静态方法

 在Java 8之前,默认情况下,接口中的所有方法都是公共的和抽象的。但是这一限制在Java 8中被打破了,Java 8允许开发人员在接口中添加新方法,而无需在实现这些接口的类中进行任何更改。

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:国际域名空间、网站空间、营销软件、网站建设、梅列网站维护、网站推广。

为什么会有默认方法?

主要是为了方便扩展已有接口;如果没有默认方法,假如给Java中的某个接口添加一个新的抽象方法,那么所有实现了该接口的类都得修改,影响将非常大。

举个例子,Sortable 接口以及实现该接口的类SortableNumberCollection和SortableStringCollection。该接口有两种方法:void sort(); 和T peek()。

 
 
 
 
  1. public interface Sortable {
  2.     void sort();
  3.     T peek();
  4. }

 sort()方法用于对象排序,T peek()用于获取指定元素,另外需要一个比较器类ObjectComparator来对对象进行排序。

 
 
 
 
  1. public class ObjectComparator implements Comparator {
  2.     @Override
  3.     public int compare(Comparable o1, Comparable o2) {
  4.         return o1.compareTo(o2);
  5.     }
  6. }

 SortableStringCollection是一个自定义集合类可以进行排序,并查看字符串指定元素,代码如下:

 
 
 
 
  1. public class SortableStringCollection implements Sortable {
  2.     private List items = new ArrayList<>();
  3.     public void add(String item) {
  4.         items.add(item);
  5.     }
  6.     @Override
  7.     public void sort() {
  8.         items.sort(new ObjectComparator());
  9.     }
  10.     @Override
  11.     public String peek() {
  12.         return items.get(0);
  13.     }
  14. }

 同样,SortableNumberCollection是一个自定义集合类,其中包含可以使用接口方法进行排序和查看的数字列表指定元素,代码如下:

 
 
 
 
  1. public class SortableNumberCollection implements Sortable {
  2.     private List items = new ArrayList<>();
  3.     public void add(Integer item) {
  4.         items.add(item);
  5.     }
  6.     @Override
  7.     public void sort() {
  8.         items.sort(new ObjectComparator());
  9.     }
  10.     @Override
  11.     public Integer peek() {
  12.         return items.get(0);
  13.     }
  14. }

 在Java8之前如果对接口Sortable 添加新方法:T sortAndPeek(),那么SortableStringCollection和

SortableNumberCollection都必须实现T sortAndPeek()方法。

Java8之后提供了一种新的实现方式,默认方法 default method,我们可以对Sortable 进行如下改造:

 
 
 
 
  1. public interface Sortable {
  2.     void sort();
  3.     T peek();
  4.     default T sortAndPeek(){    // New 'default method' added in the interface
  5.         sort();
  6.         return peek();
  7.     }
  8. }

 同时SortableStringCollection和SortableNumberCollection类不需要任何更改。这样可以减少我们对原有代码的改动。同时如果需要,还可以在实现此接口的任何类中重写该方法T sortAndPeek()的默认实现。

在下图中我们看到default Method不通的标识:

在多继承中使用默认方法问题

如果两个或多个接口具有相同的默认方法签名,并且一个类实现了这两个接口,则将引发编译时错误。例如:

 
 
 
 
  1. public interface Interface1 {
  2.     void methodOne(String str);
  3.     default void newMethod(){
  4.         System.out.println("Interface1: Newly added method");
  5.     }
  6. }
  7. public interface Interface2 {
  8.     void methodTwo(String str);
  9.     default void newMethod(){
  10.         System.out.println("Interface2: Newly added method");
  11.     }
  12. }
  13. public class InterfaceImplementation implements Interface1, Interface2{
  14.     @Override
  15.     public void methodOne(String str) {
  16.         System.out.println("Overridden methodOne: " + str);
  17.     }
  18.     @Override
  19.     public void methodTwo(String str) {
  20.         System.out.println("Overridden methodTwo: " + str );
  21.     }
  22. }

 此时代码会提示如下异常:

 
 
 
 
  1. InterfaceImplementation inherits unrelated defaults for newMethod() from types Interface1 and Interface2

要解决此问题,我们将必须重写类InterfaceImplementation中的方法:

 
 
 
 
  1. public class InterfaceImplementation implements Interface1, Interface2{
  2.     @Override
  3.     public void methodOne(String str) {
  4.         System.out.println("Overridden methodOne: " + str);
  5.     }
  6.     // newMethod implemented to resolve the conflict.
  7.     @Override
  8.     public void newMethod() {
  9.         System.out.println("InterfaceImplementation: Newly added method");
  10.     }
  11.     @Override
  12.     public void methodTwo(String str) {
  13.         System.out.println("Overridden methodTwo: " + str );
  14.     }
  15. }

 我们总结一下:

  • 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
  • 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
  • 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法,显式地选择使用哪一个默认方法的实现。

在Java 8中添加静态方法

接口定义的静态方法独立于任何对象调用。所以,在调用静态方法时,不需要实现接口,也不需要接口的实例,

就像“默认方法”一样,“静态方法”也可以添加到接口中。例如,我们可以添加一个静态方法Direction getDefaultDirection(),该方法将返回默认Direction,例如:

 
 
 
 
  1. public interface Sortable {
  2.     Direction defaultDirection = Direction.DESC;
  3.     enum Direction {
  4.         ASC,
  5.         DESC
  6.     };
  7.     void sort();
  8.     T peek();
  9.     static Direction getDefaultDirection(){    // 'static method' added to the interface.
  10.         return defaultDirection;
  11.     }
  12. }

 在上面的示例中,可以使用类引用来调用静态Direction getDefaultDirection()方法:

 
 
 
 
  1. Sortable.getDefaultDirection()

对默认方法和静态方法的一点思考

接口是设计模式中一种开闭原则的体验,而java8赋予了接口新的特性,使得接口使用起来更加的得心应手了,这也有助于我们更加内聚自己的代码结构了。Java源码中也有很多场景使用到了默认方法,例如:Iterator接口,我们在开发中可以多使用一些新的特性从而提高开发效率及增加代码的健壮性。

 
 
 
 
  1. public interface Iterable {
  2.     Iterator iterator();
  3.     
  4.     default void forEach(Consumer action) {
  5.         Objects.requireNonNull(action);
  6.         for (T t : this) {
  7.             action.accept(t);
  8.         }
  9.     }
  10.     
  11.     default Spliterator spliterator() {
  12.         return Spliterators.spliteratorUnknownSize(iterator(), 0);
  13.     }
  14.     
  15. }

文章标题:Java8新特性系列-默认方法和静态方法
网页URL:http://www.shufengxianlan.com/qtweb/news7/296957.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联