我正在读一本关于Java的书,它说你可以将整个类声明为final。我想不出有什么地方可以用它。
我只是一个编程新手,我想知道程序员是否真的在他们的程序中使用这个。如果他们使用,他们什么时候使用,这样我就能更好地理解它,知道什么时候使用它。
如果Java是面向对象的,并且你声明了一个final类,难道它不会阻止类具有对象的特征吗?
我正在读一本关于Java的书,它说你可以将整个类声明为final。我想不出有什么地方可以用它。
我只是一个编程新手,我想知道程序员是否真的在他们的程序中使用这个。如果他们使用,他们什么时候使用,这样我就能更好地理解它,知道什么时候使用它。
如果Java是面向对象的,并且你声明了一个final类,难道它不会阻止类具有对象的特征吗?
当前回答
final类可以避免在添加新方法时破坏公共API
假设在基类的版本1中:
public class Base {}
客户会这样做:
class Derived extends Base {
public int method() { return 1; }
}
然后,如果在版本2中,你想添加一个方法method到Base:
class Base {
public String method() { return null; }
}
这将破坏客户端代码。
如果我们使用final类Base,客户端就不能继承,方法的添加也不会破坏API。
其他回答
在Java中,不能更改带有final修饰符的项!
这包括final类、final变量和final方法:
final类不能被任何其他类扩展 最终变量不能被重新赋值 final方法不能被覆盖
final类是不能扩展的类。此外,方法可以声明为final,以表明不能被子类覆盖。
如果您编写api或库,并希望避免被扩展以改变基本行为,则防止类被子类化可能特别有用。
假设你有一个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,厚脸皮的程序员会造成多大的混乱。
Final类不能扩展。因此,如果你想要一个类以某种方式运行,并且不希望有人重写方法(可能效率较低,恶意代码更多),你可以将整个类声明为final或你不想被更改的特定方法。
由于声明一个类并不会阻止一个类被实例化,这并不意味着它会阻止类具有对象的特征。只是您必须坚持使用类中声明方法的方式。
如果类被标记为final,这意味着类的结构不能被任何外部的东西修改。最明显的是当你在做传统的多态继承时,基本上类B扩展A是行不通的。它基本上是一种保护代码某些部分(一定程度上)的方法。
澄清一下,标记类final并没有将其字段标记为final,因此不会保护对象属性,而是保护实际的类结构。