【问题标题】:What are the use cases of generic non-static methods?泛型非静态方法的用例是什么?
【发布时间】:2020-04-11 08:52:57
【问题描述】:

在没有类本身泛型的情况下拥有非静态方法泛型的有效用例是什么?

例子:

public class A {
    <T> T someMethod(T param) {
        //use case?
    }
}

如上图,类没有参数化,但方法有。什么时候可以使用这种结构?

请注意,上面的代码只是一个例子。我对所有返回类型或参数都很好。我只对通用非静态方法的有效用例感兴趣。

【问题讨论】:

  • 您确定它返回void 并且不接受任何参数吗?如果是这样,那对我来说也没有意义。
  • 如果没有任何参数或返回类型,很难想象这样的方法能做什么。通常,您会将方法设为泛型,以便它可以接受某种泛型类型。
  • 这个问题是理论上的,我们把void换成任何其他类型并添加任何参数。
  • 一个人为的用例:你想将两个列表合并在一起,所以两个List&lt;T&gt;。但是您不想创建此实用程序static,因为您可能想记录一些内容或将一些结果写入不在静态上下文中的数据库。

标签: java generics


【解决方案1】:

一个用例是推断编译时类型,但这需要您的方法具有实际的返回类型,而不仅仅是void

这是来自GSON的示例

public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
    if (json == null) {
      return null;
    }
    return (T) fromJson(new JsonTreeReader(json), typeOfT);
  }

【讨论】:

    【解决方案2】:

    泛型非静态方法的用例有哪些(如果类本身 不是通用的)?

    类型安全的异构容器模式说明了此方法签名的一个重要用途。这种模式在容器可以表示多种类型(不仅仅是一种类型,如List&lt;E&gt; 的情况)的情况下很有用。在这种模式中,值的键是通用的,而不是容器。

    这是类型安全的异构容器的 API,取自 Essential Java,第 2 版。 J.布洛赫:

    // Typesafe heterogeneous container pattern - API
    public class Favorites {
       public <T> void putFavorite(Class<T> type, T instance);
       public <T> T getFavorite(Class<T> type);
    }
    

    此容器将通用键映射到其类型由其对应键表示的值。这种模式利用了 Java Class 类在 Java 5 中成为泛型这一事实。泛型 Class&lt;T&gt; 对象用作提供编译时和运行时类型的运行时类型标记对应值的信息。

    要在地图中存储“最喜欢的”StringInteger 对象,客户端会这样写:

    myFavs = new Favorites();
    myFavs.putFavorite(String.class, "My Favorite String");
    myFavs.putFavorite(Integer.class, Integer.valueOf(12345));
    

    注意类文字如何用作运行时类型标记,然后当从映射中检索到每个值时,可以使用这些标记将正确的类型恢复为:

    String myFavString = myFavs.getFavorite(String.class);
    int myFavInt       = myFavs.getFavorite(Integer.class);
    

    类型安全的异构容器模式可扩展到其他类型的数据结构(例如,数据库中的一行,其中每一列可能有不同的类型),允许设计人员实现具有任意数量的数据结构以类型安全的方式使用不相关的类型。

    这是因为实例方法可以被通用化。

    【讨论】:

      【解决方案3】:
      public class A {
          <T> T someMethod(T param) {
              //use case?
          }
      }
      

      如果类本身不是通用的,那么您将创建A 的对象为A a = new A();,但如果有要求A 中的someMethod 应该具有通用参数,在这种情况下您将使用泛型。

      此类的示例可以是,我有Calc 类,它作为add 方法。

      class Calc {
      
          <T> T add(<T extends Number> param1, <T extends Number> param2) {
             return param1 + param2;
          }
      
      }
      
      

      这里上面的方法只能接受扩展Number类的参数,它会返回你作为参数提供的类型。因此代码会更安全。

      Calc c = new Calc();
      int a = 1;
      int b = 2;
      calc.add(1, 2) // returns int 3
      

      【讨论】:

      • 请注意,此方法可以设为静态。另请注意,您不能在Object 上使用+,即使它扩展了Number。最后,T 的绑定要求属于声明,而不是数字本身。所以&lt;T extends Number&gt; 然后只是T param1, T param2
      • @Zabuza 我只是用非常基本的例子来解释它。
      • 当然。但也许你想花时间改进提到的项目。然后你可能会得到更多的支持:)
      • 我会考虑到这一点,明天会更新答案。我会在这里更新,这样你就可以接受它。谢谢顺便说一句。 :)
      猜你喜欢
      • 1970-01-01
      • 2011-12-20
      • 2014-04-17
      • 2014-01-06
      • 2021-06-28
      • 2011-07-14
      • 1970-01-01
      • 2013-11-22
      • 1970-01-01
      相关资源
      最近更新 更多