簡體   English   中英

Java stream 中的 Lambda 表達式如何使用反射?

[英]How can I use reflection in the Lambda expression in Java stream?

我想讓它成為使用 java stream 過濾列表的常用功能。
但它並沒有按照我想要的方式工作......

下面的代碼不起作用,但是否可以在 lambda 表達式中使用反射進行過濾?

 List filterList = commonList.stream()
                .filter(x -> x.getClass().getDeclaredField("metadata").get(this)
                .getClass().getDeclaredField("name").get(this).matches(keywords))
                .collect(Collectors.toList());

這個表達式:

x.getClass().getDeclaredField("metadata").get(this)
.getClass().getDeclaredField("name").get(this)

返回Object Object class 中沒有聲明matches方法。想象一下將您的 lambda 重寫為:

filter(x -> {
    Object y = x.getClass().getDeclaredField("metadata").get(this)
.getClass().getDeclaredField("name").get(this);
    return y.matches(keywords);
});

因此編譯錯誤。

另外, getDeclaredField方法可以拋出檢查異常,所以它應該在 lambda 代碼中處理:

filter(x -> {
    try {
        return x.getClass().getDeclaredField("metadata").get(this)
            .getClass().getDeclaredField("name").get(this).matches(keywords);
    } catch (NoSuchFieldException e) {
        //handle it here or re throw
        throw new RuntimeException("Error filtering the stream", e);
    }
});

你有兩個基本問題:

  1. Lambda 可能不會拋出已檢查的異常,而反射方法會拋出它們
  2. 反射方法沒有類型; 他們的返回類型為Object

但是,您可以通過使用捕獲並作為 RuntimeException 重新拋出的類型化方法來解決這兩個問題:

<T> getField(String fieldName, Object obj) {
    try {
        return (T)obj.getClass().getDeclaredField(fieldName).get(obj);
    } catch (ReflectiveOperationException e) {
        throw new RuntimeException(e);
    }
}

然后使用類型化調用告訴編譯器name是一個String ,如下所示:

List filterList = commonList.stream()
    .filter(x -> this.<String>getField("name", getField("metadata", x)).matches(keywords))
    .collect(Collectors.toList());

編寫該方法的簡單方法是使用 Lombok:

@SneakyThrows
<T> getField(String fieldName, Object obj) {
    return (T)obj.getClass().getDeclaredField(fieldName).get(obj);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM