2017-06-08 117 views
1

我有這兩種功能,其基本上是相同的:功能的可變參數類型

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); 
+1

你可以創建一個兩個類都實現的'interface',然後使用該接口作爲參數類型嗎? –

+0

'OrderLine'和'Order'是否共享任何常見的超類或接口? – luk2302

+0

@ luk2302不,他們現在沒有任何界面。 – neptune

回答

3

首先,你應該建立這樣的一個接口d您的類應該實現這個接口:

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

如果你給順序表返回一個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; 
    } 

} 
+0

是的,謝謝我意識到錯誤,沒有完成! –

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(); 

你也應該避免在一個可選的通常情況下調用get()。寧可喜歡類似

Order firstOrder = orders.stream().filter(o -> o.getGcsId().equals(gcsId)).findFirst().orElseThrow(() -> new IllegalStateException("no first order with gcsId " + gcsId)); 
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; 
    } 
} 
,你可以採取列表作爲一個參數後測試的執行 實例
0
  • 的一種方式,但你的列表是參數。 如果您有任何參數化,

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

泛型信息將在運行時被刪除。相反,這是JVM將看到

`List fooList = new ArrayList();` 
  • 這被稱爲類型擦除。 JVM在運行時沒有List的參數化類型信息(在本例中)。

    由於JVM有沒有在運行時的參數化類型的信息,

    有沒有辦法,你可以做的ArrayList的一個instanceof。

所以你最好保持你的兩個功能的工作。