如何在没有编译器警告的情况下将任意数量的参数化函数传递给构造函数

How to pass an Arbitrary number of Parameterized Functions into constructor without compiler Warnings

我有一个Testclass和一个Writerclass.

Writer class 除了将字符串写入 StringBuilder 之外什么都不做,仅此而已。它也被允许有“变形金刚”。这意味着,在 Writer class 的构造函数中,您可以传递任意数量的 lambda 函数 以向您正在编写的字符串添加额外的处理。

比如点赞String::toLowerCase.

我希望能够将多个 “变形金刚” 传递给作者的构造函数。

我有以下代码:

///Writer Class   Writer(Function<String, String>... someFunctions) {
abstract class Writer {
  Function<String, String>[] functions;

  Writer(Function<String, String>... someFunctions) {
    functions = someFunctions;
  }

}

///Test Class
    @Test
    default void WriterTestWriteThere() throws IOException {
        Writer writer = createWriter();
        writer.write("There");
        writer.close();

        assertEquals("There", getContents());
    }

    @Test
    default void WriterTestTwoTransformerFunctions() throws IOException {
        Writer writer = createWriter(
                text -> text.replaceAll("sometext", "s*****"),
                String::toUpperCase
        );
        writer.write("This is somethext!");
        writer.close();

        assertEquals("THIS IS S*****!", getContents());
    }

但是,编译器发出多个警告

Possible heap pollution from parameterized vararg type - Writer class.

构造函数的错误消息

Unchecked generics array creation for varargs parameter - 创建 Writer 实例时 Test class 的错误消息。

我不能使用@SafeVarargs 或@SuppressWarnings

我在网上到处都看过,但无法得到关于为什么会产生这些警告的确切答案,除此之外 Java 编译器不喜欢将参数化参数传递到列表中。所以,提出我的问题。

我可以用什么来修复它?

我需要能够将多个函数传递给编写器 class 以按照这些函数的需要转换文本,并且没有警告。除了 Function,我还尝试了其他 Java 实用程序 classes,但我似乎找不到我需要的东西。

I cannot use @SafeVarargs or @SuppressWarnings

你可能知道,arraysgenerics 不能一起玩。

数组是协变的,即方法指定 Number[] - 您可以作为参数传递 Integer[]Double[]BigInteger[]

泛型是不变的,即如果声明的参数是 List<Number> - 你只能传递 List<Number>.

当您将参数传递给需要 varargs 的方法时,它们将被数组包裹。因此,编译器无法确定 type-safety 当您混合使用可变参数和泛型时,它会警告您可能存在堆污染,因为无法验证参数类型是否匹配。

您必须消除创建通用数组的需要。

最好的选择是在传递给 Writer.

的构造函数之前将所有函数组合成一个函数
Function<String, String> f1 = String::toUpperCase;
Function<String, String> f2 = text -> text.replaceAll("somethext", "s*****");
Function<String, String> f3 = text -> text.replaceAll("\p{Punct}", "&");

Function<String, String> combined = f1.andThen(f2).andThen(f3);

并且 Writer 应该有一个 Function<String, String> 类型的字段,但不是函数数组。

public class Writer {
    private Function<String, String> function;

    public Writer(Function<String, String> function) {
        this.function = function;
    }
}