Java 制作一个变量';s实例类型与另一个实例类型相同,根据接口编程
我正在编写一些处理HTTP响应头的代码(一个填充后的不可变集合),发现自己的代码如下所示:Java 制作一个变量';s实例类型与另一个实例类型相同,根据接口编程,java,reflection,Java,Reflection,我正在编写一些处理HTTP响应头的代码(一个填充后的不可变集合),发现自己的代码如下所示: private Map<String,String> headers; public ctor() { this.headers = new Hashtable<String,String>(); // ... some more ... (actually, this fills this.headers based on ctor parameters) }
private Map<String,String> headers;
public ctor() {
this.headers = new Hashtable<String,String>();
// ... some more ... (actually, this fills this.headers based on ctor parameters)
}
public Map<String,String> getResponseHeaders() {
Map<String,String> temp = new Hashtable<String,String>();
temp.putAll(this.headers);
return temp;
}
私有映射头;
公职人员(){
this.headers=新哈希表();
//…更多…(实际上,这会根据ctor参数填充this.headers)
}
公共地图getResponseHeaders(){
Map temp=新哈希表();
临时putAll(此标题);
返回温度;
}
看到这一点,我突然想到,虽然我现在知道了标题的类型,而且无可否认,所讨论的类足够短(目前总共大约50行,并且不会增长太多),但在这种特殊情况下,这不是一个大问题,如果问题空间稍微复杂一点,那么在getResponseHeaders()中
我可能不知道将this.headers
(使用此特定示例中的名称)实例化为的类型。另外,在我想要返回集合副本的大型类中,跟踪许多不同的实例成员变量及其类型(可能由许多因素决定;列表大小是一个可能的考虑因素)可能会变得非常棘手
两个相关问题:
如果没有一个完整的依赖注入框架,并且禁止全面使用反射(因为性能损失),那么对于一般情况,有没有办法使temp
的实例类型与上述代码中this.headers
的实例类型相同
在任何情况下,这可能会产生很大的影响吗?您可以调用this.headers.clone()
,但需要强制转换结果。此外,这仅适用于类型为可克隆的情况,并且克隆完全符合您的要求(例如,在本例中为浅克隆)
除此之外,没有任何可能性,因为访问this.headers的运行时类型(您称之为实例类型)已经涉及反射。然而,我不会因为有人说反射很慢就不使用反射。并不是所有的反射操作都很慢(例如,我希望调用对象上的getClass()
会非常快),也不是所有执行的操作都会对应用程序的性能产生影响。这取决于更多的因素,例如,执行此操作的频率、优化器的性能等
反射的问题更多的是没有通用的方法来实例化特定的类型。如果类需要构造函数参数,则需要知道要传递给构造函数的对象
因此,考虑一下:您真的需要确保is是完全相同的运行时类型吗?通常情况并非如此。针对接口编程的全部要点是,您通常不应该关心真正的运行时类型,而应该只关心它实现了正确的接口(Map
)。因此,当前形式的getter就可以了,即使this.headers
的运行时类型将来实际上是一个TreeMap
然而,在这个特定的情况下,我会建议一个完全不同的解决方案。我认为在每次调用getResponseHeaders
时创建整个集合的副本是不好的(例如,我想这比反射方法调用要昂贵得多)。相反,您可以将集合的不可修改视图传递给调用者。使用此不可修改的视图,调用方将无法更改您的集合,这通常是您想要确保的。因此,通常不需要复制整个收藏
通过将getter方法更改为
return java.util.Collections.unmodifiableMap(this.headers);
请注意,通过这种方式,如果在调用getResponseHeaders
后更改this.headers
,调用方将看到映射的更改。我建议使用Java集合框架中的类型(在本例中为HashMap
,但也为ArrayList
等),而不是以前的JCF类(Hashtable
,Vector
)。那里的API通常更干净,而且它们都很好地结合在一起。旧的类被改造成新的接口,这就是为什么它们的API不那么好(例如,重复的方法太多)。我想新类的实现也更好。即使只提到unmodifiableMap()
我也会给出+1;我完全没有提到这一点,而且它几乎避免了整个问题,至少在我目前的情况下是这样。我也会考虑HashMap
。