[疯狂Java]面向对象:final修饰符(修饰变量、方法、类)

1. final修饰变量:

    1) 当final修饰变量时,其功能类似C++的const,有不可变的意思(类似常量),但是其用法比C++的const灵活地多,功能也更丰富;

    2) 用final可以修饰任何变量(成员变量、静态成员变量、局部变量等);

    3) final变量的三大规则:

         i. 定义和初始化可以分开:final不像C++的const必须在定义变量的同时给出初始值,final的规则是:final变量一旦获得初始值就不可改变;

!!也就是说在定义一个final变量的时候可以不给定初始值,一旦在后面获得初始值后就不可改变(即定义final变量和给定初始值可以分开进行);

         ii. final变量的初始值不一定是编译时就能确定的值,也可以是运行时才确定的值!

             a. C++的const变量要求必须用编译时就能确定的值来初始化,说白了就是用一个字面值(常量)对const变量进行初始化!

             b. Java的final变量除了允许用编译时确定的值来初始化之外还允许用一个运行时才能确定的值来初始化final变量(例如用另一个变量去初始化final变量,也可以用一个方法的返回值来初始化final变量!)

public class Test {
	
	
	private final int a;
	
	private int createVal(int val) {
		return val + 17;
	}
	
	public Test(int val) { // 并且这里的final变量是定义和初始化分开的
		this.a = createVal(val); // 彻彻底底地运行时才能确定的值来初始化final变量
	}
...
}
         iii. 任何final变量系统都不会为其提供默认值初始化值(二进制0),也就是说必须要由用户自己显式地对final变量进行初始化!!否则就会编译报错!强制要求你显式初始化!


2. final局部变量的初始化:系统同样不会隐式给出默认值,必须自己显式初始化

    1) 必须要在该局部变量的作用域内、其第一次使用之前完成对其显式初始化,否则就会编译报错,强制要求你初始化;

    2) 特例:final也可以修饰方法形参,而方法形参的初始化是方法调用实参传形参时隐式完成的,在这种情况下就无需再在方法体中对final形参初始化了!

!例如:public void func(final int a) { System.out.println(a); } // 无需再初始化,传参的过程就是隐式的初始化过程


3. final成员变量的初始化:系统同样不会隐式给出默认值,必须自己显式初始化

    1) 对于静态成员,就必须在使用静态final成员之前必须完成初始化,因此必须在创建类时完成初始化,也就是说必须在静态初始化代码中完成初始化;

!!初始化必须在静态初始化块和直接默认值之间二选一,不能重复,这是显然的;

    2) 对于非静态成员,也必须在使用该成员之前完成初始化,因此必须在创建对象的时候完成初始化,也就是说必须在初始化代码或构造器中完成初始化;

!!初始化必须在直接默认值、初始化块、构造器中三选一,不能重复,这也是显然的!

4. final宏:

    1) 如果一个变量符合这三个条件,那它既是一个final宏(即一种特殊的final变量):

         i. 是一个final变量;

         ii. 定义变量时就初始化;

         iii. 初始化值是编译时就可确定的(即用一个常量初始化);

    2) 那么该变量出现的地方都会用其初始化它的那个常量进行宏替换(该常量肯定放在常量池中管理)!

    3) 例如:final int a = 5;  // 后面所有出现a的地方都用字面值5替换(编译之前预处理之后进行宏替换);

    4) 只要是编译时就能确定的就行,例如:final int a = 5 + 1;   final String s = "lala" + "haha";  或者final int a = 5; final String s = a + "lala";  // 其中a会进行宏替换成5,因此s的初始化值也是编译时就能确定的!

    5) 如果用一个非final宏的变量或者任何函数调用来初始化就不是编译时就能确定了,此时的final变量就不是一个final宏!

    6) 一个典型示例:

String a = "lalahaha";
String b = "lala";
String c = "haha";
String d = b + c;
out.println(a == d); // false

String a = "lalahaha";
final String b = "lala";
final String c = "haha";
String d = b + c;
out.println(a == d); // true


5. final方法:

    1) 用final修饰过的方法表示不能被子类重写,如果重写则编译报错!

    2) 但不过对于父类的private方法,由于其子类是不可见的,因此子类即使“重写”,那也是定义了一个新的方法而已,因此子类可以“重写”父类的final方法(其实是定义了一个新的方法而已);

    3) final方法是指不能被子类重写,但是仍然可以被重载的!!

!!重载是平行的,重写是垂直的;

    4) Object的getClass方法就是final方法,是一种即为基础的通用方法(是一个调用C语言的本地方法);


6. final类:被final修饰过的类表示不能被继承!否则会编译报错!!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值