簡體   English   中英

Java 8中的本地類構造函數的方法引用如何工作?

[英]How do method references to local class constructors in Java 8 work?

這里的示例代碼無法在Java 8(1.8.0_40)中編譯,但在Eclipse 4.4 JDT獨立編譯器(Bundle-Version:3.10.0.v20140604-1726)中編譯並成功運行:

import java.util.Arrays;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
 * Test method references to local class constructors.
 */
public class LocalClassTest {

  public long sumOfLengths(String[] input) {
    class Sum {
      final long value;

      Sum(long value) {
        this.value = value;
      }

      Sum(Sum left, Sum right) {
        this.value = left.value + right.value;
      }

      Sum add(String s) {
        return new Sum(value + s.length());
      }
    }

    return Arrays.stream(input)
                 .reduce(new Sum(0), Sum::add, Sum::new)
               .value;
  }

  static String[] input =
      {
          "a", "ab", "abc"
      };

  @Test
  public void localClassConstructorMethodRefs() {
    assertEquals(sumOfLengths(input), 6);
  }
}

javac吐出以下錯誤消息:

Error:(32, 25) java: incompatible types: cannot infer type-variable(s) U
    (argument mismatch; invalid constructor reference
      cannot access constructor Sum(Sum,Sum)
        an enclosing instance of type LocalClassTest is not in scope)

通過JLS 15.9.2(確定封閉實例)和15.13.3(方法引用的運行時評估)閱讀,我不明白為什么這應該無法編譯,並且錯誤消息似乎完全錯誤,因為我可以手動構建一個在同一方法中的Sum實例就好了。

我發現之前的一個問題內部類的構造函數引用在運行時看起來與VerifyError相關失敗 ,並且那里的鏈接JDK問題( https://bugs.openjdk.java.net/browse/JDK-8037404 )表明了一系列問題。這方面的編譯問題; 也許這是一個更普遍的問題的另一個例子。 不過,我不確定我是否正確閱讀規范; 這可以用另一種方式工作嗎?

這看起來像處理本地類的編譯器錯誤(方法中的類聲明)。 如果您更改為內部類(在方法外移動類聲明),那么它可以正常工作。 您可以同時將其更改為靜態類,這將略微減少開銷。

(內部類和本地類都有一個對包含類的隱式引用,這意味着構造函數有一個“隱藏”的第一個參數,你可以用javap看到。我懷疑編譯器知道在使用Sum::new時補償這個隱藏參數Sum::new對於內部類來說是Sum::new的,但是對於本地類來說,邏輯是缺少的。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM