lambdas 中隐含的匿名类型
在这个问题中,用户@Holger提供了一个答案,显示了匿名类的不常见用法,我不知道。
这个答案使用流,但这个问题不是关于流的,因为这种匿名类型构造可以在其他上下文中使用,即:
String s = "Digging into Java's intricacies";
Optional.of(new Object() { String field = s; })
.map(anonymous -> anonymous.field) // anonymous implied type
.ifPresent(System.out::println);
令我惊讶的是,这会编译并打印预期的输出。
注意:我很清楚,自古以来,就可以构造一个匿名的内部类并按如下方式使用其成员:
int result = new Object() { int incr(int i) {return i + 1; } }.incr(3);
System.out.println(result); // 4
但是,这不是我在这里要问的。我的情况有所不同,因为匿名类型是通过方法链传播的。Optional
现在,我可以想象这个功能的一个非常有用的用法...很多时候,我需要通过管道发出一些操作,同时还要保留原始元素,即假设我有一个人名单:map
Stream
public class Person {
Long id;
String name, lastName;
// getters, setters, hashCode, equals...
}
List<Person> people = ...;
而且我需要将我的实例的JSON表示形式存储在某个存储库中,为此我需要每个实例的JSON字符串以及每个ID:Person
Person
Person
public static String toJson(Object obj) {
String json = ...; // serialize obj with some JSON lib
return json;
}
people.stream()
.map(person -> toJson(person))
.forEach(json -> repository.add(ID, json)); // where's the ID?
在此示例中,我丢失了该字段,因为我已将每个人转换为其相应的 json 字符串。Person.id
为了规避这一点,我看到很多人使用某种类,或者,甚至,或者只是:Holder
Pair
Tuple
AbstractMap.SimpleEntry
people.stream()
.map(p -> new Pair<Long, String>(p.getId(), toJson(p)))
.forEach(pair -> repository.add(pair.getLeft(), pair.getRight()));
虽然这对于这个简单的示例来说已经足够好了,但它仍然需要一个泛型类的存在。如果我们需要通过流传播3个值,我认为我们可以使用一个类,等等。使用数组也是一种选择,但它不是类型安全的,除非所有值都属于同一类型。Pair
Tuple3
因此,使用隐含的匿名类型,上面的相同代码可以重写如下:
people.stream()
.map(p -> new Object() { Long id = p.getId(); String json = toJson(p); })
.forEach(it -> repository.add(it.id, it.json));
这是神奇的!现在,我们可以根据需要拥有任意数量的字段,同时还可以保持类型安全性。
在测试此内容时,我无法在单独的代码行中使用隐含类型。如果我修改原始代码,如下所示:
String s = "Digging into Java's intricacies";
Optional<Object> optional = Optional.of(new Object() { String field = s; });
optional.map(anonymous -> anonymous.field)
.ifPresent(System.out::println);
我收到编译错误:
Error: java: cannot find symbol
symbol: variable field
location: variable anonymous of type java.lang.Object
这是可以预料到的,因为类中没有命名的成员。field
Object
所以我想知道:
- 这是否在某个地方被记录下来,还是在JLS中有什么关于此的内容?
- 如果有的话,这有什么限制?
- 编写这样的代码真的安全吗?
- 是否有速记语法,或者这是我们能做的最好的语法?