【问题标题】:Error: cannot use raw constructor reference with explicit type parameters for constructor错误:不能将原始构造函数引用与构造函数的显式类型参数一起使用
【发布时间】:2019-08-27 16:24:13
【问题描述】:

我有以下代码:

Main.java

public class Main {
  public static void main(String[] args) {
     TestProducer c = Test::<String>new;
     System.out.println(c.produce("Point"));
  }
}

Test.java

public class Test<N extends CharSequence> {
  private CharSequence name;

  public Test(N k) {
    name = k;
  }

  public String toString() {
    return name.toString();
  }
}

TestProducer.java

@FunctionalInterface
public interface TestProducer {
  public <N extends CharSequence> Test<N> produce(N str);
}

当我编译代码时,它会产生以下错误:

OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4)
> javac -classpath .:/run_dir/junit-4.12.jar -d . Main.java Test.java TestProducer.java
Main.java:3: error: invalid constructor reference
     TestProducer c = Test::<String>new;
                      ^
  cannot use raw constructor reference with explicit type parameters for constructor
1 error
compiler exit status 1

我有以下问题:

  1. 这里的“原始构造函数引用”是什么(这里的“显式类型参数”是&lt;String&gt;)?
  2. 为什么不能“使用原始构造函数引用和构造函数的显式类型参数”(推理/为什么这不是一个好主意)?
  3. 如何解决这个错误(创建一个只接受Strings 的TestProducer)?

编辑:

关于避免错误,以下是我的发现:
我可以将TestProducer 修改为以下内容:

@FunctionalInterface
public interface TestProducer<N extends CharSequence>
{
  public Test<N> produce(N str);
}

然后像这样更改Main.java

public class Main {
  public static void main(String[] args) {
     TestProducer<String> c = Test::new;
     System.out.println(c.produce("Point"));
  }
}

通过这样做,c::produce 将只接受 Strings,这符合我对问题 3 的意图。问题 1 和问题 2 仍不清楚。

【问题讨论】:

    标签: java compiler-errors


    【解决方案1】:

    您将TestProducer 接口定义为不是通用的,而是具有通用方法:

    Test<N> produce(N str);
    

    然后你尝试在赋值中绑定一个特定的类型:

    TestProducer c = Test::<String>new;
    

    但我现在这样说是完全有道理的:

    c.produce(new StringBuilder())
    

    它必须返回Test&lt;StringBuilder&gt;,而不是Test&lt;String&gt;

    您可能应该在界面上添加N 作为类型参数。

    【讨论】:

    • 这个答案很有用,因为最后一句话引出了我对第 3 部分的方法。如果你能回答前两个部分,我会接受这个答案。
    【解决方案2】:
    1. 从你的构造函数中移除类型见证。即使在 Java 8 中也不行。

      TestProducer c = Test::new;
      System.out.println(c.produce("Point"));
      
    2. 无论如何,您都不需要提供类型见证。 TestProducer 提供了一个基于 produce 方法定义的强执行合约,任何不满足该定义的生产者都不能使用。

    3. 如果您想要一个接受Strings 的TestProducer,那么您需要将绑定更改为&lt;N extends String&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-02
      • 1970-01-01
      • 1970-01-01
      • 2017-01-28
      • 2020-11-25
      • 1970-01-01
      相关资源
      最近更新 更多