Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.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
Java中的不可变类_Java_Class_Immutability_Final - Fatal编程技术网

Java中的不可变类

Java中的不可变类,java,class,immutability,final,Java,Class,Immutability,Final,根据许多文档,我已经看到不可变类应该具有以下特性: 课程应该是期末考试 所有的方法都应该是最终的 所有的变量都应该是最终的 不应该有任何二传手 但我的问题是: 如果我有一个只有最终变量的类呢 如果我也有setter,我就不能改变对象的状态,因为我有所有的最终变量。那么这将如何影响不变性呢 在这种情况下,继承如何更改对象状态 1.如果我有一个只有final变量的类怎么办 这会让你走得更远,但不是一路走来。这些变量的类型也需要是不可变的。例如考虑< /P> class MyImmutableClas

根据许多文档,我已经看到不可变类应该具有以下特性:

  • 课程应该是期末考试

  • 所有的方法都应该是最终的

  • 所有的变量都应该是最终的

  • 不应该有任何二传手

  • 但我的问题是:

  • 如果我有一个只有最终变量的类呢

  • 如果我也有setter,我就不能改变对象的状态,因为我有所有的最终变量。那么这将如何影响不变性呢

  • 在这种情况下,继承如何更改对象状态

  • 1.如果我有一个只有
    final
    变量的类怎么办

    这会让你走得更远,但不是一路走来。这些变量的类型也需要是不可变的。例如考虑< /P>
    class MyImmutableClass {
        // final variable, referring to a mutable type
        final String[] arr = { "hello" };
    
        // ...
    }
    
    这允许某人做某事

    myImmutableObject.arr[0] = "world";
    
    并有效地改变不可变类的对象

    此外,建议禁止扩展类(因为没有办法强制子类是不可变的)。请参阅下面第三个问题的答案

  • 如果我也有setter,我就不能改变对象的状态,因为我有所有的最终变量。那么这将如何影响不变性呢
  • 对。如果所有变量都是final,那么标准设置器方法就不可能存在

  • 在这种情况下,继承如何更改对象状态
  • 子类不能更改超类的最终字段的状态。但是继承还有另一个问题

    如果您有一个不可变的
    动物
    子类,并且
    有一个变异对象的
    setDogsName
    方法,那么实际上您可能有实际上是可变的
    动物
    对象(类型

    换句话说,如果一个不可变的类开放进行扩展,那么不可变性的大部分(全部?)好处就失去了:例如,如果您收到一个
    Animal
    作为方法的参数,您就不能假定它是不可变的。你不能安全地将
    Animal
    对象作为键放在散列图中,等等


    基本上,原始语句有点多余,这就是为什么我认为它们有点令人困惑的原因:

    • 不能扩展
      final
      类,因此将方法标记为
      final
    • 如果所有变量都是最终的,那么说不应该有设置器是多余的
    此外,这些是足够的约束,但不是必需的。例如,您可以拥有没有最终变量/最终字段类型的不可变类,只要它们是私有的、从未在内部更改并且从未泄漏给外部人员

    如果我也有setter,我不能改变对象的状态,就像 我有所有的最终变量。那么这将如何影响不变性呢

    final
    位于参考级别,而不变性位于实例级别

    在上面的代码中。如果没有引用列表,则任何人都可以执行以下操作:
    someList.add(someValue)

    但他们无法做到:

    someList=someOtherList;
    
    这就是区别

    在这种情况下,继承如何更改对象状态


    子类可以访问父类的某些字段,然后对其进行更改。可以使父类引用点指向子类对象并修改其字段。因此,为了确保不变性,您必须确保子类不会改变父类中的任何内容。所以,让它成为最终的,一个不可变的类是你不能改变的。实现不变性就是消除改变对象状态的可能方式。这可以通过结构和行为手段的结合来实现


    但首先,让我们看看“应该拥有”列表:

    • “课程应该是最终的”-这可能是可取的,但可能不是严格必要的。。。甚至是令人渴望的。即使某些子类的实例是可变的,类的实例1也可以是不可变的。这完全取决于哪些类需要是不可变的,这取决于上下文

    • “所有的方法都应该是最终的”——既不必要也不充分。如果该类为
      final
      ,则不需要该类。如果该类不是
      final
      ,则它是不够的。(您可以在子类中添加具有不同签名的方法。)

    • “所有变量都应该是最终的”-既不必要也不充分。您可以有一个字段不是
      final
      的不可变类,以及一个字段都是
      final
      的可变类

    • “不应该有任何setter”-这取决于你所说的“setter”是什么意思,但再一次,这既不是必要的(对于某些可变模型),也不是充分的


    你的问题:

    1) 如果我有一个只有最终变量的类呢

    这不足以保证不变性。例如,如果最后一个变量之一是数组,则可以更改该数组的状态,从而更改整个对象的状态。这可以由setter(或该类的任何其他方法)完成,或者如果该类是“泄漏抽象”,则可以由外部代码完成

    2) 如果我也有setter,我就不能改变对象的状态,因为我有所有的最终变量。那么这将如何影响不变性呢

    见上文。将所有字段声明为
    final
    并不能保证不变性。setter可以更改对象的可变组件的状态

    3) 在这种情况下,继承如何更改对象状态

    不可能。但这不是重点

    创建不可变类
    final
    的原因是为了阻止某人创建该类的可变子类

    这有什么关系

    好吧,假设一个方法要求参数是不可变的(例如为了安全)。如果您用一个不可变的类声明它
    someList=someOtherList;