2014-05-14 31 views
1

在Java lambda expr中使用多態性時,我發現了一個有趣的行爲。我希望有人能對此有所瞭解。Java中的有趣行爲Lambda表達式的多態性

假設以下的事情:

public class Java8Test { 
    public static void main(String[] args) { 
     A a = new B(); 
     a.meth((z) -> System.out.println()); 
    } 
} 

interface X 
{ 
    void meth(int a); 
} 

interface Y 
{ 
    void meth(int a); 
} 

class A 
{ 
    void meth(X x) 
    { 
     System.out.println("A"); 
    } 

} 

class B extends A 
{ 
    void meth(X x) 
    { 
     System.out.println("B"); 
    } 
} 

如果運行Java8Test.main,我們得到的輸出

我們知道, 「一」 是指B的參考在運行時,所以它打印「B」 但是,當我們改變B類的方法類型如下

class B extends A 
{ 
    void meth(Y y) 
    { 
     System.out.println("B"); 
    } 
} 

如果運行Java8Test.main,我們得到的輸出

一個

我們知道, 「一」 是指B的在運行時的參考,但怎麼來它打印 「A」這次 ??

回答

3

lambda表達式是一種紅鯡魚。當您在B類改變方法簽名,它不再重寫

void meth(X x) 

方法在A級

+0

1.你認爲lamda簽名與B類meth()相匹配嗎? 2.此外,B的參考是在運行時不是A – SaK

+0

這只是表明你應該總是使用@Override: http://docs.oracle.com/javase/jp/8/api/java/lang/Override html的 –

1

在這兩種情況下,meth()版本B類被調用。

在第一種情況下,重寫meth()被調用和在第二種情況下繼承meth()被調用。

當你正在擴展A類,meth(X x)方法將來自父系的繼承和meth(X x)meth(Y y)兩種截然不同的方法存在於孩子B類。

PS:拉姆達表達式的類型爲目標類型

有用的文章,瞭解拉姆達的類型:

  1. Target typing
  2. Java 8 Lambda expressions
0

我認爲會發生以下情況。當你實現:

​​

通過B類,這種方法不會覆蓋:

void meth(X x) { 
    System.out.println("A"); 
} 
A級的

但變量:

A a = new B(); 

的類型爲A,因此聲明:

a.meth((z) -> System.out.println()); 

參照A的方法,因此將打印A