1

我可以在构造函数中定义静态属性而不是声明时将其设为最终属性吗?

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

4

3 回答 3

3

但是有可能制作一些标准类的不可变对象吗?

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

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

于 2012-05-01T15:54:21.000 回答
2

静态初始化

我可以在构造函数中定义静态属性而不是声明时将其设为最终属性吗?

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

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

或者

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

动态代理

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

您可以使用动态代理来拥有所有变异方法,例如抛出一个而不是它们实际执行的任何方法。setXXX()UnsupportedOperationException我认为这种方法是半骇人听闻的,但他们把它放到 Java 中来处理这种情况,所以它就是为这些类型的问题而设计的。

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

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

撞击金属

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

于 2012-05-01T16:03:33.513 回答
1

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

class Test{

    public static final int x;
    public final int y;

    public Test(){
        y = 16;
    }    

    static{
        x = 42;
    }

}

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

于 2012-05-01T15:59:58.990 回答