final的基本用法 以及 final和static final的区别
package com.study.refuse;
import java.util.*;
class Value {
int i; // Package access
public 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; }
// Typical public constant:
public final int VALUE_THREE = 39;
// Cannot be compile-time constants:
private final int i4 = rand.nextInt(20);//随机生成一个0-19的数
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 ,7,8,9,10,11};
private final int valueOne =20;
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");
FinalData fd3 = new FinalData("fd3");
System.out.println(fd2);
System.out.println(fd3);
}
} /* Output:
fd1: i4 = 15, INT_5 = 18
Creating new FinalData
fd2: i4 = 13, INT_5 = 18
fd3: i4 = 1, INT_5 = 18
*///:~
对于基本类型,final使数值恒定不变,对于对象引用, final使引用恒定不变。但是对象的自身可以改变
在 fd1,fd2,fd3内,i4的值是不可改变的,INT_5是在类装载时已被初始化,而不是加载新对象时初始化。
空白final
指被声明为final却没有给定初值的域。
必须在域的定义处或构造方法里给final进行赋值,所以final域总是在使用前初始化。
class Poppet {
private int i;
Poppet(int ii) { i = ii;
System.out.println(i);
}
}
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 the constructor:
public BlankFinal() {
j = 1; // Initialize blank final
p = new Poppet(1); // Initialize blank final reference
}
public BlankFinal(int x) {
j = x; // Initialize blank final
p = new Poppet(x); // Initialize blank final reference
}
public static void main(String[] args) {
new BlankFinal();
new BlankFinal(48);
}
} ///:~
final和private关键字
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()");
}
}
//class OverridingPrivate3 extends OverridingPrivate2{
// public final void f() {
// System.out.println("OverridingPrivate2.f()");
// }
//}
//子类可以再将方法声明为final ,如果父类不是final.
public class FinalOverridingIllusion {
public static void main(String[] args) {
OverridingPrivate2 op2 = new OverridingPrivate2();
System.out.println(op2);
op2.f();
op2.g();
// You can upcast:
OverridingPrivate op = op2;
// But you can't call the methods:
//! op.f();
//! op.g();
// Same here:
WithFinals wf = op2;
//! wf.f();
//! wf.g();
}
}
在方法前加private final 会造成混淆,因为声明为private 的方法,他的子类并不会重写他,所以只是拥有相同的方法名而已。
所以上面向上转型之后,无法调用子类的方法,因为子类根本就没有重写!这个很坑。。。
final类
final类禁止继承,所有方法隐式指定为final。所以不需要在final类中给方法加final,无意义。