为了账号安全,请及时绑定邮箱和手机立即绑定

Java 泛型:使用一个函数签名处理两种泛型类型的简洁方法

Java 泛型:使用一个函数签名处理两种泛型类型的简洁方法

函数式编程 2023-05-24 15:30:27
有一个Utilities提供公共静态函数的类,用于进行通用数据处理。该类主要用于创建FloatPointer要在本机代码中使用的 s。该类如下所示:class Utilities{    private Utilities(){}    static FloatPointer toPointer( List< TypeA > list )    {        // do some magic        return p    }    static FloatPointer toPointer( List< TypeB > list )    {        // do some different magic        return p    }}这个问题很明显。因为编译器将这些签名解析为FloatPointer toPointer( List list )擦除问题,所以不能这样定义这些函数。现在我问自己,实现这个的最干净的方法是什么。首先,我非常想坚持使用名称toPointer而不是使用不同的函数名称。这是因为在真实的类中有一大堆toPointer处理各种类型的函数。引入一个新名称会破坏计划,因为团队中的其他开发人员已经习惯了toPointer这不是一个好主意。我可以想象有两个函数private static typeAToPointer( List< TypeA > list )and private static typeBToPointer( List< TypeB > list ),但这两个函数需要从公共toPointer函数调用,以免破坏函数名称的方案。遗憾的是我们没有实现TypeAor TypeB,所以我不能让两者实现一个公共接口并接受它——一般来说我不能以任何方式改变TypeAor TypeB。目前我倾向于实现一个函数接受一个List< T >并简单地检查类型,然后处理它。这个例程看起来像这样:static < T > FloatPointer toPointer( List< T > list ){    Class clazz;    if( !list.isEmpty() ) clazz = list.get( 0 ).getClass();    else throw new IllegalArgumentException( "Empty list will result in NP." );    if( clazz == TypeA.class ) return typeAToPointer( list );    else if( clazz == TypeB.class ) return typeBToPointer( list );    else throw new IllegalArgumentException( "List entries of invalid type." );}对我来说,这看起来像糟糕的代码。我错了吗?什么是实现我的目标的优雅/干净的方式,即保持函数调用toPointer,但处理通用列表,同时无法调整TypeAor的定义TypeB?
查看完整描述

2 回答

?
缥缈止盈

TA贡献2041条经验 获得超4个赞

对我来说,这看起来像糟糕的代码。我错了吗?

不,你没有看错。那里的示例混乱、不清楚,在运行时执行不必要的检查,并且无法在编译时检查任何类型安全性。

话虽如此:

什么是实现我的目标的优雅/干净的方式,即保持对指针的函数调用,但处理通用列表,同时无法调整 TypeA 或 TypeB 的定义?

...你不能。

Java 泛型是通过擦除实现的,因此泛型信息在运行时全部丢失(字节码中没有它的概念。)这意味着你不能有两个方法,它们的签名仅在它们的泛型类型上不同,就像 JVM 那样无法在运行时区分它们。

尽管您不情愿,但实现您所追求的目标的最简洁、最明显的方法就是放宽您对方法名称必须相同的要求。这几乎没有什么变化,可以为您提供编译时类型安全性和比上面的示例更清晰的代码。

您唯一的其他选择是创建一个非泛型子类,它List实现您想要处理的每个泛型类型,并为每种类型使用不同的子类 - 但我真的看不到任何情况更可取。


查看完整回答
反对 回复 2023-05-24
?
米脂

TA贡献1836条经验 获得超3个赞

你可以这样做:


static FloatPointer typeAToPointer( List< TypeA > list )

{

    return toPointer( list, objectOfTypeA -> /*parse to FloatPointer*/ );

}


static FloatPointer typeBToPointer( List< TypeB > list )

{

    return toPointer( list, objectOfTypeB -> /*parse to FloatPointer*/ );

}


static < T > FloatPointer toPointer( List< T > list, Function< T, FloatPointer > parser ) {

   //do some common code here

   T object = /* extract object from list*/

   FloatPointer pointer = parser.apply( object );

   //do some other common code on pointer 

   return pointer ;

}

这里有一个 toPointer 模板方法,它使用Function< T, FloatPointer > 解析器将某种类型 T 的对象映射到 FloatPinter。它的映射方式在具体的 toPointer( List< TypeA > list ) 方法中指定。例如,objectOfTypeA -> / parse to FloatPointer / 可能只是 objectOfTypeA -> objectOfTypeA.getFloatPointer()。

查看完整回答
反对 回复 2023-05-24
  • 2 回答
  • 0 关注
  • 187 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信