2017-05-01 27 views
5

Trong lớp bên dưới, tôi chuyển tham chiếu phương thức WordCounterEx::accumulate làm tham số thứ hai cho phương thức giảm. Chữ ký của phương thức giảm là:Tham chiếu phương thức không hoàn thành hợp đồng giao diện chức năng nhưng nó biên dịch. Làm thế nào nó có thể?

<U> U reduce(U identity, 
      BiFunction<U, ? super T, U> accumulator, 
      BinaryOperator<U> combiner); 

Do đó, thông số thứ hai của phương pháp giảm, phải hoàn thành công thức BiFunction. Nhưng phương pháp tích lũy được truyền không phải là BiFunction (nó chỉ có một tham số). Tại sao nó vẫn biên dịch?

public class WordCounterEx { 
    private final int counter; 
    private final boolean lastSpace; 

    public WordCounterEx(int counter, boolean lastSpace) { 
     this.counter = counter; 
     this.lastSpace = lastSpace; 
    } 

    public int countWords(Stream<Character> stream) { 
     WordCounterEx wordCounter = stream.reduce(new WordCounterEx(0, true), 
       //HOW CAN THIS WORK? here must come BiFunction - R apply(T t, U u); 
       WordCounterEx::accumulate, 
       WordCounterEx::combine); 
     return wordCounter.counter; 
    } 

    public WordCounterEx accumulate(Character c) { 
     if(Character.isWhitespace(c)) { 
      return lastSpace ? 
        this : 
        new WordCounterEx(counter, true); 
     } else { 
      return lastSpace ? 
        new WordCounterEx(counter+1, false) : 
        this; 
     } 
    } 

    public WordCounterEx combine(WordCounterEx wordCounter) { 
     return new WordCounterEx(counter + wordCounter.counter 
       ,wordCounter.lastSpace /*does not matter*/); 
    } 
} 

Trả lời

3

accumulate() là phương pháp thể hiện và bạn gọi nó theo tên lớp và tên phương thức (không phải ví dụ và tên phương pháp). Vì vậy, nếu tôi muốn gọi phương pháp bạn đang cho tôi, tôi thường sẽ làm myEx.accumulate(myCh). Vì vậy, tôi cung cấp hai thứ, ví dụ WordCounterEx và ký tự. Do đó, được sử dụng theo cách này, phương pháp được tính là BiFunction<WordCounterEx, ? super Character, WordCounterEx>.

Nếu thay vào đó bạn đã cho tôi ví dụ this::accumulate, đối tượng để gọi phương thức trên sẽ được trao (this), và nó có thể không còn được sử dụng như một BiFunction (trong Eclipse của tôi, tôi nhận được “Phương pháp này giảm (U, BiFunction, BinaryOperator) trong loại Stream không áp dụng cho các đối số (WordCounterEx, this :: accumulate, WordCounterEx :: combine) ”).

+2

Lưu ý rằng trong Java 8 bạn có thể vượt qua 'this' như một cuộc tranh cãi, khớp với chữ ký hoàn hảo: 'công khai WordCounterEx tích lũy (WordCounterEx này, Ký tự c)'. Điều này tương đương với phiên bản không có 'this' như một đối số, như trong câu hỏi. –

1

Phương pháp WordCounterEx#countWords thể được viết lại như sau:

public int countWordsWithInstance(Stream<Character> stream) { 
    WordCounterEx wordCounter = stream.reduce(new WordCounterEx(0, true), 
      this::accumulate, 
      WordCounterEx::combine); 
    return wordCounter.counter; 
} 

public WordCounterEx accumulate(WordCounterEx wc,Character c) { 
    if(Character.isWhitespace(c)) { 
     return wc.lastSpace ? 
       wc : 
       new WordCounterEx(wc.counter, true); 
    } else { 
     return wc.lastSpace ? 
       new WordCounterEx(wc.counter+1, false) : 
       wc; 
    } 
} 

Trong trường hợp này phương pháp tích lũy phải có WordCounterEx wc trong chữ ký của mình

+2

Điều đó đúng. Như một biến thể của cùng bạn có thể khai báo 'accumulate()' 'static' và tham chiếu đến nó như' WordCounterEx :: accumulate' (như trong câu hỏi của bạn) (điều này có tác dụng bởi vì, như bạn biết, phương thức 'static' được gọi mà không có một đối tượng). –

Các vấn đề liên quan