在java中扩展不可实例化的类

时间:2010-01-09 12:55:19

标签: java

我读了Joshua Bloch的“Effective Java”,并从我们的应用程序中删除了“Constant Interface anti-pattern”。诀窍是使用非实例化的util类,其构造函数是私有的,并将所有常量定义为'public static final'

我必须扩展这个常量util类。我只能在将构造函数更改为protected时才能执行此操作。

有人可以提出更好的方法。

public class Constants {
    private Constants () {} // Prevent instantiation
    public static final String MyString = "MyString";
}

public class MyConstants extends Constants {
    private MyConstants () {} // Compiler error : Implicit super constructor Constants() is not visible.
    public static final String MySecondString = "MySecondString";
}

6 个答案:

答案 0 :(得分:7)

通常不应该扩展这些常量类。你能否为我们提供一个更具体的例子来说明你想做什么?

通常,您希望在相关时将常量组合在一起,例如,数学常量或特定功能组件的配置参数名称。

如果常量确实相关,那么你是否可以将它们添加到原始类中?或者,您是否有任何理由不能为常量创建单独的类?

答案 1 :(得分:3)

我通常会做以下事情:

public abstract class Constants {
    // ...constants...
    public Constants () {
        throw new UnsupportedOperationException();  // prevent instantiation
    }
}

这样可以扩展类以创建派生的实用程序类,但任何(错误的)实例化它的尝试都将失败。我希望以这种方式定义java.util.Collections,因此不必为其他实用程序方法定义Collections2(或类似)。

顺便提一下,给定一个抽象类,“受保护”和“公共”对于构造函数实际上是相同的。仅仅使构造函数受到保护几乎没有任何好处,因为尽管有“保护”,任何人仍然可以轻松地创建类的实例:

public class Base {
    protected Base() { }
}

// Somewhere else:
Base b = new Base() { };  // anonymous subclass

答案 2 :(得分:2)

我认为将构造函数更改为protected没有任何问题。

我也没有看到使用接口来保持常量有什么问题。

答案 3 :(得分:1)

使用protected关键字时是否有问题?对我来说,这似乎是一个务实的解决方案。

我必须说(另外)我使用接口来保持常量没有特别的问题。使用static import使其在您的客户端类中可用。不过,我不会主张实施它。

答案 4 :(得分:1)

如果这些类在同一个包中,并且您想禁止非包类的继承,请考虑使用默认访问:

public class Constants {
    Constants () {} // Prevent instantiation
    public static final String MyString = "MyString";
}

答案 5 :(得分:0)

我使用Joshua Bloch推荐的方法。

public class Constants {

    private Constants() {
        throw new AssertionError();
    }

    public static class Math {

        private Math() {
            throw new AssertionError();
        }

        public static final int COUNT = 12;
    }

    public static class Strings {

        private Strings() {
            throw new AssertionError();
        }

        public static final String LOREM = "Lorem";
    }

}

Constants类和嵌套类

  • 无法延期
  • 无法实例化

如果我需要按类型对常量进行分组,我只会使用嵌套类。请记住,每个嵌套类必须抛出AssertionError