声明后使静态属性不可变



当静态属性在构造函数中定义而不是在声明中定义时,我可以使静态属性最终确定吗?

我知道如何创建创建不可变实例的自定义类。但是是否有可能使某个标准类的不可变对象?例如对象,JPanel,日历或其他任何东西?

但是是否有可能使某个标准类的不可变对象?

不。Java中没有任何内容可以支持这一点。您所能做的就是限制引用的广泛发布范围,并确保任何有权访问它的代码都不会改变它。当然,您可以创建自己的包装器类型,该类型仅公开只读操作,并自由公开该类型。

编辑:如评论中所述,JDK中对此有一些支持,用于集合 - Guava为它们提供了更彻底的不可变集合和构建器。但是,没有什么通用的用途可以获取任何可变类型的对象并返回它的不可变视图。

静态初始化

当静态属性

在构造函数中定义时,我可以使静态属性最终确定吗? 不是在声明上?

只有在声明属性时或在static { }块中,才能分配static final属性。当构造函数被调用时为时已晚,引用已经分配给null因为首先计算所有static代码。

private static final String s = "Hello World!";

private static final String s;
static { s = "Hello World!"; }

动态代理

我知道如何创建创建不可变的自定义类 实例。但是是否有可能使某些对象的不可变 标准类?例如对象,JPanel,日历或其他任何东西?

您可以使用动态代理让所有变异方法,例如抛出UnsupportedOperationException而不是它们实际执行的操作setXXX()。我认为这种方法是半黑客式的,但是他们将其放入Java中以应对这种情况,因此它只是针对这些类型的问题而设计的。

根据所涉及的接口和命名约定,它可能与自己手动创建包装器一样多。

所以在 Java 中绝对是可能的,这里有一个在List上禁用 .add() 方法的示例,这是使类不可变的开始。

撞击金属

你可以用CGLib做同样的事情,甚至更多,但是没有真正易于使用的文档或示例,所以我在这里只提到完整性;这将是修改final类行为的唯一方法。JMock 这样做是为了提供final类的模拟实现。这是深奥的魔法,但如果你真的需要这样做,这是可能的。

对于问题的第一部分,如果我没看错的话:

class Test{
    public static final int x;
    public final int y;
    public Test(){
        y = 16;
    }    
    static{
        x = 42;
    }
}

基本上,static final字段也可以在静态初始值设定项块中初始化,final字段可以在构造函数中初始化。

最新更新