一·final变量
final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常,由final定义的变量为常量。
final关键字定义的变量必须在声明时对其进行赋值操作。final除了可以修饰基本数据类型的常量,还可以修饰对象引用,也可以修饰数组。一个既是static又是final的字段只占据一段不能改变的储存空间。
import static java.lang.System.out;
import java.util.Random;
class test{
int i=0;
}
public class Test2{
static Random rand=new Random();
private final int value_1=1;
private final int value_2=2;
private final int[] a={1,2,3,4,5,6};
private final int irand=rand.nextInt(20); //随机产生就不会改变
private final int firand=rand.nextInt(20);
private final test t1=new test();
private test t2=new test();
public String toString(){
return irand+" "+firand;
}
public static void main(String[] args) {
Test2 t=new Test2();
//t.t1=new test(); 编译报错
//t.value_2++; 编译报错
t.t2=new test();
for(int i=0;i<t.a.length;i++)
// a[i]=10; 编译报错
out.println(t); //输出对象 (toString)
out.println("t");
out.println(new Test2()); //新引用一个对象,就会新产生irand和firand
out.println(t);
}
}
输出结果:
3 11
3 11
3 11
3 11
3 11
3 11
t
10 16
3 11
static final与final的区别
package com.code;
import java.util.Random;
import static java.lang.System.out;
public class FinalStatic {
private static Random rand=new Random();
private final int a1=rand.nextInt(10);
private static final int a2=rand.nextInt(10); //final static 在内存中固定,无法改变其值
public static void main(String[] args) {
FinalStatic f1=new FinalStatic();
out.println(f1.a1);
out.println(f1.a2);
FinalStatic f2=new FinalStatic();
out.println(f2.a1);
out.println(f2.a2);
}
}
输出结果:
7
7
0
7
a1会在实例化对象时被更改,在那个对象里他是不能被更改的
a2是static final 形式的,在内存中他是一个无法改变的区域,当再实例化一个FinalStatic 对象时,仍然指向a2这块内存区域,所以a2的值不改变
程序在哪些位置可以定义final数据
public class FinalTest{
final int value1=1; //final成员变量不可更改
final int value2; //声明final成员变量时没有赋值,称为空白final
public FinalTest(){
value2=2; // 在构造方法中卫空白final赋值
}
int doit(final int x){ //设置final参数,不可以改变参数的值
return x+1;
}
void dosomething(){
final int i=3; //局部变量定义为final,不可以改变i的值
}
}
二·final方法
final方法不能被重写,将方法定义为final类型,可以防止子类修改该类的定义与实现方式。final的方法的执行效率要高于非final方法。修身符private,如果在父类的某个方法被设置为private修饰符,子类无法访问该方法,自然无法覆盖该方法。一个定义为private方法隐式被指定为final类型,因此无法将一个定义为private方法再定义为final类型。
private final void test(){
//......
}
在父类中被定义为private final的方法似乎可以被子类覆盖(注意似乎),其实并不是覆盖,如下面例子
class Parents{
private final void doit(){
System.out.println("父类.doit()");
}
final void doit2(){
System.out.println("父类.doit2()");
}
public void doit3(){
System.out.println("父类.doit3()");
}
}
class Son extends Parents{
public final void doit(){ //在子类中定义一个doit()方法
System.out.println("子类.doit()");
}
/* final void doit2(){ 编译报错 final方法不能重写
System.out.println("子类.doit2()");
}*/
public void doit3(){
System.out.println("子类.doit3()");
}
}
public class FinalMethod {
public static void main(String[] args) {
Son s=new Son();
s.doit();
Parents p=s;
p.doit2();
p.doit3();
}
}
输出结果:
子类.doit()
父类.doit2()
子类.doit3()
final方法不能被重写,所以doit2()方法不能被重写。在父类中定义了一个private final的doit()方法,同时在子类中也定义了一个doit()方法,表面上覆盖了父类的doit()方法,其实并没有,覆盖必须满足一个对象向上转型为它的基本类型并调用相同方法这样一个条件。可是你发现,主函数中"Parents p=s;"执行向上操作,但是p并不能调用doit()方法。所以子类中的doit()方法并不是被正常覆盖了,而是产生了一个新方法
class Parents{
public void doit(){
System.out.println("父类.doit()");
}
final void doit2(){
System.out.println("父类.doit2()");
}
public void doit3(){
System.out.println("父类.doit3()");
}
}
class Son extends Parents{
public void doit(){
System.out.println("子类.doit()");
}
/* final void doit2(){
System.out.println("子类.doit2()");
}*/
public void doit3(){
System.out.println("子类.doit3()");
}
}
public class FinalMethod {
public static void main(String[] args) {
Son s=new Son();
s.doit();
Parents p=s;
p.doit(); //向上转型 子类的重写方法覆盖了父类
p.doit2();
p.doit3();
Parents p2=new Parents();
p2.doit(); //没有向上转型
}
}
输出结果:
子类.doit()
子类.doit()
父类.doit2()
子类.doit3()
父类.doit()
三·final类
定义为final的类不能被继承。如果希望一个类不被任何类继承,并且不允许其他人对这个类进行任何改动,可以将这个类定义为final形式
final 类名{
}
将一个类定义为final形式,则类中的所有方法都被隐式设置为final形式,但是final类中的成员变量可以被定义为final或非final形式
final class Test {
int i=0;
public static void main(String[] args) {
Test t=new Test();
t.i++;
System.out.println(t.i);
}
}
输出结果:
1