当前位置: 首页 > 面试题库 >

为什么final关键字对于不可变的类是必需的?

别旻
2023-03-14
问题内容

您能否澄清一下,为什么在我们将 final 关键字设为不变时,为什么 在上课之前需要 final
关键字。我的意思是,如果我们将所有属性声明为私有和最终的,那么它也是一个不可变的类,不是吗?

很抱歉,这个问题似乎很简单,但是我对此感到非常困惑。帮帮我。

编辑:我知道一个声明为final的类不能被子类化。但是如果每个属性都是私有和final的,那有什么区别呢?


问题答案:

正如堆纸器所说的那样,final确保该类没有被子类化。这很重要,因此任何 依赖 其不变性的代码都可以安全地这样做。

例如,不可变类型(每个字段也是不可变类型)可以在线程之间自由使用,而不必担心数据争用等。现在考虑:

public class Person {
    private final String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

看起来 喜欢你可以分享Person没有问题的自由跨线程的实例。但是,当您共享的对象 实际上是 一个可变子类时,该怎么办:

public class Employee extends Person {
    private String company;

    public Employee(String name, String company) {
        super(name);
        this.company = company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getCompany() {
        return company; 
    }
}

现在,Employee 不可以 在线程之间共享实例,因为它们不是不可变的。但是进行共享的代码 可能
只将它们作为Person…的实例来了解,从而导致它们产生错误的安全感。

缓存也是如此-缓存和重用不可变类型应该是安全的,对吗?那么,它 安全的缓存实例那些真正不可变型的-但如果你正在处理一个类型本身不允许突变,但
不会 允许子类,它是突然不是安全了。

想一想java.lang.Object。它没有任何可变字段,但是将每个Object引用都视为对不变类型的引用显然是一个坏主意。基本上,这取决于您是否将不变性视为类型或对象的属性。真正不可变的类型声明“任何时候看到这种类型的引用,您都可以将其视为不可变的”
–而允许任意子类化的类型则不能声明该声明。

顺便说一句,有一个半途而废的方法:如果您可以将子类别限制为仅“受信任”的位置,则可以确保所有内容都是不可变的,但仍允许该子类别。Java中的访问使这一点变得棘手,但是例如在C#中,您可以有一个公共类,该公共类只允许在同一程序集中进行子类化-
提供一个在不可变性方面很好并且很强的公共API,同时仍然允许多态性的好处。



 类似资料:
  • 问题内容: 为什么字典键必须是不可变的?我正在寻找一个简单明了的原因,为什么Python字典中的键具有该限制。 问题答案: 在我的计算机上,有一个包含大量英语单词的文件: 让我们创建一个字典来存储所有这些单词的长度: 并且,为了踢球,我们将改组原始单词列表: 嗯,滚刀。无论如何…现在我们已经有点混乱了,我们变得有点偏执了(可能出于与渴望滚刀相同的原因),并且我们想检查字典中的所有单词是否都正确。我

  • 有一个问题,为什么他们要求在字典中使用不可变对象作为键。 当我最近使用字典(显然不是为了哈希表)将Xml节点对象作为键放置时,这个问题实际上进入了我的脑海。然后,我在使用过程中多次更新节点。 那么,“使用不可变键”到底意味着什么呢?

  • 问题内容: 我不明白为什么我不能总是从“侦听器”或“处理程序”内部访问变量。 这是我的代码: 唯一的方法是使用关键字声明它: 为什么需要声明变量 final 以获取事件内部的访问权限? 问题答案: 您是一个匿名内部类,我认为这很清楚: 本地类绝对可以引用实例变量。它们无法引用非最终局部变量的原因是,方法返回后,局部类实例可以保留在内存中。当该方法返回时,局部变量超出范围,因此需要它们的副本。如果变

  • 问题内容: 似乎几乎没有人意识到这一点,但是Java中的“ thisreference”是最终的。在正常的编程天中,我认为可以通过在自己的类中重新定义此引用来重新定义整个实例: 为什么此引用在Java中是最终的? 问题答案: 问题不在于它是参考,而是它本身根本不是参考。是一个 关键字 ,“表示一个值,该值是对为其调用实例方法或默认方法的对象的引用”(JLS§15.8.3)。 此外,从可以重新分配变

  • 当我在写这段代码时,我得到了一个编译时错误,它说:“lambdas中的变量必须是final或实际上是final”。

  • 下面是一个不可变类的示例: 下面是类的实现: 当我创建的实例时,我正在的构造函数中对进行深度复制,但是我能够通过更新的值,这种方法破坏了my类的不变性。我在这里做错了什么?