【问题标题】:Technique for extending a class with private constructors使用私有构造函数扩展类的技术
【发布时间】:2013-10-01 02:25:19
【问题描述】:

是否有一种标准技术来“扩展”具有私有构造函数的类,就像大多数 Singleton 类一样?具体来说,我正在尝试扩展 java.lang.management.ThreadInfo 类,因为我将它们中的很多添加到 HashSet 以控制唯一性。但是,我确定两个线程是否相等的方式与equals() 方法的默认实现不同且不完全相同。

在这种情况下,扩展课程显然不是一种选择。

制作类似包装类的东西是否合理,它在构造函数中接受ThreadInfo,然后用值手动填充所有相关字段,然后覆盖equals()hashCode(),或者有更好的方法吗?这样做?

我开始写这样的东西,但更好的实现将是理想的:

class ThreadInfoWrapper {

    private ThreadInfo info;
    ThreadInfoWrapper(ThreadInfo info) {
        this.info = info;
    }

    //Populate instance variables with Thread.State, thread ID, etc.. with
    //Getters/setters and all that other stuff

    public boolean equals(Object o) { //Unique implementation
    }

    public int hashCode() { //Whatever implementation
    }

}

但这感觉像是实现一些基本功能的一种非常迂回的方式。我调查了一下,Java 标准库中不存在带有自定义比较器的 Set 实现。我想我可以编写自己的哈希集实现,但对于一个简单的情况来说工作量太大了。任何见解都会有所帮助。

【问题讨论】:

  • 我很确定这样的类不能扩展。
  • @JakobWeisblat 实际上,它们可以扩展,但只能通过它们的内部类进行扩展,这在这种情况下没有帮助。我知道在我自己的类文件中扩展它们是行不通的。我正在寻找合理的替代方案,特别是看看是否有任何标准做法。找了一会儿也没找到。
  • 你不应该重写 equals() 方法,除非你打算遵守它的合同。
  • @scottb 我的覆盖将履行合同。

标签: java multithreading inheritance hash equals


【解决方案1】:

通过扩展,您的意思是如何创建派生类,这些派生类使用私有构造函数作为它们的超类构造函数。你不能,他们被保密以防止你这样做。由于 JRE 类是由有能力的程序员编写的,因此有充分的理由。因此,即使您可以使用诸如反射或字节码操作之类的技巧来解决它,您也不应该这样做。

但一切都没有丢失。无论如何,您应该更喜欢组合而不是继承。 Decorator 和 Proxy 设计模式可能很有用(您的示例接近这些)。

【讨论】:

    【解决方案2】:

    鉴于没有其他选择,我认为您的做法是合理的。

    另一种方法可能是编写您自己的 HashMap 子类,使用您的“特殊”等于而不是默认值。 (可能已经有 apache 或 guava 实现来做到这一点 - 有人知道吗?)

    (稍后添加)

    因为我很懒,而且因为 ThreadInfo 具有所有 getter,所以公开它是相当“安全”的,我很想使包装类非常简单,既没有 getter 也没有 setter:

    public class ThreadInfoWrapper {
    
    // public so an outsider can get at the wrapped ThreadInfo 
    // could be private if you are sure that will never be necessary
    public final ThreadInfo threadInfo;
    
    public ThreadInfoWrapper(ThreadInfo threadInfo) {
      this.threadInfo = threadInfo;
    }
    
    public boolean equals(Object o) { //Unique implementation
      // refer to threadInfo.blah...
    }
    
    public int hashCode() { //Whatever implementation
      // refer to threadInfo.blah...
    }
    

    }

    但是,这取决于您用于 equals 和 hashcode 的信息。

    【讨论】:

    • 感谢您的回复。当我在搜索时,我发现这个回复 (stackoverflow.com/questions/14880450/…) 声称 Guava 已经“明确拒绝”了具有与 equals() 方法不兼容的相等标准的 Set 的任何实现。
    • 听起来您已经完成了研究。祝你好运。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 2016-10-22
    • 2013-11-15
    相关资源
    最近更新 更多