final 和其他 Java 关键字 - 1

“嗨,阿米戈!”

“嗨,比拉博!”

“今天,我将向您介绍 Java 中的几个关键字。但我将从最有趣的关键字开始:关键字 final。

“在声明变量、方法或类时可以使用关键字final 。”

“为什么我们需要final?”

“这很简单。如果我们将一个变量标记为最终变量,那么它就变得不可更改了:”

final int i = 5;
i++; //Compilation error: the value of i cannot be changed.

“我懂了。”

“如果我们将方法标记为 final,则禁止在派生类中覆盖该方法:”

class Cat
{
 public final String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat
{
 public String getName() //Compilation error: overriding the getName()
 {
  return "tiger";
 }
}

“我明白了。但是为什么你需要禁止覆盖一个方法呢?”

“嗯,举个例子,假设一个程序员在一个方法中写了很多重要的代码,并且想保证所有继承他的类的类都具有指定的行为。”

“最后,第三种用法。”

“如果我们用关键字 final 标记一个类,那么它就不能被继承。”

public final class Cat
{
 public String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat //Compilation error: the Cat class cannot be
{
 public String getName()
 {
  return "tiger";
 }
}

“为什么我们要阻止一个类被继承?”

“你应该明白,我们阻止继承并不是为了烦人,而是为了安全和代码完整性。如果不禁止类继承,那么暗示它是允许的。而且类的编写的代码设计器将适用于此类的对象以及任何派生类的对象。”

“但是,如果开发人员意识到即使对他的类进行微小的更改也会导致一切按预期停止工作,那么最好禁止继承。”

“例如,String 类被声明为 final,所有原始类型也是如此:Integer、Boolean、Double、Character……”

“啊,明白了。String 类是作为不可变类创建的,如果它们突然可变,那么很多东西都会停止工作。”

“好吧,差不多。这么说吧:一切都会像以前一样工作,但有时会出现很难发现和理解的错误。所以,在某些情况下,继承类或方法并不是真正的罪过,但禁止它意味着以后要捕获的错误更少。”

“你还能在哪里使用final?”

“您可以在函数参数之前和方法中的变量之前使用 final。这是一个示例:”

public void setName(final String name)
{
 final String displayName = "Mr."+ name;
  …
 this.name = displayName;
}

“那有什么意义呢?”

“嗯,有两个。首先,如果我们想告诉其他开发人员这个值是一个特定的常量,而不仅仅是一个变量,我们就将一个变量声明为 final。”

例如,我们要根据价格计算销售税:

public int getPriceNDS()
{
 final int NDS = 20;
 return this.price * NDS / 200;
}

“其次,我们在编写本地或匿名内部类时需要这种类型的变量。我很快就会告诉你这些类型的类。但不是今天。”

“好吧,到目前为止还没有什么太复杂的事情。”

“请注意,只有变量变得不可更改,而不是它可能引用的对象。对象仍然可以更改。”

“其实我正想问问这个,而且没有办法让对象不可变?”

“不,除非你写一个不可变的类。”

“请注意,由于无法更改最终变量的值,因此您必须立即为其分配初始值。”

这段代码将编译 此代码无法编译
class Home
{
 private final int width = 200;
 private final int height = 100;

 public Home()
 {
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
 }
}

“但是,也就是说,Java 允许您将类的最终变量的初始化延迟到构造函数。”

这段代码将编译 此代码无法编译
class Home
{
 private final int width = 200;
 private final int height;

 public Home()
 {
  height = 100;
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
 }
}

“此外,不同的构造函数可以用不同的值初始化最终变量。这很方便:”

这段代码将编译
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
  width = 200;
 }

 public Home(int width)
 {
  this.height = 300;
  this.width = width;
 }

 public Home(int width, int height)
 {
  this.height = height;
  this.width = width;
 }
}

“这是一个非常有趣的话题,绝对一切都说得通。谢谢你,Bilaabo!”