有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使一个变量的实例类型与另一个变量的实例类型相同,针对接口编程

我正在编写一些处理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)
}

public Map<String,String> getResponseHeaders() {
    Map<String,String> temp = new Hashtable<String,String>();
    temp.putAll(this.headers);
    return temp;
}

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

两个相关问题:

如果没有一个完整的依赖注入框架,并且禁止全面使用反射(因为性能的损失),对于一般情况,有没有办法使temp的实例类型与上述代码中的this.headers的实例类型相同

在任何情况下,这可能会产生很大的影响吗


共 (1) 个答案

  1. # 1 楼答案

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

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

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

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

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

    通过将getter方法更改为

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

    注意,通过这种方式,如果在调用getResponseHeaders之后更改this.headers,调用方将看到映射的更改