【问题标题】:Function with generic type as member variable泛型类型作为成员变量的函数
【发布时间】:2020-09-16 19:04:23
【问题描述】:

我有一个将class 对象映射到此类的实例的函数。 基本上:

 Function<Class<T>, T> fun;

我可以在一个方法中定义这个函数,但是当试图把它放在一个成员变量中时,编译器会报错,因为类型 T 是未知的。

因此,T 并不特定于封闭对象。它可能因调用而异。在类级别定义这样一个函数的正确语法是什么?

编辑

我想澄清一下。我有课A

public class A {
  public <T> T get(Class<T> clazz) {...}
}

现在,我想将指向该函数的指针传递给 B 类,如下所示:

public class B {
  <T> Function<Class<T>, T> fun;
  
  public <T> T get(Class<T> clazz) {
    return fun.apply(clazz);
  }
}

但是,&lt;T&gt; Function&lt;Class&lt;T&gt;, T&gt; fun 的语法不正确。有没有办法保留信息,那个乐趣会一直保留T这个类型?

我目前的解决方案是

public class B {
  Function<Class<?>, ?> fun;

  public <T> void setFun(Function<Class<T>, T> fun) {
    this.fun = fun;
  }

  public <T> T get(Class<T> clazz) {
    return (T) fun.apply(clazz);
  }
}

这可行(并且通过不变量显然是正确的)但由于需要强制转换而有点丑陋。

【问题讨论】:

    标签: java generics


    【解决方案1】:

    在 Java(和 JVM)中,值不是多态的,方法是。

    正确的是用方法来定义

    <T> Function<Class<T>, T> fun();
    

    Polymorphic values in Java


    关于编辑

    现在,我想将指向该函数的指针传递给 B 类,如下所示:

    public class B {
      <T> Function<Class<T>, T> fun;
     
      public <T> T get(Class<T> clazz) {
        return fun.apply(clazz);
      }
    }
    

    再一次,一个值(包括一个字段)不能是多态的,方法可以。

    • 所以你可以让fun 成为一个方法

       public abstract class B {
          abstract <T> Function<Class<T>, T> fun();
      
          public <T> T get(Class<T> clazz) {
              return this.<T>fun().apply(clazz);
          }
       }
      

      你不能写像setFun 这样的setter。它的签名应该类似于

       public void setFun(<T> Function<Class<T>, T> fun); // pseudocode
      

      而不是

       public <T> void setFun(Function<Class<T>, T> fun);
      

      &lt;T&gt; Function&lt;Class&lt;T&gt;, T&gt;被称为rank-N类型,在Java中是没有的

      What is the purpose of Rank2Types?

      https://wiki.haskell.org/Rank-N_types

    • 或者,您可以使用类(接口)包装多态 fun

      public interface PolyFunction {
          <T> T apply(Class<T> clazz);
      }
      
      public class B {
          PolyFunction fun;
      
          public void setFun(PolyFunction fun) {
              this.fun = fun;
          }
      
          public <T> T get(Class<T> clazz) {
              return fun.apply(clazz);
          }
      }
      

      PolyFunction 看起来像你的 A 所以也许你想要

      public class B {
          A a;
      
          public void setA(A a) {
              this.a = a;
          }
      
          public <T> T get(Class<T> clazz) {
              return a.get(clazz);
          }
      }
      

    【讨论】:

    • 唯一可以返回的值是null,因为Test&lt;?&gt; t = new Test&lt;&gt;(); Function&lt;Class&lt;String&gt;, String&gt; strFn = t.fun(); Function&lt;Class&lt;Integer&gt;, Integer&gt; intFn = t.fun();都是合法的。
    • @AndyTurner 这是一个函数,所以我猜你错了(null 是唯一的选择)。例如&lt;T&gt; Function&lt;Class&lt;T&gt;, T&gt; fun() { return (Class&lt;T&gt; cls) -&gt; { T t = null; try { t = cls.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } return t; }; }.
    • 我想我是,那么!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-22
    • 2020-09-29
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多