final关键字

final可以修饰非抽象类、非抽象类成员方法和变量。

(1)final类:不能被继承,没有子类,final类中的方法默认是final的;

(2)final方法:不能被子类的方法覆盖,但可以被继承;

(3)final成员变量:表示常量,只能被赋值一次,赋值后值不再改变;

(4)final不能用于修饰构造方法。

(父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final的)

1.final类

  final类不能被继承,因此final类的成员方法没有机会被覆盖,默认是final的,在设计类的时候,如果这个类不需要有子类,类的实现细节不允许变动,并且确定这个类不会再被扩展,可以将这个类设置为final类。

2.final方法

  如果一个类不允许子类覆盖某个方法,可以将这个方法设置为final方法。

  将方法声明为final的原因主要有两个:

    ①将方法锁定:防止任何子类修改它的意义和实现;

    ②高效:编译器遇到调用final方法的时候,会转入内嵌机制,大大提高执行效率。

父类Test1.java

package EmployeeTest_4_2;

public class Test1 
{
	public static void main(String[] args)
	{
		
	}
	
	public void f1()
	{
		System.out.println("父类的f1");
	}
	
	public final void f2()
	{
		System.out.println("父类的f2");
	}
	
	public void f3()
	{
		System.out.println("父类的f3");
	}
	
	public void f4()
	{
		System.out.println("父类的f4");
	}
	
}

  

子类Test2.java

package EmployeeTest_4_2;

public class Test2 extends Test1
{
	public void f1()
	{
		System.out.println("父类的f1方法被覆盖!");
	}

	//这种声明f2的方法会报错,因为在Test1中已经将f2方法声明为final
//	public void f2()
//	{
//		System.out.println("父类的f2方法被覆盖!");
//	}
	
	public void f3()
	{
		System.out.println("父类的f3方法被覆盖!");
	}
	
	
	public static void main(String[] args)
	{
		Test2 t = new Test2();
		t.f1();
		t.f2();
		t.f3();
		t.f4();
	}

}

  

输出的结果为:

父类的f1方法被覆盖!
父类的f2
父类的f3方法被覆盖!
父类的f4

  由于父类中f2方法已经被声明为final,所以如果在子类Test2中重写f2方法的时候,会报错,这时候会提示将父类Test1中的f2方法声明为“非final”方法。

Exception in thread "main" java.lang.VerifyError: class EmployeeTest_4_2.Test2 overrides final method f2.()V
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(Unknown Source)
	at java.security.SecureClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.access$100(Unknown Source)
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

  

3.final变量

  用final修饰的成员变量表示常量,值一旦给定就无法改变。

  总共可以修饰三种变量:静态变量、实例变量和局部变量。

  final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。

package EmployeeTest_4_2;

public class Test3
{
private final String s = "final变量";
private final int A = 100;
public final int B = 90;

public static final int C = 80;
public static final int D = 70;

public final int E;//final空白,必须在初始化对象的时候赋初值

public Test3(int x)
{
E = x;
}

public static void main(String[] args)
{
Test3 t = new Test3(2);
// t.A = 101;//final变量的值一旦给定就无法改变
// t.B = 91;
// t.C = 81;
// t.D = 71;

System.out.println(t.A);
System.out.println(t.B);
System.out.println(t.C); //不推荐用对象方式访问静态字段
System.out.println(t.D);
System.out.println(Test3.C);
System.out.println(Test3.D);
//System.out.println(Test3.E);//出错,因为E为final空白,依据不同对象值有所不同.
System.out.println(t.E);

Test3 t1 = new Test3(3);
System.out.println(t1.E);//final空白变量E依据对象的不同而不同
}

private void test()
{
System.out.println(new Test3(1).A);
System.out.println(Test3.C);
System.out.println(Test3.D);
}

public void test2()
{
final int a;//final空白,在需要的时候才赋值
final int b = 4;//局部常量--final用于局部变量的情形
final int c;//final空白,一直没有给赋值.
a = 3;
//a=4; 出错,已经给赋过值了.
//b=2; 出错,已经给赋过值了.
}
}

输出结果:

100
90
80
70
80
70
2
3

4. final参数

  当函数参数为final类型的时候,可以读取使用该参数,但是无法修改该参数的值。

  

package EmployeeTest_4_2;

public class Test4 
{
	public static void main(String[] args)
	{
		new Test4().f1(1);
	}
	
	public void f1(final int i)
	{
		System.out.println(i);
	}

}

总结:

  1、final修饰类

    final修饰的类不允许被继承。一个类不能既是final的,又是abstract的,因为抽象类的目的就是为了让子类去实现其中的方法,而final修饰的类不能被继承,所以产生了矛盾。

  2、final修饰方法

    final修饰方法,表示该方法不能被子类重写Override。

  3、final修饰变量

    final成员变量表示常量,只能被赋值一次,赋值后的值不能改变。

 

原文地址:https://www.cnblogs.com/Mr24/p/6748011.html