Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从javabean创建不可变对象_Java_Immutability_Javabeans - Fatal编程技术网

从javabean创建不可变对象

从javabean创建不可变对象,java,immutability,javabeans,Java,Immutability,Javabeans,我参与了这个项目,在这个项目中,我们是在很好的遗留代码的基础上构建的。我有一个关于一个大JavaBean对象的特殊情况,它必须通过有线传输。因此,我的第一个想法是使其不可变并可序列化,以实现这一点。在这一点上,我面临着一些困难的选择:- 理想情况下,我想有办法 自动生成一个不可变的, 此类的可序列化版本。 我没有重构或修改的余地 以任何方式改变这个类,我 我真的很不愿意 复制并粘贴带有 不同的名字 假设我放弃了1,即i 实际上选择了复制的代码 巨大的javabean类,我仍然 将处于不利的境地

我参与了这个项目,在这个项目中,我们是在很好的遗留代码的基础上构建的。我有一个关于一个大JavaBean对象的特殊情况,它必须通过有线传输。因此,我的第一个想法是使其不可变并可序列化,以实现这一点。在这一点上,我面临着一些困难的选择:-

  • 理想情况下,我想有办法 自动生成一个不可变的, 此类的可序列化版本。 我没有重构或修改的余地 以任何方式改变这个类,我 我真的很不愿意 复制并粘贴带有 不同的名字

  • 假设我放弃了1,即i 实际上选择了复制的代码 巨大的javabean类,我仍然 将处于不利的境地 必须编写构造函数 有大约20-25个参数要做 这个类是不可变的。什么是 使类不可变的更好方法 除了构造函数注入


  • 感谢和问候,

    要使其真正不可变,您需要在构造时初始化成员

    要做到这一点并避免构造函数中出现大量参数列表,一种方法(我不是说它很漂亮!)是使用具有相同属性的可变类型。通过“setters”一次设置一个可变类型的属性,然后将可变对象作为单个参数传递给不可变类型的构造函数。然后,不可变对象将属性从可变源复制到它自己的(
    final
    )成员

    你也可以考虑“有效的不可改变性”。也就是说,即使系统没有强制执行不可变性,您也可以使用将初始化阶段与使用阶段明确分开的编码实践。毕竟,序列化不需要不变性


    您可以更进一步,为接口创建一个实现隐藏包装器,该包装器不公开实现的属性。包装器仅通过委托给“真实”实现来实现接口中的方法。包装器中不存在来自实现的setter和getter。这将阻止客户端简单地从接口向下转换到实现类,并操纵属性。

    20-25属性对于一次性来说并不庞大,特别是如果您使用的是一个半体面的编辑器

    如果在构造不可变版本时已经有一个可变实例,只需将其传递给构造函数即可

    如果您想成为真正邪恶的黑客,请使用
    java.beans
    为实现
    Externalizable
    的可变类或子类创建可序列化的
    Map
    。或者,您可以使用
    java.beans
    XML序列化(通过java序列化可以发送的XML…。

    步骤1:创建一个新类,并为其提供与“大JavaBean对象”的实例变量名称完全相同的实例变量。这个新类不应该有setter(但只有getter)使其不可变

    步骤2:使用Apache Commons BeanUtils.copyProperties将所有属性(即实例变量)从“大java bean对象”复制到新对象。

    一些想法:

    受保护的设置器和工厂方法 您可以使用受保护的setter方法定义bean,并在同一个包中定义一个接受所有参数并调用这些setter的工厂类。bean在该包之外是不可变的。为了实现这一点,请确保密封jar,以便最终用户无法在同一个包中创建新类

    注意:您可以使用my JavaDude Bean注释简化创建:

    例如:

    @Bean(writer=Access.PROTECTED, // all setXXX methods will be protected
        properties={
            @Property(name="name"),
            @Property(name="age", type=int.class)
        })
    public class Person extends PersonGen {
    }
    
    在eclipse中创建getter和构造函数

    Eclipse提供了一些很好的工具来加快速度:

  • 创建bean类
  • 添加所需的字段
  • 在编辑器窗口中单击鼠标右键
  • 选择源->生成getter和setter
  • 按“选择获取者”按钮
  • 按ok
  • 在编辑器窗口中单击鼠标右键
  • 选择源->从字段生成构造函数
  • 在构造函数中选择并排序所需的字段
  • 按ok
  • 不变性修饰符

    另一个想法是用getter和setter定义bean(可以使用上述技术,但包括setter),然后可以为bean创建一个只包含getter的包装类。

    Joshua Bloch的“有效Java”说明了构建器模式,其中,简单生成器对象用于构造具有长构造函数参数列表的复杂对象。我推荐它


    一个包含getter的简单只读接口怎么样

    如果bean类是您自己的,那么让它简单地实现接口,并在创建后仅使用接口


    如果您无法控制bean类,还可以创建一个getter接口,并通过为getter接口创建一个代理来实现它,该代理使用一个调用处理程序将所有方法调用委托给bean。

    您可以为每个场景添加一些代码示例吗,我正在努力理解,这是一个很好的问题。除非您有一个重复的不可变类,否则似乎没有真正好的方法来解决这个问题。我使用了有效的不可变方法!