java - 使一个变量的实例类型与另一个变量的实例类型相同,针对接口(interface)进行编程

标签 java reflection

我正在编写一些代码来处理 HTTP 响应 header (一个一旦填充就不可变的集合),并发现自己的代码如下所示:

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;
}

看到这里,我突然想到,虽然我知道 headers 的类型 now,并且诚然,所讨论的类足够短(目前总共大约 50 行,并且不会增长更多)在这种特殊情况下这不是主要问题,如果问题空间有点复杂,那么在 getResponseHeaders() 中我可能不知道 this.headers(使用这个特定示例中的名称)被实例化为。此外,在一个大类中,我想返回集合的副本,跟踪许多不同的实例成员变量及其类型(可能由许多因素决定;列表大小在我的脑海中可能 考虑)可能会变得非常毛茸茸。

两个相关问题:

如果没有成熟的依赖注入(inject)框架,并且禁止全面使用反射(因为性能损失),有什么办法可以使 temp 的实例类型与像上面的代码中 this.headers 的实例类型,对于一般情况?

有没有什么情况可能会realistically有很大的不同吗?

最佳答案

您可以调用this.headers.clone(),但您需要转换结果。此外,这仅适用于类型可克隆的情况,并且克隆完全符合您的要求(例如,在本例中为浅克隆)。

除此之外,没有任何可能性,因为访问 this.headers 的运行时类型(您所说的实例类型)已经涉及反射。但是,我不会仅仅因为有人说它慢就避免使用反射。并非所有反射操作都很慢(例如,我希望在对象上调用 getClass() 会非常快。),并且并非您执行的所有操作都会对您的应用程序产生性能差异。这取决于更多因素,即此操作执行的频率、优化器的性能等。

反射的问题更多的是没有通用的方法来实例化特定类型。如果一个类需要构造函数参数,您将需要知道将哪些对象传递给构造函数。

因此,考虑一下:您真的需要确保它是完全相同的运行时类型吗?通常情况并非如此。针对接口(interface)编程的全部要点是您通常不应该关心真正的运行时类型,而只关心它实现了正确的接口(interface)(此处为 Map)。因此,即使 this.headers 的运行时类型将来实际上是一个 TreeMap,当前形式的 getter 也可以。

但是,在这种特定情况下,我会建议一个完全不同的解决方案。我认为在每次调用 getResponseHeaders 时创建整个集合的副本是不好的(例如,我猜这比反射方法调用要昂贵得多)。相反,您可以将不可修改的 Collection View 传递给调用者。使用这种不可修改的 View ,调用者将无法更改您的集合,这通常是您要确保的。因此通常不需要复制整个集合。

这可以通过将 getter 方法更改为非常容易地完成

return java.util.Collections.unmodifiableMap(this.headers);

请注意,如果在调用 getResponseHeaders 之后更改 this.headers,调用者将看到 map 的变化。

关于java - 使一个变量的实例类型与另一个变量的实例类型相同,针对接口(interface)进行编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8035416/

相关文章:

java - 为什么 Java 的 Iterator 不是 Iterable?

c# - 使用反射创建类型的实例

.net - 从名称实例化泛型的最佳方法是什么?

python - 使用类的名称实例化类的对象

java - 从文本文档扫描

java - 底部导航菜单点击图标选择

java - Google App Engine - Cloud Console Stackdriver 跟踪详细信息

c# - 使用不带参数的 "params"关键字使用反射调用方法

c# - 类类型的反射(reflect)

java - Eclipse,包消失了?