当前位置: 首页 > 知识库问答 >
问题:

为什么不可变类不能有setter方法?

宰父玄天
2023-03-14

我在读关于不可变类的书,而使类不可变的方法据说是:

  • 1-使类成为最终类以防止继承

我认为第三个条件是不必要的。当我们使一个变量最终并为它提供任何值时,在那之后,即使通过setter方法也不能给它赋值(因为一旦赋值给它,最终变量就不能改变)。那么为什么我们需要第三个条件没有setter方法呢?

我是不是理解错了?

共有3个答案

金谭三
2023-03-14

是的,可以简化为

  1. 使类成为最终类以防止继承

然而,出于教育目的,更短的要点可能效果更好——即使有点多余。

洪永长
2023-03-14

你说得有点对。根据定义,setter用给定值替换字段。如果所有字段都是最终字段,那么无论如何都不可能提供setter。

我对如何编写不可变类的描述如下:

  • 使所有字段最终
  • 确保每个字段的类型本身是不可变的

如果您非常小心地确保字段永远不会更改,那么可以编写一个包含可变字段的不可变类,但在这种情况下需要非常小心。

孙修德
2023-03-14
public class Person{
  private String name;
  public Person(String name){
    this.name = name;
  }
  public String getName(){
    return this.name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

现在,很明显Person不是一个不可变的类。这并不意味着Person的实例不能是另一个(据说)不可变的类的成员。

public final class MyImmutableClass {
  // p is final, so it can't be re-referenced
  private final Person p;

  public MyImmutableClass(Person p) {
    this.p = p;
  }
  // it can be altered, though
  public void setPersonName(String name) {
    this.p.setName(name);
  }
  public String toString() {
    return "Person: " + p.getName();
  }
}

现在,我们有一个不可变的类,但它确实包含一个setter。这个二传手主动改变(最终)场p的一个成员。

public static void main(String[] args) {
  MyImmutableClass c = new MyImmutableClass(new Person("OriginalName"));
  System.out.println(c);
  c.setPersonName("AlteredName");
  System.out.println(c);
}

和给你。通过setter更改成员(即使变量是final)。要明白,“最终变量”不一定是常数,在大多数情况下,它的状态是可以改变的。最后一个变量的要点是,它不能被重新引用。注意,我们也可以有这样的方法:

public void setPerson(Person p) {
  this.p.setName(p.getName());
}

如果类型本身是不可变的类型,或者如果它是一个基元,那么最后一个变量本身只是一个常量,但是您应该理解,大多数类型都是可变的。类型是不可变的还是一个原语,并且它被声明为final?当然,添加一个setter。但是,为了什么?误导使用你的课程的人?

 类似资料:
  • 我现在在这里读到,为了实现我的目标的不变性,我必须: 宣布我的所有字段为私有和最终 不定义设定者 如果没有setter,为什么我需要声明字段是最终的。java编译器不允许这样的事情: 如果我尝试使用反射,那么关键字不会阻止我更改引用。 我在这里找到了一个很好的解释,为什么整个类需要是,但没有解释为什么私有字段需要是final。 编辑:作为对GotoFinal评论的回复,这里有一个类展示了我如何通过

  • 这个问题与前一个问题相关,在前一个问题中,我们注意到init捕获lambdas与Boost的范围和迭代器不兼容,因为一些相当模糊且嵌套很深的故障可能很难通过破解Boost来解决。射程源。 接受的答案建议将lambda存储在对象中。为了避免潜在的函数调用开销,我编写了两个函数对象,可以作为潜在的解决方法。它们在下面的代码中被称为和 不使用和编译行,并正确打印行的的实例。 然而,标准草案提到 5.1.

  • 问题内容: 我有一个通用的抽象模板类。我以为如果创建特定于类型的生产者,则可以直接在通用类中注入一些DAO服务。但是我不能。 为什么?我该如何解决? 当我注入一个例如它完美地工作。但是没有泛型… 问题答案: 当您要求 容器知道您要一个类型为的bean 。如果存在这样的bean并且其类型信息已知,则容器可以满足注入。例如,类型信息保留在带注释的方法中 容器使用反射来检索该参数化的类型,并将其与请求的

  • 相对来说,我是java的业余爱好者,一直使用类和对象调用静态变量和方法。当它们是静态的时,类和对象都可以使用它们。 为什么程序员不对类变量和方法都保持默认的静态?

  • 我在这里读了一些关于创建不可变对象的书,我想知道,我有以下类: 这是Oracle建议创建不可变类的方式,但是,在C#中,你可以声明你的setter私有,Java如果我这样做,它仍然是不可变的吗? 实现私有setter而不是使私有变量为final并使用构造函数有什么错?

  • 本文向大家介绍String 为什 么是不可变的?相关面试题,主要包含被问及String 为什 么是不可变的?时的应答技巧和注意事项,需要的朋友参考一下 简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,`private final char value[]`,所以 String 对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 Ab