final
:最终的,不可更改的
final
可以用来修饰的结构:类、方法、变量(成员变量、局部变量)
表示这个类不能被继承,没有子类。提高安全性,提高程序的可读性。
例如:String类、System类、StringBuffer类
final class Eunuch{//太监类
}
class Son extends Eunuch{//错误
}
【举例】
正常情况下:
class A{
}
class B extends A{
}
若此时类A前面有final修饰,则B无法继承于A。如下:
什么样的类需要用final去修饰呢?
功能不需要再被扩展了,比如String
类、StringBuffer
类、StringBuilder
类。
会发现String加了一个final修饰:
public final class String...
这就意味着不能去声明一个类去继承于String。
Stirng类用final修饰,没有必要再进行功能的扩展。
表示这个方法不能被子类重写。
例如:Object类中的getClass()
class Father{
public final void method(){
System.out.println("father");
}
}
class Son extends Father{
public void method(){//错误
System.out.println("son");
}
}
【举例】
正常情况下:
class C{
public void method(){
}
}
class D extends C{
//此时可以
public void method(){
}
}
若是method()方法前面有final
修饰,就不能重写了。如下:
什么样的方法需要用final去修饰呢?
当这个方法已经设计的很完备了,也没有扩展的必要性,就可以用final修饰。
比如Object类中的getClass()
。
可以看一下,首先Ctrl+N
调出搜索框,输入“Object”:
然后Ctrl+F12
,搜索”getClass“:
然后可以看到getClass被final修饰,表示这个方法不能被重写了。这个方法的作用就是获取当前对象所属的类,不需要重写。
native
表示调用的是本地的方法,会调用底层C、C++相关的代码。
native修饰的getClass()方法若是调用的时候,这个方法的栈帧会进入栈中,此时它入的栈叫做本地方法栈。
这个本地方法,就是指native修饰的方法。
为啥getClass()方法没有方法体?因为它调用的是底层的C、C++,不是用java代码写的,所以没有方法体。它会链接到相关dll文件中的C、C++代码。
在早期,Java发展不成熟的时候,会用到native。
final修饰某个变量(成员变量或局部变量),一旦赋值,它的值就不能被修改,即常量
,常量名建议使用大写字母。
例如:final double MY_PI = 3.14;
如果某个成员变量用final修饰后,没有set方法,并且必须初始化(可以显式赋值、或在初始化块赋值、实例变量还可以在构造器中赋值)
public class FinalTest {
public static void main(String[] args) {
E e=new E();
System.out.println(e.MIN_SCORE); //可以调用
}
}
class E{
//成员变量
final int MIN_SCORE=0;
}
常量MIN_SCORE可以被调用,但是不能更改:
若此时将常量的显示赋值删掉,发现不可以:
没有默认值吗?
对于final
修饰的成员变量,这时候默认值就不好使了。即使想用默认值0,也需要写出来。
若用方法赋值,不可以:
方法需要用对象去调用,而调用对象的时候,这个值该有就应该得有了。
之前说过给类的实例变量赋值的位置,其中默认初始化、显示初始化、代码块中初始化、构造器中初始化,它们在造对象过程中实现;而通过“对象.属性”或“对象.方法”进行赋值的时候,对象已经有了。
现在我们给常量赋值,意思就是当创建完对象的时候,这些属性的值就应该要有了。
后续调用方法(比如setRight()方法),体现为修改这个值。
而在声明它的时候没有赋值,而在有了对象之后,方法里面又不能修改这个值。
当对象创建完,属性的值就应该确定下来了。
有哪些位置可以给成员变量赋值?
class E{
//成员变量
//1.默认赋值--NO
//final int MIN_SCORE;
//2.显示赋值--YES
final int MIN_SCORE=0;
//3.代码块中赋值--YES
final int MAX_SCORE;
{
MAX_SCORE=100; //一旦赋值就不可以再次赋值
}
//4.构造器中赋值--YES
final int LEFT;
public E(){ //用此构造器造完对象LEFT就赋完值了
LEFT=2;
}
public E(int left){ //不同构造器都需要对常量LEFT赋值,每造一个对象就会拥有一份LEFT,所以每个对象的LEFT可以不同,但是一旦赋值不可更改
LEFT=left;
}
//5.方法赋值--NO
/*final int RIGHT; //没有在允许的位置赋值
public void setRIGHT(int right){
RIGHT=right; //有了对象之后,不能在方法里面修改常量的值
}*/
}
public final class Test {
public static int totalNumber = 5;
public final int ID;
public Test() {
ID = ++totalNumber; // 可在构造器中给final修饰的“变量”赋值
}
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.ID);
}
}
final修饰局部变量:一旦赋值就不能修改
【举例】
一般情况下:
class F{
public void method(){
int num=10;
num++;
System.out.println(num);
}
}
若此时给num加上final,就不可以对num更改了:
如下:
class F{
public void method(){
final int num=10; //写两行也没事,只要在调用它之前赋上值就行,一旦赋值不可更改
//num++;
System.out.println(num);
}
}
【举例】
一般情况下:
class F{
public void method(int num){
num++;
System.out.println(num);
}
}
若是给num加上final
,num就是一个常量,这个常量还是在调用的时候赋的,那么赋完值之后就不要更改了。
如下:
class F{
public void method(final int num){
//num++; //赋完值之后就不要更改了
System.out.println(num);
}
}
public class TestFinal {
public static void main(String[] args){
final int MIN_SCORE ;
MIN_SCORE = 0;
final int MAX_SCORE = 100;
MAX_SCORE = 200; //非法
}
}
class A {
private final String INFO = "atyuyi"; //声明常量
public void print() {
//The final field A.INFO cannot be assigned
//INFO = "雨翼轻尘";
}
}
final
与static
搭配:修饰成员变量时(不能是局部变量,static不能修饰局部变量),此成员变量称为:全局常量
。(只有一个且不能改变)
这个变量兼具final和static的特点。
比如:Math的PI (直接通过类来调用且不能变)
在实际写代码的时候,若是在修饰类、修饰方法的时候忘记使用不碍事,但是修饰变量的时候记得加上,而且变量名要大写。
1、 final
的理解:最终的
2、final
可以用来修饰的结构:类、方法、变量(成员变量、局部变量)
3、具体说明:
final修饰类:表示此类不能被继承。
比如:String、StringBuffer、StringBuilder类
final修饰方法:表示此方法不能被重写
比如:Object类中的getClass()
final修饰变量:既可以修饰成员变量,也可以修饰局部变量。
此时的"变量"其实就变成了"常量",意味着一旦赋值,就不可更改。
final修饰成员变量: 有哪些位置可以给成员变量赋值?
> 显式赋值
> 代码块中赋值
> 构造器中赋值
final修饰局部变量:一旦赋值就不能修改
> 方法内声明的局部变量:在调用局部变量前,一定需要赋值。而且一旦赋值,就不可更改
> 方法的形参:在调用此方法时,给形参进行赋值。而且一旦赋值,就不可更改
4、 final
与static
搭配:修饰成员变量时,此成员变量称为:全局常量。
比如:Math的PI
排错
public class Something {
public int addOne(final int x) {
//return ++x; //不可以
return x + 1; //可以,x值没有变
}
}
排错
public class Something {
public static void main(String[] args) {
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o) {
// o = new Other();
o.i++; //让i++可以,因为i是变量,o不能变
}
}
class Other {
public int i;
}
局部变量o指向一个Other对象,Other对象里面有一个i,i没有用final修饰,表示它是一个变量。
将o加了一个final,意味着它的地址不能变了,而o指向的对象的属性可以变化。