java final keyword

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangbingfengf98/article/details/85289799

case 1: final data

// reuse/FinalData.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// The effect of final on fields

import java.util.*;

class Value {
  int i; // Package access

  Value(int i) {
    this.i = i;
  }
}

public class FinalData {
  private static Random rand = new Random(47);
  private String id;

  public FinalData(String id) {
    this.id = id;
  }
  // Can be compile-time constants:
  private final int valueOne = 9;
  private static final int VALUE_TWO = 99;
  // Typical public constant:
  public static final int VALUE_THREE = 39;
  // Cannot be compile-time constants:
  private final int i4 = rand.nextInt(20);
  static final int INT_5 = rand.nextInt(20);
  private Value v1 = new Value(11);
  private final Value v2 = new Value(22);
  private static final Value VAL_3 = new Value(33);
  // Arrays:
  private final int[] a = {1, 2, 3, 4, 5, 6};

  @Override
  public String toString() {
    return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
  }

  public static void main(String[] args) {
    FinalData fd1 = new FinalData("fd1");
    // - fd1.valueOne++; // Error: can't change value
    fd1.v2.i++; // Object isn't constant!
    fd1.v1 = new Value(9); // OK -- not final
    for (int i = 0; i < fd1.a.length; i++) {
      fd1.a[i]++; // Object isn't constant!
    } // - fd1.v2 = new Value(0); // Error: Can't
    // - fd1.VAL_3 = new Value(1); // change reference
    // - fd1.a = new int[3];
    System.out.println(fd1);
    System.out.println("Creating new FinalData");
    FinalData fd2 = new FinalData("fd2");
    System.out.println(fd1);
    System.out.println(fd2);
  }
}
/* Output:
fd1: i4 = 15, INT_5 = 18
Creating new FinalData
fd1: i4 = 15, INT_5 = 18
fd2: i4 = 13, INT_5 = 18
*/

Note the output show i4 are unique, INT_5 is not changed.

case 2: blank finals

// reuse/BlankFinal.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// "Blank" final fields

class Poppet {
  private int i;

  Poppet(int ii) {
    i = ii;
  }
}

public class BlankFinal {
  private final int i = 0; // Initialized final
  private final int j; // Blank final
  private final Poppet p; // Blank final reference
  // Blank finals MUST be initialized in constructor:
  public BlankFinal() {
    j = 1; // Initialize blank final
    p = new Poppet(1); // Init blank final reference
  }

  public BlankFinal(int x) {
    j = x; // Initialize blank final
    p = new Poppet(x); // Init blank final reference
  }

  public static void main(String[] args) {
    new BlankFinal();
    new BlankFinal(47);
  }
}

You’re forced to perform assignments to finals either with an expression at the point of definition of the field or in every constructor.

case 3: final arguments

// reuse/FinalArguments.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Using "final" with method arguments

class Gizmo {
  public void spin() {}
}

public class FinalArguments {
  void with(final Gizmo g) {
    // - g = new Gizmo(); // Illegal -- g is final
  }

  void without(Gizmo g) {
    g = new Gizmo(); // OK -- g not final
    g.spin();
  }
  // void f(final int i) { i++; } // Can't change
  // You can only read from a final primitive:
  int g(final int i) {
    return i + 1;
  }

  public static void main(String[] args) {
    FinalArguments bf = new FinalArguments();
    bf.without(null);
    bf.with(null);
  }
}

case 4: final methods

There are two reasons for final methods. The first is to put a “lock” on the method to prevent an inheriting class from changing that method’s meaning by overriding it.

The second reason final methods were suggested in the past is efficiency. In earlier implementations of Java, if you made a method final , you allowed the compiler to turn any calls to that method into inline calls. When the compiler saw a final method call, it could (at its discretion) skip the normal approach of inserting code to perform the method call mechanism (push arguments on the stack, hop over to the method code and execute it, hop back and clean off the stack arguments, and deal with the return value) and instead replace the method call with a copy of the actual code in the method body. This eliminates the overhead of the method call. However, if a method is big, your code begins to bloat, and you probably wouldn’t see performance gains from inlining, since any speedups in the call and return were dwarfed by the amount of time spent inside the method. Relatively early in the history of Java, the virtual machine (in particular, the hotspot technologies) began detecting these situations and optimizing away the extra indirection. For a long time, using final to help the optimizer has been discouraged. You should let the compiler and JVM handle efficiency issues and make a method final only to explicitly prevent overriding.

ps: please note the comments in the code.

case 5: final and private

Any private methods in a class are implicitly final.

// reuse/FinalOverridingIllusion.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// It only looks like you can override
// a private or private final method

class WithFinals {
  // Identical to "private" alone:
  private final void f() {
    System.out.println("WithFinals.f()");
  }
  // Also automatically "final":
  private void g() {
    System.out.println("WithFinals.g()");
  }
}

class OverridingPrivate extends WithFinals {
  private final void f() {
    System.out.println("OverridingPrivate.f()");
  }

  private void g() {
    System.out.println("OverridingPrivate.g()");
  }
}

class OverridingPrivate2 extends OverridingPrivate {
  public final void f() {
    System.out.println("OverridingPrivate2.f()");
  }

  public void g() {
    System.out.println("OverridingPrivate2.g()");
  }
}

public class FinalOverridingIllusion {
  public static void main(String[] args) {
    OverridingPrivate2 op2 = new OverridingPrivate2();
    op2.f();
    op2.g();
    // You can upcast:
    OverridingPrivate op = op2;
    // But you can't call the methods:
    // - op.f(); // error: f() has private access in OverridingPrivate
    // - op.g(); // error: g() has private access in OverridingPrivate
    // Same here:
    WithFinals wf = op2;
    // - wf.f(); // error: f() has private access in WithFinals
    // - wf.g(); // error: g() has private access in WithFinals
  }
}
/* Output:
OverridingPrivate2.f()
OverridingPrivate2.g()
*/

If a method is private , it isn’t part of the base-class interface. It is just code that’s hidden away inside the class, and it just happens to have that name. But if you create a public, protected, or package-access method with the same name in the derived class, there’s no connection to the method that might happen to have that name in the base class. You haven’t overridden the method, you’ve just created a new method.

case 6: final classes

It prevents inheritance.

// reuse/Jurassic.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Making an entire class final

class SmallBrain {}

final class Dinosaur {
  int i = 7;
  int j = 1;
  SmallBrain x = new SmallBrain();

  void f() {}// implicicitly final
}

// - class Further extends Dinosaur {}
// error: Cannot extend final class 'Dinosaur'

public class Jurassic {
  public static void main(String[] args) {
    Dinosaur n = new Dinosaur();
    n.f();
    n.i = 40;
    n.j++;
  }
}

Be caution when make a method final.

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/reuse/FinalData.java

3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/reuse/BlankFinal.java

4. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/reuse/FinalArguments.java

5. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/reuse/FinalOverridingIllusion.java

6. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/reuse/Jurassic.java

猜你喜欢

转载自blog.csdn.net/wangbingfengf98/article/details/85289799