我一直在想如何委托属性("by -Keyword")如何工作.
我通过契约获得了委托("by"的右侧)必须实现get和setValue(...)方法,但是如何通过编译器确保这一点以及如何在运行时访问这些方法?
我最初的想法是,代表们显然必须实现某种"SuperDelegate" - 接口,但似乎并非如此.
所以剩下的唯一选择(我所知道的)就是使用Reflection来访问那些方法,这些方法可能在语言本身的低层实现.我发现这有些奇怪,因为根据我的理解,这将是相当低效的.此外,Reflection API甚至不是stdlib的一部分,这使得它更加怪异.
我假设后者已经(部分)答案了.所以让我进一步问你以下内容:为什么没有SuperDelegate-Interface声明我们被迫使用的getter和setter方法呢?那不是更干净吗?
以下问题不是必不可少的
所描述的接口甚至已经在ReadOnlyProperty和ReadWriteProperty中定义.然后决定使用哪一个可以依赖于我们是否有val/var.或者甚至省略,因为编译器阻止在val上调用setValue方法,并且只使用ReadWriteProperty-Interface作为SuperDelegate.
可以说,当要求委托实现某个接口时,该构造的灵活性会降低.虽然这可以假设用作代表的类可能没有意识到这样使用,但鉴于对必要方法的具体要求,我认为不太可能.如果你仍然坚持,这里有一个疯狂的想法:为什么不通过扩展使该类实现所需的接口(我知道现在不可能,但是,为什么不呢?可能有一个好的'为什么不',请作为旁注告诉我.
给出以下作为数据类的示例:
class Country {
List<Region> regions = new ArrayList<>();
List<Region> getRegions() {
return regions;
}
}
class Region {
String getName() {
return "some name";
}
}
Run Code Online (Sandbox Code Playgroud)
假设我有一份国家清单
List<Country> countries = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)
我想将这些内容传递给他们的区域及其相应的名称我想做以下事情:
countries.stream().flatMap(Country::getRegions).map(Region::getName)...
Run Code Online (Sandbox Code Playgroud)
但是,该代码无法编译,因为"getRegions"的返回值是Collection(List),而不是flatMap方法接受的Stream.但是因为我知道任何Collection都可以通过其Collection.stream()方法进行流式传输,这应该不是问题.我还是被迫写成如下:
countries.stream().flatMap(c -> c.getRegions().stream()).map(Region::getName)...
Run Code Online (Sandbox Code Playgroud)
这是(给定更丰富的背景)远比前者更不可读.
问题是,有什么理由,我错过了,因为这是那么笨重?我在我们的框架中有很多例子,我不得不采取这种方式,总是让我有一种酸味.(猜猜我只需要将Kotlin添加到我们的项目中并使用flatMap方法扩展Stream类,该方法采用Collection:p或者我?)
以下内容与其说是一个问题,不如说是一个评估请求。
因此,您很可能熟悉以下惰性 getter 模式。
private Object obj;
public Object getObject() {
if(obj==null) {
obj = new Object();
}
return obj;
}
Run Code Online (Sandbox Code Playgroud)
那个代码
所以最近一个同事和我想出了以下界面(简化):
public interface LazyGetterSupport {
default Object get(Supplier<Object> impl) {
String key = impl.getClass().getName();
Object retVal;
if ((retVal = getInstanceCache().get(key)) == null) {
retVal = impl.get();
getInstanceCache().put(key, retVal);
}
return retVal;
}
Map<String, Object> getInstanceCache();
}
Run Code Online (Sandbox Code Playgroud)
旁注:不使用 HashMap#computeIfAbsent bc of Bug-8071667
然后该接口由您要使用惰性获取器的类实现。您需要提供getInstanceCache()如下实现:
private Map<String, Object> instanceCache;
@Override
public Map<String, Object> getInstanceCache() …Run Code Online (Sandbox Code Playgroud) java getter lazy-loading lazy-evaluation lazy-initialization
java ×2
collections ×1
delegates ×1
flatmap ×1
getter ×1
java-8 ×1
java-stream ×1
kotlin ×1
lazy-loading ×1
reflection ×1