【问题标题】:Java generics with Function.apply带有 Function.apply 的 Java 泛型
【发布时间】:2017-12-11 09:53:04
【问题描述】:

我正在玩 Java 实用程序函数。我有以下代码:

public class Checker<T>{

  private T value;
  private Function<T, T> callback;

  private Checker(T value) {
    this.value = value;
  }

  public static Checker when(String o) {
    return new Checker<String>(o);
  }

  public static Checker when(int o) {
    return new Checker<Integer>(o);
  }

  public Checker then(Function<T, T> callback) {
    this.callback = callback;
    return this;
  }

  public void execute() {
    if (this.value instanceof String) {
      this.callback.apply("123");
    }
    if (this.value instanceof Integer) {
      this.callback.apply(123);
    }
  }

  Checker.when("123").then(str -> {
    return "";
  }).execute();

  Checker.when(123).then(str -> {
    return "";
  }).execute();

现在我收到this.callback.apply("123") 的错误,因为它需要T 并且不能将其转换为String

Function&lt;T,T&gt; 是否可以有通用返回类型?我可以发送T,但随后它在我的 lambda 中以Object 的形式接收,但我想要StringInteger

【问题讨论】:

  • 为什么你需要做这个instanceof链,而不是简单的this.callback.apply(value)?为什么要专门传入123?为什么不直接将value 设为123 的兼容实例?
  • 请修正你的缩进。

标签: java function lambda java-8


【解决方案1】:

我对您的 Checker 课程进行了一些更改,这对我来说很有意义。我消除了所有原始类型,并在execute 中使用了value 成员。我添加了execute 的返回类型,以便能够打印其结果。

class Checker<T>{

  private T value;
  private Function<T, T> callback;

  private Checker(T value) {
    this.value = value;
  }

  public static Checker<String> when(String o) {
    return new Checker<>(o);
  }

  public static Checker<Integer> when(int o) {
    return new Checker<>(o);
  }

  public Checker<T> then(Function<T, T> callback) {
    this.callback = callback;
    return this;
  }

  public T execute() {
    return this.callback.apply(value);
  }

  public static void main (String[] args) {
    Checker.when("123").then(str -> {
      return "." + str + ".";
    }).execute();

    Checker.when(123).then(i -> {
      return i + 100;
    }).execute();
  }
}

现在当你检查你的班级时:

System.out.println (Checker.when("123").then(str -> "." + str + ".").execute());
System.out.println (Checker.when(123).then(i -> i + 100).execute());

你得到:

.123.
223

【讨论】:

  • 您可以将Function&lt;T,T&gt; 替换为UnaryOperator&lt;T&gt; 并通过return new Checker&lt;&gt;(o) 推断类型
  • 你也可以用str -&gt; "." + str + "."替换str -&gt; {return "." + str + ".";}
  • then 被多次调用时,除了最后一个函数之外的所有函数都会丢失。如果从未调用过then,您将获得NullPointerException。最好用Function.identity()初始化callback,用this.callback = this.callback.andThen(callback);实现then……
  • @Eugene:但在这里使用UnaryOperator 没有任何优势。它只会在代码中添加restrictions。换个方向会更有用:public &lt;R&gt; Checker&lt;R&gt; then(Function&lt;? super T, ? extends R&gt; callback) { … }
  • @Holger 同意,我不知道 OP 为什么选择Function&lt;T,T&gt;,我只是尊重他的选择
【解决方案2】:

此代码可以进一步简化,如下所示:

static class Checker<T> {

    private final T value;

    private UnaryOperator<T> callback;

    private Checker(T value) {
        this.value = value;
    }

    public static <T> Checker<T> when(T o) {
        return new Checker<>(o);
    }

    public Checker<T> then(UnaryOperator<T> callback) {
        this.callback = callback;
        return this;
    }

    public T execute() {
        return this.callback.apply(value);
    }
}

【讨论】:

    【解决方案3】:

    正如其他人所建议的那样,代码可以被简化,但为什么不让调用链式化并且类最终化,这样你就有了一个简单而干净的模型:

    final class Checker<T> {
    
        private final T value;
    
        private final UnaryOperator<T> callback;
    
        private Checker(T value, UnaryOperator<T> callback) {
            this.value = value;
            this.callback = callback;
        }
    
        public static <T> Checker<T> when(T t) {
            return new Checker<>(t, UnaryOperator.identity());
        }
    
        public Checker<T> then(UnaryOperator<T> callback) {
            return new Checker<>(value, t -> callback.apply(this.callback.apply(t)));
        }
    
        public T execute() {
            return callback.apply(value);
        }
    }
    

    这种方法不是在then() 中返回this,而是返回一个全新的检查器实例

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-14
      • 2021-08-01
      • 1970-01-01
      • 2017-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多