我正在读一本关于Java的书,它说你可以将整个类声明为final。我想不出有什么地方可以用它。

我只是一个编程新手,我想知道程序员是否真的在他们的程序中使用这个。如果他们使用,他们什么时候使用,这样我就能更好地理解它,知道什么时候使用它。

如果Java是面向对象的,并且你声明了一个final类,难道它不会阻止类具有对象的特征吗?


当前回答

面向对象不是关于继承,而是关于封装。继承会破坏封装。

在很多情况下,声明类final是非常有意义的。任何代表“价值”的对象,如颜色或金额,都可能是最终的。他们是独立的。

如果您正在编写类库,请将类设为final,除非您显式地将它们缩进以派生。否则,人们可能会派生你的类并重写方法,破坏你的假设/不变量。这也可能有安全隐患。

Joshua Bloch在《Effective Java》一书中建议明确地为继承而设计,或者禁止为继承而设计,他指出为继承而设计并不是那么容易。

其他回答

是的,有时您可能需要这样做,无论是出于安全性还是速度原因。在c++中也可以做到。它可能不适用于程序,但更适用于框架。 http://www.glenmccl.com/perfj_025.htm

在一个场景中,final很重要,当您出于安全原因想要防止类的继承时。这允许您确保您正在运行的代码不会被其他人覆盖。

另一个场景是为了优化:我似乎记得Java编译器内联了final类中的一些函数调用。因此,如果你调用a.x()并且a被声明为final,我们在编译时就知道代码将是什么,并且可以内联到调用函数中。我不知道这是否真的做到了,但最终是有可能的。

在java中,final关键字用于以下场合。

最后一个变量 最后的方法 最后的课程

在java中,final变量不能重赋,final类不能扩展,final方法不能重写。

假设你有一个Employee类,它有一个方法greet。当greet方法被调用时,它只是简单地打印Hello everyone!这就是greet方法的预期行为

public class Employee {

    void greet() {
        System.out.println("Hello everyone!");
    }
}

现在,让GrumpyEmployee继承Employee并重写greet方法,如下所示。

public class GrumpyEmployee extends Employee {

    @Override
    void greet() {
        System.out.println("Get lost!");
    }
}

现在在下面的代码中看看sayHello方法。它以Employee实例作为参数,并调用greet方法,希望它会说Hello everyone!但我们得到的是滚开!这种行为变化是因为员工grumpyEmployee = new grumpyEmployee ();

public class TestFinal {
    static Employee grumpyEmployee = new GrumpyEmployee();

    public static void main(String[] args) {
        TestFinal testFinal = new TestFinal();
        testFinal.sayHello(grumpyEmployee);
    }

    private void sayHello(Employee employee) {
        employee.greet(); //Here you would expect a warm greeting, but what you get is "Get lost!"
    }
}

如果Employee类是final类,则可以避免这种情况。想象一下,如果没有将String Class声明为final,厚脸皮的程序员会造成多大的混乱。

我只知道一个实际用例:生成类

在生成类的用例中,我知道一个:依赖注入,例如https://github.com/google/dagger