具有可变参数类型

时间:2017-06-08 06:33:46

标签: java generics

我有两个基本相同的功能:

private Order getOrder( List<Order> orders, String gcsId )
{
    Predicate<Order> predicate = c -> c.getGcsId().equals( gcsId );
    Order obj = orders.stream().filter( predicate ).findFirst().get();
    return obj;
}

private OrderLine getOrderLine( List<OrderLine> orderLines, String gcsId )
{
    Predicate<OrderLine> predicate = c -> c.getGcsId().equals( gcsId );
    OrderLine obj = orderLines.stream().filter( predicate ).findFirst().get();
    return obj;
}

唯一的区别是第一个参数的类型。如何使用第一个具有变量类型的参数创建单个函数?

编辑:这就是我在同一个类的另一个方法中调用这些函数的方法:

Order order = getOrder( orders, orderId );
OrderLine orderLine = getOrderLine( order.getOrderLines(), orderLineId );

5 个答案:

答案 0 :(得分:3)

首先你应该创建一个这样的接口,你的类应该实现这个接口:

public interface IOrder {

   String getGcsId();
}

public class Order implements IOrder {
  // Content of your class
}

public class OrderLine implements IOrder {
  // Content of your class
}

之后你可以使用泛型编写你的方法:

private <T extends IOrder> T getOrder( List<T> orders, String gcsId )
{
    Predicate<T> predicate = c -> c.getGcsId().equals( gcsId );
    T obj = orders.stream().filter( predicate ).findFirst().get();
    return obj;
}

答案 1 :(得分:2)

要么让它们实现一个公共接口,它定义了getGcsId()方法,并使用

private <T extends CommonInterface> T getFirstWithGcsId(List<T> orders, String gcsId) {
    Predicate<T> predicate = c -> c.getGcsId().equals(gcsId);
    T obj = orders.stream().filter(predicate).findFirst().get();
    return obj;
}

或者更改方法的签名以向其传递一个知道如何提取gcsId的函数:

private <T> T getFirstWithGcsId(List<T> orders, String gcsId, Function<T, String> gcsIdExtractor) {
    Predicate<T> predicate = c -> gcsIdExtractor.apply(c).equals(gcsId);
    T obj = orders.stream().filter(predicate).findFirst().get();
    return obj;
}

但是这种方法非常简单,坦率地说,如果你没有任何通用接口,我只想内联它。它基本上是一行代码:

Order firstOrder = orders.stream().filter(o -> o.getGcsId().equals(gcsId)).findFirst().get();

你也应该避免在一般的Optional上调用get()。更喜欢像

这样的东西
Order firstOrder = orders.stream().filter(o -> o.getGcsId().equals(gcsId)).findFirst().orElseThrow(() -> new IllegalStateException("no first order with gcsId " + gcsId));

答案 2 :(得分:1)

如果您提供订单列表,则返回一个Ornder,如果您给定义一个通用方法:

private <T extends Foo> T getOrder(List<T > orders, String gcsId) {
    Predicate<T> predicate = c -> c.getGcsId().equals(gcsId);
    T obj = orders.stream().filter(predicate).findFirst().get();
    return obj;
}

Foo接口在哪里

interface Foo {
    String getGcsId();
}

class OrderLine implements Foo {

    @Override
    public String getGcsId() {
        return something;
    }

}

class Order implements Foo {

    @Override
    public String getGcsId() {
        return something;
    }

}

答案 3 :(得分:1)

您应该创建一个Interface。见下文:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class SomeFunctionsRefactored {

    public static void main(String[] args) {
        Order simpleOrder = new SimpleOrder();
        Order lineOrder = new LineOrder();
        String gcsId;
        List<Order> simpleOrders = new ArrayList(Arrays.asList(simpleOrder));
        List<Order> lineOrders = new ArrayList(Arrays.asList(lineOrder));

        Order order = getOrder(simpleOrders, "Hi I'm a simple order");
        System.out.println(order.getGcsId());  // Hi I'm a simple order

        order = getOrder(lineOrders, "Hi I'm a line order");
        System.out.println(order.getGcsId());  // Hi I'm a line order

    }

    private static Order getOrder(List<Order> orders, String gcsId) {
        Predicate<Order> predicate = c -> c.getGcsId().equals(gcsId);
        return orders.stream().filter(predicate).findFirst().get();
    }

界面:

interface Order {
    public String getGcsId();
}

class SimpleOrder implements Order {
    String gcsId = "Hi I'm a simple order";

    public String getGcsId() {
        return gcsId;
    }

}

class LineOrder implements Order {
    String gcsId = "Hi I'm a line order";

    public String getGcsId() {
        return gcsId;
    }
}

答案 4 :(得分:0)

  • 将列表作为参数后,您可以执行 实例测试的一种方法,但您的列表已参数化。 如果你有任何参数化的东西,

    List<Foo> fooList = new ArrayList<Foo>();

Generics信息将在运行时被删除。相反,这就是JVM将看到的内容

   `List fooList = new ArrayList();`
  • 这称为类型擦除。 在运行时,JVM没有List的参数化类型信息(在示例中)。

    由于JVM在运行时没有参数化类型的信息,

    您无法使用ArrayList的实例

这样你可以更好地保持两种功能。