[英]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);
}
});
你有兩個基本問題:
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.