Java:使用多种方法创建通用方法

时间:2018-03-14 12:53:41

标签: java generics

我遇到了一段代码,其中两个方法具有非常相似的功能,返回相同的类型,但不同。

private Set<String> extractDeviceInfo(List<Device> devices){
        Set<String> sets= new HashSet<>();
        for(Device item:items){
            sets.add(item.getDeviceName());
        }
        return sets;
    }

private Set<String> extractDeviceInfoFromCustomer(List<Customer> customers){
    Set<String> sets= new HashSet<>();
        for (Customer c : customers) {
                sets.add(c.getDeviceName());
            }
        return sets;
}

从上面的代码中可以看出,两种方法都返回相同的Set并检索相同的数据。

我试图尝试从中创建一个通用方法并做了一些研究但是找不到任何可以解决这个问题的方法。 如果我正确理解这一点,使用泛型,我可以在方法中定义泛型参数,然后在调用方法时传递参数和类类型。但是我不知道病房后要做什么。 例如,方法 getDeviceName()如何从泛型类中调用它,因为编译器不知道泛型类是否具有该方法。

如果有人能告诉我这是否可能以及如何达到预期效果,我将非常感激。

由于

更新:创建一个界面,然后实现看起来是一个很好的解决方案,但我觉得它在重构几个方法以避免锅炉板时过度。 我注意到Generic类可以作为参数传递,并且有像 getMethod()等方法。 我想知道是否有可能创建一个通用方法,您传递类和方法名称,然后方法在运行时解析

例如。

private <T> Set<String> genericMethod(Class<T> clazz, String methodName ){
    clazz.resolveMethod(methodName);
}

基本上,我可以在调用方法时执行此操作:

genericMethod(Customer.class,"gedDeviceInfo");

我相信有一种语言可以实现,但不确定你是否可以用Java实现,但几年前我记得读过将字符串解析为java代码,以便在运行时进行编译。 / p>

3 个答案:

答案 0 :(得分:3)

DeviceCustomer都应该实现定义方法getDeviceName的相同接口:

interface Marker {
    String getDeviceName();
}
class Device implements Marker { ... }
class Customer implements Marker { ... }

我将其命名为Marker,但您可以合理地命名。然后,该方法可能如下所示:

private Set<String> extractDeviceInfo(List<? extends Marker> markers) {
    return markers.stream().map(Marker::getDeviceName).collect(Collectors.toSet());
}

它允许下一个类型变体:

extractDeviceInfo(new ArrayList<Device>());
extractDeviceInfo(new ArrayList<Customer>());
extractDeviceInfo(new ArrayList<Marker>());

答案 1 :(得分:1)

99%的时间Andrew answer是解决方案。但是,另一种方法是在参数中定义函数。

这对某些报告很有用,或者如果您需要能够使用相同的方法以多种方式从实例中提取值。

getAt(LocalDate key)

示例:

public static <T, U>  Set<U> extractInfo(List<T> data, Function<T, U> function){
    return data.stream().map(function).collect(Collectors.toSet());
}

答案 2 :(得分:0)

在java中使用反射会受到性能影响。在你的情况下,它可能不值得。

您的原始代码没有任何问题,如果使用它的地方少于3个,请勿重构。如果有超过3个位置并且期待更多,你可以使用@ andrew的方法进行重构。

在我看来,你不应仅仅为了重构而重构代码。