精华内容
下载资源
问答
  • JAVA8也为流在提供另一个功能——并行流。即是有并行流,那么是不是也有顺序流。没有错。我前面操作的一般都是顺序流。在JAVA8里面并行流和顺序流是可以转变的。来看一个例子——笔者打印数字。 1 package ...

    流,确定是笔者内心很向往的天堂,有他之后JAVA在处理数据就变更加的灵动。加上lambda表达不喜欢都不行。JAVA8也为流在提供另一个功能——并行流。即是有并行流,那么是不是也有顺序流。没有错。我前面操作的一般都是顺序流。在JAVA8里面并行流和顺序流是可以转变的。来看一个例子——笔者打印数字。

     1 package com.aomi;
     2 
     3 import java.util.stream.LongStream;
     4 
     5 public class Main {
     6 
     7     public static void main(String[] args) {
     8         // TODO Auto-generated method stub
     9 
    10         LongStream.range(0, 10).forEach(i -> {
    11             System.out.print(i + " ");
    12         });
    13     }
    14 
    15 }

    LongStream.range这个方法是来获取数字的。这里表示获得0到10,但不含10 的数字。运行结果:

    现在让我们把他换成并行来看看。

     1 package com.aomi;
     2 
     3 import java.util.stream.LongStream;
     4 
     5 public class Main {
     6 
     7     public static void main(String[] args) {
     8         // TODO Auto-generated method stub
     9 
    10         LongStream.range(0, 10).parallel().forEach(i -> {
    11             System.out.print(i + " ");
    12         });
    13     }
    14 
    15 }

    运行结果:

    俩个结果相比一下,我们就可以明显他们发生了变化。我们只是加一个parallel函数就发生好多的变化。笔者本来是要讲他们之间的性能比较的。不敢,因为笔者试好还有个例子。却发现有时候顺序流都比并行流来快。上面是顺序流转并行流。在来看一下相反的。

    1 public static void main(String[] args) {
    2         // TODO Auto-generated method stub
    3 
    4         List<Integer> datas = Arrays.asList(1,2,3,4,56);
    5         
    6         datas.parallelStream().forEach(i -> {
    7             System.out.print(i + " ");
    8         });
    9     }

    parallelStream函数就是用来建一个并行流的。运行结果:

    转为顺序流

    1 public static void main(String[] args) {
    2         // TODO Auto-generated method stub
    3 
    4         List<Integer> datas = Arrays.asList(1,2,3,4,56);
    5         
    6         datas.parallelStream().sequential().forEach(i -> {
    7             System.out.print(i + " ");
    8         });
    9     }

     运行结果:

    我们都知道流里面用到了JAVA7里面的分支和合并的框架来进行的。古代有一个词叫分而治之。把一个事情分为几个小事件。然面各自处理。所以了解代码里面是什么样子折分成小事件是非常重要的。他有俩个关键字Fork和Join。Fork方法你可以理解为拆分,并压入线程队列中。而Join就是合并的意思了。来笔者来写一个试。

     1 package com.aomi;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 import java.util.concurrent.RecursiveTask;
     6 
     7 public class DistinctCharForkJoin extends RecursiveTask<List<Character>> {
     8 
     9     private List<Character> chars;
    10 
    11     public DistinctCharForkJoin(List<Character> chars) {
    12         this(chars, 0, chars.size());
    13     }
    14 
    15     public DistinctCharForkJoin(List<Character> chars, int start, int end) {
    16 
    17         this.chars = chars.subList(start, end);
    18     }
    19 
    20     @Override
    21     protected List<Character> compute() {
    22         // TODO Auto-generated method stub
    23         List<Character> tmpChars = new ArrayList<Character>();
    24 
    25         // 判断不可以在拆分了
    26         if (this.chars.size() < 3) {
    27 
    28             for (Character character : chars) {
    29                 if (!tmpChars.contains(character))
    30                     tmpChars.add(character);
    31             }
    32 
    33         } else {// 表示可以在拆分。
    34 
    35             int len = this.chars.size();
    36 
    37             // 建立左边的小事件
    38             DistinctCharForkJoin leftForkJoin = new DistinctCharForkJoin(chars, 0, len / 2);
    39 
    40             leftForkJoin.fork();
    41 
    42             // 建立右边的小事件
    43             DistinctCharForkJoin rightForkJoin = new DistinctCharForkJoin(chars, len / 2, len);
    44 
    45             rightForkJoin.fork();
    46 
    47             List<Character> rChars = rightForkJoin.join();
    48 
    49             List<Character> lChars = leftForkJoin.join();
    50 
    51             // 俩个合并。
    52             for (Character character : rChars) {
    53                 if (!tmpChars.contains(character))
    54                     tmpChars.add(character);
    55             }
    56 
    57             for (Character character : lChars) {
    58                 if (!tmpChars.contains(character))
    59                     tmpChars.add(character);
    60             }
    61 
    62         }
    63 
    64         return tmpChars;
    65     }
    66 
    67 }

    Main:

     1 public static void main(String[] args) {
     2         // TODO Auto-generated method stub
     3 
     4         List<Character> chars = Arrays.asList('a', 'b', 'c', 'd', 'b', 'a');
     5 
     6         DistinctCharForkJoin task = new DistinctCharForkJoin("main", chars);
     7 
     8         List<Character> resChars = new ForkJoinPool().invoke(task);
     9 
    10         for (Character character : resChars) {
    11 
    12             System.out.print(character +" ");
    13         }
    14     }

    运行结果:

    你们一定很奇怪为什么笔者会讲到JAVA7带来的东西呢?JAVA8引入了一个新的接口——Spliterator接口。人称可分迭代器。如果你有心去看一个接口List的话,你可能会发现一个方法。如下

    1 default Spliterator<E> spliterator() {
    2         return Spliterators.spliterator(this, Spliterator.ORDERED);
    3     }

    Spliterator接口:

    1 public interface Spliterator<T> {
    2     boolean tryAdvance(Consumer<? super T> action);
    3     Spliterator<T> trySplit();
    4     long estimateSize();
    5     int characteristics();
    6 }

    讲JAVA7里面的分支/合并的目地就是为了理解Spliterator接口的作用。如下

    • tryAdvance:用于遍历当前的元素。如果还有的话,就返回true;
    • trySplit:用于拆分。如果当前不可以在拆分的话,就返回null;跟上面的compute方法很像。
    • estimateSize:表示还需要遍历的元素有多少。
    • characteristics:表示当前处理的数据是什么样子的。比如是否有序,每一元素是否为null。上面Spliterator接口的代码是笔者去掉大部分复制出来。这个值都在代码中。作用你们可以自己去看一下代码就是知道。

    要注意Spliterator接口只是用去拆分任务的作用。JAVA8帮你做了很多拆分的功能。大部分你可以不用自己写。当然如果你想要自己动手。你只要实现这样子就可以了。如下

     1 package com.aomi;
     2 
     3 import java.util.List;
     4 import java.util.Spliterator;
     5 import java.util.function.Consumer;
     6 
     7 public class DistinctCharSpliterator implements Spliterator<Character> {
     8 
     9     private List<Character> chars;
    10     private int index = 0;
    11 
    12     public DistinctCharSpliterator(List<Character> chars) {
    13         this.chars = chars;
    14     }
    15 
    16     public DistinctCharSpliterator(List<Character> chars, int start, int end) {
    17         this.chars = chars.subList(start, end);
    18     }
    19 
    20     @Override
    21     public boolean tryAdvance(Consumer<? super Character> action) {
    22         // TODO Auto-generated method stub
    23         action.accept(this.chars.get(index++));
    24         return index < this.chars.size();
    25     }
    26 
    27     @Override
    28     public Spliterator<Character> trySplit() {
    29         // TODO Auto-generated method stub
    30         int difLen = this.chars.size() - index;
    31 
    32         // 判断不可以在拆分了
    33         if (difLen < 3) {
    34             return null;
    35         } else {// 表示可以在拆分。
    36 
    37             
    38             DistinctCharSpliterator spliterator = new DistinctCharSpliterator(chars.subList(index, index + 2));
    39 
    40             index = index + 2;
    41 
    42             return spliterator;
    43 
    44         }
    45     }
    46 
    47     @Override
    48     public long estimateSize() {
    49         // TODO Auto-generated method stub
    50         return this.chars.size() - index;
    51     }
    52 
    53     @Override
    54     public int characteristics() {
    55         // TODO Auto-generated method stub
    56         // 有序 元素不空 遍历过程不能删除,和修改 增加
    57         return ORDERED + NONNULL + IMMUTABLE;
    58     }
    59 
    60 }

    Main:

     1 public static void main(String[] args) {
     2         // TODO Auto-generated method stub
     3 
     4         List<Character> chars = Arrays.asList('a', 'b', 'c', 'd', 'b', 'a');
     5 
     6         DistinctCharSpliterator distinctCharSpliterator = new DistinctCharSpliterator(chars);
     7 
     8         Stream<Character> stream = StreamSupport.stream(distinctCharSpliterator, true);
     9 
    10         stream.distinct().forEach((Character ch) -> {
    11 
    12             System.out.print(ch+" ");
    13         });
    14 
    15     }

    运行结果:

    上面的例子有一点烂。但是大家可以复制做一下继点去看看他的执行过程。就可以看出很多东西来。主要是理解这个原理就可以了。
    流的并行功能并没有让笔者有多心动。真正让笔者感觉不错的要属于JAVA8对接口的升级。什么意思?笔者不清楚有多少个人写个框架或是读过框架源码,一般框架里面都会用到一些面向接口的编程模式。那个或多或少会有这样子感觉。一但项目发布出去,这个时候你想要修改接口。比如在接口里面增加一个新的功能方法。这样子时候你就不得不考虑一下外面有多少个人在实现你现在框架的接口。因为你增加一个接口的新方法。别人也要跟着实现,不然的一定会报错或是运行时候报错。不管哪一种都是设计者不想看到的。
    JAVA8现在可以让你定义接口的默认方法。什么思意呢?让笔得写一个例子。

    Base接口:

    1 package com.aomi;
    2 
    3 public interface Base {
    4     void call();
    5 }

    BaseA类:

     1 package com.aomi;
     2 
     3 public class BaseA implements Base {
     4 
     5     @Override
     6     public void call() {
     7         
     8     }
     9 
    10 }

    Main:

     1 package com.aomi;
     2 
     3 public class Main {
     4 
     5     public static void main(String[] args) {
     6         // TODO Auto-generated method stub
     7 
     8         Base baseA = new BaseA();
     9 
    10         baseA.call();
    11     }
    12 }

    上面的代码没有什么特别的。现在笔者在加一个方法。看一个他会不会有问题。如下

    base类:

    1 package com.aomi;
    2 
    3 public interface Base {
    4     void call();
    5     void call2();
    6 }

    结果:

    看到吧。BaseA类马上就报错。现在笔者在加上一个默认的方法会什么呢?

    package com.aomi;
    
    public interface Base {
        void call();
    
        default void call2() {
            System.out.println("default call2");
        }
    }

    Main修改一下吧。

     1 package com.aomi;
     2 
     3 public class Main {
     4 
     5     public static void main(String[] args) {
     6         // TODO Auto-generated method stub
     7 
     8         Base baseA = new BaseA();
     9 
    10         baseA.call2();
    11     }
    12 }

    运行结果:

    上面的代码。笔者在BaseA类里面并没有实现call2的方法。显然现在的功能对我们写框架的人来写太棒了。在也不用担心增加一个接方法而去考虑有多少个人用这个接口了。
    那么问题来了。我们在写代码的过程中,一定会遇到方法相同的情况吧。这个时候JAVA8提供了三个标准来确定用哪一个。

    1. 类或父类的方法优先级高于接口默认的方法。
    2. 如果上面不行的话,谁拥有最具体的实现的话,就用谁。
    3. 如果都不能确定的情况下,就必须显性的调用。来指定他要调哪一个。

    举例子。A和B都是接口。其中B继承了A。同时C实现了A和B。这个时候调用C会是什么样子。
    A:

    public interface A {
    
        default void call() {
            System.out.println("A call");
        }
    }

    B:

    public interface B  extends A {
        default void call() {
            System.out.println("B call");
        }
    }

    C:

    public class C implements A, B {
    
    }

    D:

    public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            C c = new C();
            
            c.call();
    
        }

    运行结果:

    上面A和B都是接口。他们有call方法。其中关键是B继承了。说明B拥有A的一切方法。那么是不是说B就是最具体实现的。如果你们只用第一个标准的话,那是肯定不行的。
    还是简单一点,我们把B继承A的这个关系去掉,在来看看。

    不好意思好像报错了。所以只能苦一下了。显性调用。

    package com.aomi;
    
    public class C implements B, A {
    
        public void call() {
            B.super.call();
        }
    }

     当然除了上面之外,你还是可以定义静态方法和常量。这个时候有人就会说他不是跟抽象类很像吗?是很像。可是不一样子。抽象类是不是可以实例一个字段。但是接口却不行。还有抽像类你只能单继承。接口就可以多继承了。

    转载于:https://www.cnblogs.com/hayasi/p/10639994.html

    展开全文
  • JAVA8也为流在提供另一个功能——并行流。即是有并行流,那么是不是也有顺序流。没有错。我前面操作的一般都是顺序流。在JAVA8里面并行流和顺序流是可以转变的。来看一个例子——笔者打印数字。1 package com.aomi;...

    流,确定是笔者内心很向往的天堂,有他之后JAVA在处理数据就变更加的灵动。加上lambda表达不喜欢都不行。JAVA8也为流在提供另一个功能——并行流。即是有并行流,那么是不是也有顺序流。没有错。我前面操作的一般都是顺序流。在JAVA8里面并行流和顺序流是可以转变的。来看一个例子——笔者打印数字。

    1 package com.aomi;2

    3 import java.util.stream.LongStream;4

    5 public classMain {6

    7 public static voidmain(String[] args) {8 //TODO Auto-generated method stub

    9

    10 LongStream.range(0, 10).forEach(i ->{11 System.out.print(i + " ");12 });13 }14

    15 }

    LongStream.range这个方法是来获取数字的。这里表示获得0到10,但不含10 的数字。运行结果:

    1376afc783b6cfff9309d7d41e19d00f.png

    现在让我们把他换成并行来看看。

    1 package com.aomi;2

    3 import java.util.stream.LongStream;4

    5 public classMain {6

    7 public static voidmain(String[] args) {8 //TODO Auto-generated method stub

    9

    10 LongStream.range(0, 10).parallel().forEach(i ->{11 System.out.print(i + " ");12 });13 }14

    15 }

    运行结果:

    4b6ef5524f128029c0f31fc33a954b75.png

    俩个结果相比一下,我们就可以明显他们发生了变化。我们只是加一个parallel函数就发生好多的变化。笔者本来是要讲他们之间的性能比较的。不敢,因为笔者试好还有个例子。却发现有时候顺序流都比并行流来快。上面是顺序流转并行流。在来看一下相反的。

    1 public static voidmain(String[] args) {2 //TODO Auto-generated method stub

    3

    4 List datas = Arrays.asList(1,2,3,4,56);5

    6 datas.parallelStream().forEach(i ->{7 System.out.print(i + " ");8 });9 }

    parallelStream函数就是用来建一个并行流的。运行结果:

    9e601fdec0ed36dcb69181f888be1422.png

    转为顺序流

    1 public static voidmain(String[] args) {2 //TODO Auto-generated method stub

    3

    4 List datas = Arrays.asList(1,2,3,4,56);5

    6 datas.parallelStream().sequential().forEach(i ->{7 System.out.print(i + " ");8 });9 }

    运行结果:

    0f52d0716e3aed79eefa32feb8d2293f.png

    我们都知道流里面用到了JAVA7里面的分支和合并的框架来进行的。古代有一个词叫分而治之。把一个事情分为几个小事件。然面各自处理。所以了解代码里面是什么样子折分成小事件是非常重要的。他有俩个关键字Fork和Join。Fork方法你可以理解为拆分,并压入线程队列中。而Join就是合并的意思了。来笔者来写一个试。

    1 packagecom.aomi;2

    3 importjava.util.ArrayList;4 importjava.util.List;5 importjava.util.concurrent.RecursiveTask;6

    7 public class DistinctCharForkJoin extends RecursiveTask>{8

    9 private Listchars;10

    11 public DistinctCharForkJoin(Listchars) {12 this(chars, 0, chars.size());13 }14

    15 public DistinctCharForkJoin(List chars, int start, intend) {16

    17 this.chars =chars.subList(start, end);18 }19

    20 @Override21 protected Listcompute() {22 //TODO Auto-generated method stub

    23 List tmpChars = new ArrayList();24

    25 //判断不可以在拆分了

    26 if (this.chars.size() < 3) {27

    28 for(Character character : chars) {29 if (!tmpChars.contains(character))30 tmpChars.add(character);31 }32

    33 } else {//表示可以在拆分。

    34

    35 int len = this.chars.size();36

    37 //建立左边的小事件

    38 DistinctCharForkJoin leftForkJoin = new DistinctCharForkJoin(chars, 0, len / 2);39

    40 leftForkJoin.fork();41

    42 //建立右边的小事件

    43 DistinctCharForkJoin rightForkJoin = new DistinctCharForkJoin(chars, len / 2, len);44

    45 rightForkJoin.fork();46

    47 List rChars =rightForkJoin.join();48

    49 List lChars =leftForkJoin.join();50

    51 //俩个合并。

    52 for(Character character : rChars) {53 if (!tmpChars.contains(character))54 tmpChars.add(character);55 }56

    57 for(Character character : lChars) {58 if (!tmpChars.contains(character))59 tmpChars.add(character);60 }61

    62 }63

    64 returntmpChars;65 }66

    67 }

    Main:

    1 public static voidmain(String[] args) {2 //TODO Auto-generated method stub

    3

    4 List chars = Arrays.asList('a', 'b', 'c', 'd', 'b', 'a');5

    6 DistinctCharForkJoin task = new DistinctCharForkJoin("main", chars);7

    8 List resChars = newForkJoinPool().invoke(task);9

    10 for(Character character : resChars) {11

    12 System.out.print(character +" ");13 }14 }

    运行结果:

    39fc1a685d41fffdf75f719df26aa76b.png

    你们一定很奇怪为什么笔者会讲到JAVA7带来的东西呢?JAVA8引入了一个新的接口——Spliterator接口。人称可分迭代器。如果你有心去看一个接口List的话,你可能会发现一个方法。如下

    1 default Spliteratorspliterator() {2 return Spliterators.spliterator(this, Spliterator.ORDERED);3 }

    Spliterator接口:

    1 public interface Spliterator{2 boolean tryAdvance(Consumer super T>action);3 SpliteratortrySplit();4 longestimateSize();5 intcharacteristics();6 }

    讲JAVA7里面的分支/合并的目地就是为了理解Spliterator接口的作用。如下

    tryAdvance:用于遍历当前的元素。如果还有的话,就返回true;

    trySplit:用于拆分。如果当前不可以在拆分的话,就返回null;跟上面的compute方法很像。

    estimateSize:表示还需要遍历的元素有多少。

    characteristics:表示当前处理的数据是什么样子的。比如是否有序,每一元素是否为null。上面Spliterator接口的代码是笔者去掉大部分复制出来。这个值都在代码中。作用你们可以自己去看一下代码就是知道。

    要注意Spliterator接口只是用去拆分任务的作用。JAVA8帮你做了很多拆分的功能。大部分你可以不用自己写。当然如果你想要自己动手。你只要实现这样子就可以了。如下

    1 packagecom.aomi;2

    3 importjava.util.List;4 importjava.util.Spliterator;5 importjava.util.function.Consumer;6

    7 public class DistinctCharSpliterator implements Spliterator{8

    9 private Listchars;10 private int index = 0;11

    12 public DistinctCharSpliterator(Listchars) {13 this.chars =chars;14 }15

    16 public DistinctCharSpliterator(List chars, int start, intend) {17 this.chars =chars.subList(start, end);18 }19

    20 @Override21 public boolean tryAdvance(Consumer super Character>action) {22 //TODO Auto-generated method stub

    23 action.accept(this.chars.get(index++));24 return index < this.chars.size();25 }26

    27 @Override28 public SpliteratortrySplit() {29 //TODO Auto-generated method stub

    30 int difLen = this.chars.size() -index;31

    32 //判断不可以在拆分了

    33 if (difLen < 3) {34 return null;35 } else {//表示可以在拆分。

    36

    37

    38 DistinctCharSpliterator spliterator = new DistinctCharSpliterator(chars.subList(index, index + 2));39

    40 index = index + 2;41

    42 returnspliterator;43

    44 }45 }46

    47 @Override48 public longestimateSize() {49 //TODO Auto-generated method stub

    50 return this.chars.size() -index;51 }52

    53 @Override54 public intcharacteristics() {55 //TODO Auto-generated method stub56 //有序 元素不空 遍历过程不能删除,和修改 增加

    57 return ORDERED + NONNULL +IMMUTABLE;58 }59

    60 }

    Main:

    1 public static voidmain(String[] args) {2 //TODO Auto-generated method stub

    3

    4 List chars = Arrays.asList('a', 'b', 'c', 'd', 'b', 'a');5

    6 DistinctCharSpliterator distinctCharSpliterator = newDistinctCharSpliterator(chars);7

    8 Stream stream = StreamSupport.stream(distinctCharSpliterator, true);9

    10 stream.distinct().forEach((Character ch) ->{11

    12 System.out.print(ch+" ");13 });14

    15 }

    运行结果:

    18e84fc1d482fe9587cd0c0bf459657e.png

    上面的例子有一点烂。但是大家可以复制做一下继点去看看他的执行过程。就可以看出很多东西来。主要是理解这个原理就可以了。

    流的并行功能并没有让笔者有多心动。真正让笔者感觉不错的要属于JAVA8对接口的升级。什么意思?笔者不清楚有多少个人写个框架或是读过框架源码,一般框架里面都会用到一些面向接口的编程模式。那个或多或少会有这样子感觉。一但项目发布出去,这个时候你想要修改接口。比如在接口里面增加一个新的功能方法。这样子时候你就不得不考虑一下外面有多少个人在实现你现在框架的接口。因为你增加一个接口的新方法。别人也要跟着实现,不然的一定会报错或是运行时候报错。不管哪一种都是设计者不想看到的。

    JAVA8现在可以让你定义接口的默认方法。什么思意呢?让笔得写一个例子。

    Base接口:

    1 packagecom.aomi;2

    3 public interfaceBase {4 voidcall();5 }

    BaseA类:

    1 packagecom.aomi;2

    3 public class BaseA implementsBase {4

    5 @Override6 public voidcall() {7

    8 }9

    10 }

    Main:

    1 packagecom.aomi;2

    3 public classMain {4

    5 public static voidmain(String[] args) {6 //TODO Auto-generated method stub

    7

    8 Base baseA = newBaseA();9

    10 baseA.call();11 }12 }

    上面的代码没有什么特别的。现在笔者在加一个方法。看一个他会不会有问题。如下

    base类:

    1 packagecom.aomi;2

    3 public interfaceBase {4 voidcall();5 voidcall2();6 }

    结果:

    11a5bc8e611f6f6f31fcba957a6dde15.png

    看到吧。BaseA类马上就报错。现在笔者在加上一个默认的方法会什么呢?

    packagecom.aomi;public interfaceBase {voidcall();default voidcall2() {

    System.out.println("default call2");

    }

    }

    Main修改一下吧。

    1 packagecom.aomi;2

    3 public classMain {4

    5 public static voidmain(String[] args) {6 //TODO Auto-generated method stub

    7

    8 Base baseA = newBaseA();9

    10 baseA.call2();11 }12 }

    运行结果:

    9387b716ae5989e19131bb0271331b83.png

    上面的代码。笔者在BaseA类里面并没有实现call2的方法。显然现在的功能对我们写框架的人来写太棒了。在也不用担心增加一个接方法而去考虑有多少个人用这个接口了。

    那么问题来了。我们在写代码的过程中,一定会遇到方法相同的情况吧。这个时候JAVA8提供了三个标准来确定用哪一个。

    类或父类的方法优先级高于接口默认的方法。

    如果上面不行的话,谁拥有最具体的实现的话,就用谁。

    如果都不能确定的情况下,就必须显性的调用。来指定他要调哪一个。

    举例子。A和B都是接口。其中B继承了A。同时C实现了A和B。这个时候调用C会是什么样子。

    A:

    public interfaceA {default voidcall() {

    System.out.println("A call");

    }

    }

    B:

    public interface B extendsA {default voidcall() {

    System.out.println("B call");

    }

    }

    C:

    public class C implementsA, B {

    }

    D:

    public static voidmain(String[] args) {//TODO Auto-generated method stub

    C c= newC();

    c.call();

    }

    运行结果:

    a3ab4409dd70dfe12c9291f753dfb6df.png

    上面A和B都是接口。他们有call方法。其中关键是B继承了。说明B拥有A的一切方法。那么是不是说B就是最具体实现的。如果你们只用第一个标准的话,那是肯定不行的。

    还是简单一点,我们把B继承A的这个关系去掉,在来看看。

    2e589155878e0c955a4f85c143e0e572.png

    不好意思好像报错了。所以只能苦一下了。显性调用。

    packagecom.aomi;public class C implementsB, A {public voidcall() {

    B.super.call();

    }

    }

    当然除了上面之外,你还是可以定义静态方法和常量。这个时候有人就会说他不是跟抽象类很像吗?是很像。可是不一样子。抽象类是不是可以实例一个字段。但是接口却不行。还有抽像类你只能单继承。接口就可以多继承了。

    展开全文
  • JAVA8给我带了什么——并流行和接口功能流,确定是笔者内心很向往的天堂,有他之后JAVA在处理数据就变更加的灵动。加上lambda表达不喜欢都不行。JAVA8也为流在提供另一个功能——并行流。即是有并行流,那么是不是...

    JAVA8给我带了什么——并流行和接口新功能
    流,确定是笔者内心很向往的天堂,有他之后JAVA在处理数据就变更加的灵动。加上lambda表达不喜欢都不行。JAVA8也为流在提供另一个功能——并行流。即是有并行流,那么是不是也有顺序流。没有错。我前面操作的一般都是顺序流。在JAVA8里面并行流和顺序流是可以转变的。来看一个例子——笔者打印数字。

    复制代码
    1 package com.aomi;
    2
    3 import java.util.stream.LongStream;
    4
    5 public class Main {
    6
    7 public static void main(String[] args) {
    8 // TODO Auto-generated method stub
    9
    10 LongStream.range(0, 10).forEach(i -> {
    11 System.out.print(i + " ");
    12 });
    13 }
    14
    15 }
    复制代码
    LongStream.range这个方法是来获取数字的。这里表示获得0到10,但不含10 的数字。运行结果:

    现在让我们把他换成并行来看看。

    复制代码
    1 package com.aomi;
    2
    3 import java.util.stream.LongStream;
    4
    5 public class Main {
    6
    7 public static void main(String[] args) {
    8 // TODO Auto-generated method stub
    9
    10 LongStream.range(0, 10).parallel().forEach(i -> {
    11 System.out.print(i + " ");
    12 });
    13 }
    14
    15 }
    复制代码
    运行结果:

    俩个结果相比一下,我们就可以明显他们发生了变化。我们只是加一个parallel函数就发生好多的变化。笔者本来是要讲他们之间的性能比较的。不敢,因为笔者试好还有个例子。却发现有时候顺序流都比并行流来快。上面是顺序流转并行流。在来看一下相反的。

    复制代码
    1 public static void main(String[] args) {
    2 // TODO Auto-generated method stub
    3
    4 List datas = Arrays.asList(1,2,3,4,56);
    5
    6 datas.parallelStream().forEach(i -> {
    7 System.out.print(i + " ");
    8 });
    9 }
    复制代码
    parallelStream函数就是用来建一个并行流的。运行结果:

    转为顺序流

    复制代码
    1 public static void main(String[] args) {
    2 // TODO Auto-generated method stub
    3
    4 List datas = Arrays.asList(1,2,3,4,56);
    5
    6 datas.parallelStream().sequential().forEach(i -> {
    7 System.out.print(i + " ");
    8 });
    9 }
    复制代码
    运行结果:

    我们都知道流里面用到了JAVA7里面的分支和合并的框架来进行的。古代有一个词叫分而治之。把一个事情分为几个小事件。然面各自处理。所以了解代码里面是什么样子折分成小事件是非常重要的。他有俩个关键字Fork和Join。Fork方法你可以理解为拆分,并压入线程队列中。而Join就是合并的意思了。来笔者来写一个试。

    复制代码
    1 package com.aomi;
    2
    3 import java.util.ArrayList;
    4 import java.util.List;
    5 import java.util.concurrent.RecursiveTask;
    6
    7 public class DistinctCharForkJoin extends RecursiveTask> {
    8
    9 private List chars;
    10
    11 public DistinctCharForkJoin(List chars) {
    12 this(chars, 0, chars.size());
    13 }
    14
    15 public DistinctCharForkJoin(List chars, int start, int end) {
    16
    17 this.chars = chars.subList(start, end);
    18 }
    19
    20 @Override
    21 protected List compute() {
    22 // TODO Auto-generated method stub
    23 List tmpChars = new ArrayList();
    24
    25 // 判断不可以在拆分了
    26 if (this.chars.size() < 3) {
    27
    28 for (Character character : chars) {
    29 if (!tmpChars.contains(character))
    30 tmpChars.add(character);
    31 }
    32
    33 } else {// 表示可以在拆分。
    34
    35 int len = this.chars.size();
    36
    37 // 建立左边的小事件
    38 DistinctCharForkJoin leftForkJoin = new DistinctCharForkJoin(chars, 0, len / 2);
    39
    40 leftForkJoin.fork();
    41
    42 // 建立右边的小事件
    43 DistinctCharForkJoin rightForkJoin = new DistinctCharForkJoin(chars, len / 2, len);
    44
    45 rightForkJoin.fork();
    46
    47 List rChars = rightForkJoin.join();
    48
    49 List lChars = leftForkJoin.join();
    50
    51 // 俩个合并。
    52 for (Character character : rChars) {
    53 if (!tmpChars.contains(character))
    54 tmpChars.add(character);
    55 }
    56
    57 for (Character character : lChars) {
    58 if (!tmpChars.contains(character))
    59 tmpChars.add(character);
    60 }
    61
    62 }
    63
    64 return tmpChars;
    65 }
    66
    67 }
    复制代码
    Main:

    复制代码
    1 public static void main(String[] args) {
    2 // TODO Auto-generated method stub
    3
    4 List chars = Arrays.asList('a', 'b', 'c', 'd', 'b', 'a');
    5
    6 DistinctCharForkJoin task = new DistinctCharForkJoin("main", chars);
    7
    8 List resChars = new ForkJoinPool().invoke(task);
    9
    10 for (Character character : resChars) {
    11
    12 System.out.print(character +" ");
    13 }
    14 }
    复制代码
    运行结果:

    你们一定很奇怪为什么笔者会讲到JAVA7带来的东西呢?JAVA8引入了一个新的接口——Spliterator接口。人称可分迭代器。如果你有心去看一个接口List的话,你可能会发现一个方法。如下

    1 default Spliterator spliterator() {
    2 return Spliterators.spliterator(this, Spliterator.ORDERED);
    3 }
    Spliterator接口:

    1 public interface Spliterator {
    2 boolean tryAdvance(Consumer<? super T> action);
    3 Spliterator trySplit();
    4 long estimateSize();
    5 int characteristics();
    6 }
    讲JAVA7里面的分支/合并的目地就是为了理解Spliterator接口的作用。如下

    tryAdvance:用于遍历当前的元素。如果还有的话,就返回true;
    trySplit:用于拆分。如果当前不可以在拆分的话,就返回null;跟上面的compute方法很像。
    estimateSize:表示还需要遍历的元素有多少。
    characteristics:表示当前处理的数据是什么样子的。比如是否有序,每一元素是否为null。上面Spliterator接口的代码是笔者去掉大部分复制出来。这个值都在代码中。作用你们可以自己去看一下代码就是知道。
    要注意Spliterator接口只是用去拆分任务的作用。JAVA8帮你做了很多拆分的功能。大部分你可以不用自己写。当然如果你想要自己动手。你只要实现这样子就可以了。如下

    复制代码
    1 package com.aomi;
    2
    3 import java.util.List;
    4 import java.util.Spliterator;
    5 import java.util.function.Consumer;
    6
    7 public class DistinctCharSpliterator implements Spliterator {
    8
    9 private List chars;
    10 private int index = 0;
    11
    12 public DistinctCharSpliterator(List chars) {
    13 this.chars = chars;
    14 }
    15
    16 public DistinctCharSpliterator(List chars, int start, int end) {
    17 this.chars = chars.subList(start, end);
    18 }
    19
    20 @Override
    21 public boolean tryAdvance(Consumer<? super Character> action) {
    22 // TODO Auto-generated method stub
    23 action.accept(this.chars.get(index++));
    24 return index < this.chars.size();
    25 }
    26
    27 @Override
    28 public Spliterator trySplit() {
    29 // TODO Auto-generated method stub
    30 int difLen = this.chars.size() - index;
    31
    32 // 判断不可以在拆分了
    33 if (difLen < 3) {
    34 return null;
    35 } else {// 表示可以在拆分。
    36
    37
    38 DistinctCharSpliterator spliterator = new DistinctCharSpliterator(chars.subList(index, index + 2));
    39
    40 index = index + 2;
    41
    42 return spliterator;
    43
    44 }
    45 }
    46
    47 @Override
    48 public long estimateSize() {
    49 // TODO Auto-generated method stub
    50 return this.chars.size() - index;
    51 }
    52
    53 @Override
    54 public int characteristics() {
    55 // TODO Auto-generated method stub
    56 // 有序 元素不空 遍历过程不能删除,和修改 增加
    57 return ORDERED + NONNULL + IMMUTABLE;
    58 }
    59
    60 }
    复制代码
    Main:

    复制代码
    1 public static void main(String[] args) {
    2 // TODO Auto-generated method stub
    3
    4 List chars = Arrays.asList('a', 'b', 'c', 'd', 'b', 'a');
    5
    6 DistinctCharSpliterator distinctCharSpliterator = new DistinctCharSpliterator(chars);
    7
    8 Stream stream = StreamSupport.stream(distinctCharSpliterator, true);
    9
    10 stream.distinct().forEach((Character ch) -> {
    11
    12 System.out.print(ch+" ");
    13 });
    14
    15 }
    复制代码
    运行结果:

    上面的例子有一点烂。但是大家可以复制做一下继点去看看他的执行过程。就可以看出很多东西来。主要是理解这个原理就可以了。
    流的并行功能并没有让笔者有多心动。真正让笔者感觉不错的要属于JAVA8对接口的升级。什么意思?笔者不清楚有多少个人写个框架或是读过框架源码,一般框架里面都会用到一些面向接口的编程模式。那个或多或少会有这样子感觉。一但项目发布出去,这个时候你想要修改接口。比如在接口里面增加一个新的功能方法。这样子时候你就不得不考虑一下外面有多少个人在实现你现在框架的接口。因为你增加一个接口的新方法。别人也要跟着实现,不然的一定会报错或是运行时候报错。不管哪一种都是设计者不想看到的。
    JAVA8现在可以让你定义接口的默认方法。什么思意呢?让笔得写一个例子。

    Base接口:

    1 package com.aomi;
    2
    3 public interface Base {
    4 void call();
    5 }
    BaseA类:

    复制代码
    1 package com.aomi;
    2
    3 public class BaseA implements Base {
    4
    5 @Override
    6 public void call() {
    7
    8 }
    9
    10 }
    复制代码
    Main:

    复制代码
    1 package com.aomi;
    2
    3 public class Main {
    4
    5 public static void main(String[] args) {
    6 // TODO Auto-generated method stub
    7
    8 Base baseA = new BaseA();
    9
    10 baseA.call();
    11 }
    12 }
    复制代码
    上面的代码没有什么特别的。现在笔者在加一个方法。看一个他会不会有问题。如下

    base类:

    1 package com.aomi;
    2
    3 public interface Base {
    4 void call();
    5 void call2();
    6 }
    结果:

    看到吧。BaseA类马上就报错。现在笔者在加上一个默认的方法会什么呢?

    复制代码
    package com.aomi;

    public interface Base {

    void call();
    
    default void call2() {
        System.out.println("default call2");
    }

    }
    复制代码
    Main修改一下吧。

    复制代码
    1 package com.aomi;
    2
    3 public class Main {
    4
    5 public static void main(String[] args) {
    6 // TODO Auto-generated method stub
    7
    8 Base baseA = new BaseA();
    9
    10 baseA.call2();
    11 }
    12 }
    复制代码
    运行结果:

    上面的代码。笔者在BaseA类里面并没有实现call2的方法。显然现在的功能对我们写框架的人来写太棒了。在也不用担心增加一个接方法而去考虑有多少个人用这个接口了。
    那么问题来了。我们在写代码的过程中,一定会遇到方法相同的情况吧。这个时候JAVA8提供了三个标准来确定用哪一个。

    类或父类的方法优先级高于接口默认的方法。
    如果上面不行的话,谁拥有最具体的实现的话,就用谁。
    如果都不能确定的情况下,就必须显性的调用。来指定他要调哪一个。
    举例子。A和B都是接口。其中B继承了A。同时C实现了A和B。这个时候调用C会是什么样子。
    A:

    public interface A {

    default void call() {
        System.out.println("A call");
    }

    }
    B:

    public interface B extends A {

    default void call() {
        System.out.println("B call");
    }

    }
    C:

    public class C implements A, B {

    }
    D:

    复制代码
    public static void main(String[] args) {

        // TODO Auto-generated method stub
    
        C c = new C();
        
        c.call();
    
    }

    复制代码
    运行结果:

    上面A和B都是接口。他们有call方法。其中关键是B继承了。说明B拥有A的一切方法。那么是不是说B就是最具体实现的。如果你们只用第一个标准的话,那是肯定不行的。
    还是简单一点,我们把B继承A的这个关系去掉,在来看看。

    不好意思好像报错了。所以只能苦一下了。显性调用。

    复制代码
    package com.aomi;

    public class C implements B, A {

    public void call() {
        B.super.call();
    }

    }
    复制代码
    当然除了上面之外,你还是可以定义静态方法和常量。这个时候有人就会说他不是跟抽象类很像吗?是很像。可是不一样子。抽象类是不是可以实例一个字段。但是接口却不行。还有抽像类你只能单继承。接口就可以多继承了。
    原文地址https://www.cnblogs.com/hayasi/p/10639994.html

    展开全文
  • JAVA8给我带了什么——并流行和接口功能流,确定是笔者内心很向往的天堂,有他之后JAVA在处理数据就变更加的灵动。加上lambda表达不喜欢都不行。JAVA8也为流在提供另一个功能——并行流。即是有并行流,那么是不是...

    JAVA8给我带了什么——并流行和接口新功能
    流,确定是笔者内心很向往的天堂,有他之后JAVA在处理数据就变更加的灵动。加上lambda表达不喜欢都不行。JAVA8也为流在提供另一个功能——并行流。即是有并行流,那么是不是也有顺序流。没有错。我前面操作的一般都是顺序流。在JAVA8里面并行流和顺序流是可以转变的。来看一个例子——笔者打印数字。

    复制代码
    1 package com.aomi;
    2
    3 import java.util.stream.LongStream;
    4
    5 public class Main {
    6
    7 public static void main(String[] args) {
    8 // TODO Auto-generated method stub
    9
    10 LongStream.range(0, 10).forEach(i -> {
    11 System.out.print(i + " ");
    12 });
    13 }
    14
    15 }
    复制代码
    LongStream.range这个方法是来获取数字的。这里表示获得0到10,但不含10 的数字。运行结果:

    现在让我们把他换成并行来看看。

    复制代码
    1 package com.aomi;
    2
    3 import java.util.stream.LongStream;
    4
    5 public class Main {
    6
    7 public static void main(String[] args) {
    8 // TODO Auto-generated method stub
    9
    10 LongStream.range(0, 10).parallel().forEach(i -> {
    11 System.out.print(i + " ");
    12 });
    13 }
    14
    15 }
    复制代码
    运行结果:

    俩个结果相比一下,我们就可以明显他们发生了变化。我们只是加一个parallel函数就发生好多的变化。笔者本来是要讲他们之间的性能比较的。不敢,因为笔者试好还有个例子。却发现有时候顺序流都比并行流来快。上面是顺序流转并行流。在来看一下相反的。

    复制代码
    1 public static void main(String[] args) {
    2 // TODO Auto-generated method stub
    3
    4 List datas = Arrays.asList(1,2,3,4,56);
    5
    6 datas.parallelStream().forEach(i -> {
    7 System.out.print(i + " ");
    8 });
    9 }
    复制代码
    parallelStream函数就是用来建一个并行流的。运行结果:

    转为顺序流

    复制代码
    1 public static void main(String[] args) {
    2 // TODO Auto-generated method stub
    3
    4 List datas = Arrays.asList(1,2,3,4,56);
    5
    6 datas.parallelStream().sequential().forEach(i -> {
    7 System.out.print(i + " ");
    8 });
    9 }
    复制代码
    运行结果:

    我们都知道流里面用到了JAVA7里面的分支和合并的框架来进行的。古代有一个词叫分而治之。把一个事情分为几个小事件。然面各自处理。所以了解代码里面是什么样子折分成小事件是非常重要的。他有俩个关键字Fork和Join。Fork方法你可以理解为拆分,并压入线程队列中。而Join就是合并的意思了。来笔者来写一个试。

    复制代码
    1 package com.aomi;
    2
    3 import java.util.ArrayList;
    4 import java.util.List;
    5 import java.util.concurrent.RecursiveTask;
    6
    7 public class DistinctCharForkJoin extends RecursiveTask> {
    8
    9 private List chars;
    10
    11 public DistinctCharForkJoin(List chars) {
    12 this(chars, 0, chars.size());
    13 }
    14
    15 public DistinctCharForkJoin(List chars, int start, int end) {
    16
    17 this.chars = chars.subList(start, end);
    18 }
    19
    20 @Override
    21 protected List compute() {
    22 // TODO Auto-generated method stub
    23 List tmpChars = new ArrayList();
    24
    25 // 判断不可以在拆分了
    26 if (this.chars.size() < 3) {
    27
    28 for (Character character : chars) {
    29 if (!tmpChars.contains(character))
    30 tmpChars.add(character);
    31 }
    32
    33 } else {// 表示可以在拆分。
    34
    35 int len = this.chars.size();
    36
    37 // 建立左边的小事件
    38 DistinctCharForkJoin leftForkJoin = new DistinctCharForkJoin(chars, 0, len / 2);
    39
    40 leftForkJoin.fork();
    41
    42 // 建立右边的小事件
    43 DistinctCharForkJoin rightForkJoin = new DistinctCharForkJoin(chars, len / 2, len);
    44
    45 rightForkJoin.fork();
    46
    47 List rChars = rightForkJoin.join();
    48
    49 List lChars = leftForkJoin.join();
    50
    51 // 俩个合并。
    52 for (Character character : rChars) {
    53 if (!tmpChars.contains(character))
    54 tmpChars.add(character);
    55 }
    56
    57 for (Character character : lChars) {
    58 if (!tmpChars.contains(character))
    59 tmpChars.add(character);
    60 }
    61
    62 }
    63
    64 return tmpChars;
    65 }
    66
    67 }
    复制代码
    Main:

    复制代码
    1 public static void main(String[] args) {
    2 // TODO Auto-generated method stub
    3
    4 List chars = Arrays.asList('a', 'b', 'c', 'd', 'b', 'a');
    5
    6 DistinctCharForkJoin task = new DistinctCharForkJoin("main", chars);
    7
    8 List resChars = new ForkJoinPool().invoke(task);
    9
    10 for (Character character : resChars) {
    11
    12 System.out.print(character +" ");
    13 }
    14 }
    复制代码
    运行结果:

    你们一定很奇怪为什么笔者会讲到JAVA7带来的东西呢?JAVA8引入了一个新的接口——Spliterator接口。人称可分迭代器。如果你有心去看一个接口List的话,你可能会发现一个方法。如下

    1 default Spliterator spliterator() {
    2 return Spliterators.spliterator(this, Spliterator.ORDERED);
    3 }
    Spliterator接口:

    1 public interface Spliterator {
    2 boolean tryAdvance(Consumer<? super T> action);
    3 Spliterator trySplit();
    4 long estimateSize();
    5 int characteristics();
    6 }
    讲JAVA7里面的分支/合并的目地就是为了理解Spliterator接口的作用。如下

    tryAdvance:用于遍历当前的元素。如果还有的话,就返回true;
    trySplit:用于拆分。如果当前不可以在拆分的话,就返回null;跟上面的compute方法很像。
    estimateSize:表示还需要遍历的元素有多少。
    characteristics:表示当前处理的数据是什么样子的。比如是否有序,每一元素是否为null。上面Spliterator接口的代码是笔者去掉大部分复制出来。这个值都在代码中。作用你们可以自己去看一下代码就是知道。
    要注意Spliterator接口只是用去拆分任务的作用。JAVA8帮你做了很多拆分的功能。大部分你可以不用自己写。当然如果你想要自己动手。你只要实现这样子就可以了。如下

    复制代码
    1 package com.aomi;
    2
    3 import java.util.List;
    4 import java.util.Spliterator;
    5 import java.util.function.Consumer;
    6
    7 public class DistinctCharSpliterator implements Spliterator {
    8
    9 private List chars;
    10 private int index = 0;
    11
    12 public DistinctCharSpliterator(List chars) {
    13 this.chars = chars;
    14 }
    15
    16 public DistinctCharSpliterator(List chars, int start, int end) {
    17 this.chars = chars.subList(start, end);
    18 }
    19
    20 @Override
    21 public boolean tryAdvance(Consumer<? super Character> action) {
    22 // TODO Auto-generated method stub
    23 action.accept(this.chars.get(index++));
    24 return index < this.chars.size();
    25 }
    26
    27 @Override
    28 public Spliterator trySplit() {
    29 // TODO Auto-generated method stub
    30 int difLen = this.chars.size() - index;
    31
    32 // 判断不可以在拆分了
    33 if (difLen < 3) {
    34 return null;
    35 } else {// 表示可以在拆分。
    36
    37
    38 DistinctCharSpliterator spliterator = new DistinctCharSpliterator(chars.subList(index, index + 2));
    39
    40 index = index + 2;
    41
    42 return spliterator;
    43
    44 }
    45 }
    46
    47 @Override
    48 public long estimateSize() {
    49 // TODO Auto-generated method stub
    50 return this.chars.size() - index;
    51 }
    52
    53 @Override
    54 public int characteristics() {
    55 // TODO Auto-generated method stub
    56 // 有序 元素不空 遍历过程不能删除,和修改 增加
    57 return ORDERED + NONNULL + IMMUTABLE;
    58 }
    59
    60 }
    复制代码
    Main:

    复制代码
    1 public static void main(String[] args) {
    2 // TODO Auto-generated method stub
    3
    4 List chars = Arrays.asList('a', 'b', 'c', 'd', 'b', 'a');
    5
    6 DistinctCharSpliterator distinctCharSpliterator = new DistinctCharSpliterator(chars);
    7
    8 Stream stream = StreamSupport.stream(distinctCharSpliterator, true);
    9
    10 stream.distinct().forEach((Character ch) -> {
    11
    12 System.out.print(ch+" ");
    13 });
    14
    15 }
    复制代码
    运行结果:

    上面的例子有一点烂。但是大家可以复制做一下继点去看看他的执行过程。就可以看出很多东西来。主要是理解这个原理就可以了。
    流的并行功能并没有让笔者有多心动。真正让笔者感觉不错的要属于JAVA8对接口的升级。什么意思?笔者不清楚有多少个人写个框架或是读过框架源码,一般框架里面都会用到一些面向接口的编程模式。那个或多或少会有这样子感觉。一但项目发布出去,这个时候你想要修改接口。比如在接口里面增加一个新的功能方法。这样子时候你就不得不考虑一下外面有多少个人在实现你现在框架的接口。因为你增加一个接口的新方法。别人也要跟着实现,不然的一定会报错或是运行时候报错。不管哪一种都是设计者不想看到的。
    JAVA8现在可以让你定义接口的默认方法。什么思意呢?让笔得写一个例子。

    Base接口:

    1 package com.aomi;
    2
    3 public interface Base {
    4 void call();
    5 }
    BaseA类:

    复制代码
    1 package com.aomi;
    2
    3 public class BaseA implements Base {
    4
    5 @Override
    6 public void call() {
    7
    8 }
    9
    10 }
    复制代码
    Main:

    复制代码
    1 package com.aomi;
    2
    3 public class Main {
    4
    5 public static void main(String[] args) {
    6 // TODO Auto-generated method stub
    7
    8 Base baseA = new BaseA();
    9
    10 baseA.call();
    11 }
    12 }
    复制代码
    上面的代码没有什么特别的。现在笔者在加一个方法。看一个他会不会有问题。如下

    base类:

    1 package com.aomi;
    2
    3 public interface Base {
    4 void call();
    5 void call2();
    6 }
    结果:

    看到吧。BaseA类马上就报错。现在笔者在加上一个默认的方法会什么呢?

    复制代码
    package com.aomi;

    public interface Base {

    void call();
    
    default void call2() {
        System.out.println("default call2");
    }

    }
    复制代码
    Main修改一下吧。

    复制代码
    1 package com.aomi;
    2
    3 public class Main {
    4
    5 public static void main(String[] args) {
    6 // TODO Auto-generated method stub
    7
    8 Base baseA = new BaseA();
    9
    10 baseA.call2();
    11 }
    12 }
    复制代码
    运行结果:

    上面的代码。笔者在BaseA类里面并没有实现call2的方法。显然现在的功能对我们写框架的人来写太棒了。在也不用担心增加一个接方法而去考虑有多少个人用这个接口了。
    那么问题来了。我们在写代码的过程中,一定会遇到方法相同的情况吧。这个时候JAVA8提供了三个标准来确定用哪一个。

    类或父类的方法优先级高于接口默认的方法。
    如果上面不行的话,谁拥有最具体的实现的话,就用谁。
    如果都不能确定的情况下,就必须显性的调用。来指定他要调哪一个。
    举例子。A和B都是接口。其中B继承了A。同时C实现了A和B。这个时候调用C会是什么样子。
    A:

    public interface A {

    default void call() {
        System.out.println("A call");
    }

    }
    B:

    public interface B extends A {

    default void call() {
        System.out.println("B call");
    }

    }
    C:

    public class C implements A, B {

    }
    D:

    复制代码
    public static void main(String[] args) {

        // TODO Auto-generated method stub
    
        C c = new C();
        
        c.call();
    
    }

    复制代码
    运行结果:

    上面A和B都是接口。他们有call方法。其中关键是B继承了。说明B拥有A的一切方法。那么是不是说B就是最具体实现的。如果你们只用第一个标准的话,那是肯定不行的。
    还是简单一点,我们把B继承A的这个关系去掉,在来看看。

    不好意思好像报错了。所以只能苦一下了。显性调用。

    复制代码
    package com.aomi;

    public class C implements B, A {

    public void call() {
        B.super.call();
    }

    }
    复制代码
    当然除了上面之外,你还是可以定义静态方法和常量。这个时候有人就会说他不是跟抽象类很像吗?是很像。可是不一样子。抽象类是不是可以实例一个字段。但是接口却不行。还有抽像类你只能单继承。接口就可以多继承了。
    原文地址https://www.cnblogs.com/hayasi/p/10639994.html

    展开全文
  • 接口的讲解: ... /* * 接口(interface) 是与类并行的一个概念 * 1.接口可以看做是一个特殊的抽象类。...接口定义的就是一种功能,此功能可以被类所实现(implements) * 比如:class CC extends DD implem...
  • 5.项目版本和接口快照功能并行,你可以为一个项目定义1.0,1.1,1.2版本,并且可以自由的在不同版本间切换回滚,再也不怕接口信息的遗失,同时接口也有快照功能,当你接口开发到一半或者接口需求变更的时候,可以...
  • 作者 | LieBrother责编 | 屠敏出品 | CSDN 博客什么是线程?试想一下没有线程的程序是怎么样的?百度网盘在上传文件时就无法下载文件了,得等文件上传完成后才能下载文件。这个我们现在看起来很反人性,因为我们习惯...
  • “确认”: 该键完成对其他功能键的确认,防止误按键,在键盘中除“复位”键外,其他功能键都必须加“确认”键才能完成所定义的功能。 “复位”: 该键为重启系统按键。在任何时候或者系统出现不正常状态时都可按下...
  • 1.最早的计算机是没有操作系统的,操作系统的诞生解决了什么问题? 2.什么是批处理操作系统,它有什么特点? 3.什么是分时操作系统,它有什么特点? 4.操作系统主要功能什么? 5.操作系统实现了对计算机资源的抽象,这...
  • 1最早的计算机是没有操作系统的,操作系统的诞生解决了什么问题? 2. 什么是批处理操作系统,它有什么特点? 3. 什么是分时操作系统,它有什么特点? 4. 操作系统主要功能什么? 5. 操作系统实现了对计算机...
  • MPI的使用小感

    2015-07-14 16:46:38
    我在做基于VTK的分布式数据的并行显示的时候,由于每个节点可能其上的数据并不一定最后显示在...我谈谈我用它做了什么,我也没有用到什么复杂的功能,主要就是用它的数据传输的功能,主要用到以下几个函数: MPI_Gat
  • Mapreduce#文档.docx

    2020-01-14 19:57:55
    可以进行拆分的前提是这些小任务可以并行计算,彼此间几乎没有依赖关系。 Reduce 负责“合”,即对 map 阶段的结果进行全局汇总。 这两个阶段合起来正是 MapReduce 思想的体现。 图:MapReduce 思想模型 还有一...
  • 前端模块化

    2021-03-17 10:08:51
    模块化是一种自顶向下的过程,通过把一个大的系统,逐步划分为一个个小的模块,这些模块内部封装了一些特定的功能,通过约定的接口对外暴露。各个模块之间互不干扰,易于插拔。 模块化可以解耦代码,更好地进行复用...
  • 现有的包装器运行缓慢,使用阻塞API,并且没有正常的面向对象的接口(用于选项)。 它阻止编写快速且更优雅的编程代码。 安装 composer require spacetab-io/wkhtmltopdf 用法 在您的机器上 简单案例 从HTML字符串...
  • 11.6.4 为什么没有使用我的索引 430 11.6.5 神话:索引中从不重用空间 435 11.6.6 神话:最有差别的元素应该在最前面 438 11.7 小结 441 第12章 数据类型 442 12.1 Oracle数据类型概述 442 12.2 字符和二进制...
  • 但是文档中没有实战用例,没有告诉我们哪些可行或者哪些不可行,什么情况下可行或者什么情况下不可行,为什么可行或者为什么不可行,它只是“公事公办”为你呈上厚厚的一摞文字,告诉你情况就是这样,你自己看着办吧...
  • 学习 FPGA 书籍分享

    2016-04-12 14:03:26
    ②、FPGA的学习,熟悉QuartusII软件的各种功能,各种逻辑算法设计,接口模块(RS232,LCD,VGA,SPI,I2c等)的设计,时序分析,硬件优化等,自己开始设计简单的FPGA板子。 ③、NiosII的学习,熟悉NiosII的开发流程,...
  • LINQ 实战 6/11

    2012-03-31 17:10:04
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 11/11

    2012-03-31 17:19:10
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 10/11

    2012-03-31 17:17:32
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 9/11

    2012-03-31 17:15:45
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 8/11

    2012-03-31 17:13:51
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 7/11

    2012-03-31 17:12:04
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 5/11

    2012-03-31 17:07:56
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 4/11

    2012-03-31 17:05:58
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 3/11

    2012-03-31 17:03:51
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 2/11

    2012-03-31 17:01:57
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...
  • LINQ 实战 1/11

    2012-03-31 16:59:57
    2.6.2 没有名字的类型也是类型 55 2.6.3 使用匿名类型改进实例程序 56 2.6.4 匿名类型的限制 57 2.7 小结 58 第3章 LINQ构建块 61 3.1 LINQ对.NET的扩展 61 3.1.1 语言扩展回顾 61 3.1.2 构成LINQ...

空空如也

空空如也

1 2 3 4 5 6
收藏数 113
精华内容 45
关键字:

并行接口没有什么功能