猿问

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

有一个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?


函数式编程
浏览 188回答 2
2回答

缥缈止盈

对我来说,这看起来像糟糕的代码。我错了吗?不,你没有看错。那里的示例混乱、不清楚,在运行时执行不必要的检查,并且无法在编译时检查任何类型安全性。话虽如此:什么是实现我的目标的优雅/干净的方式,即保持对指针的函数调用,但处理通用列表,同时无法调整 TypeA 或 TypeB 的定义?...你不能。Java 泛型是通过擦除实现的,因此泛型信息在运行时全部丢失(字节码中没有它的概念。)这意味着你不能有两个方法,它们的签名仅在它们的泛型类型上不同,就像 JVM 那样无法在运行时区分它们。尽管您不情愿,但实现您所追求的目标的最简洁、最明显的方法就是放宽您对方法名称必须相同的要求。这几乎没有什么变化,可以为您提供编译时类型安全性和比上面的示例更清晰的代码。您唯一的其他选择是创建一个非泛型子类,它List实现您想要处理的每个泛型类型,并为每种类型使用不同的子类 - 但我真的看不到任何情况更可取。

米脂

你可以这样做: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()。
随时随地看视频慕课网APP

相关分类

Java
我要回答