final,見名知意,就是最終的意思,那麼它在java中可以修飾什麼呢?又有什麼作用呢?
一、final的使用
在java中,final可以修飾變量,方法,類。
1.1 final修飾變量
當變量被final修飾時,那麼此時的變量也就稱之爲常量。當一旦final修飾的變量被初始化後,那麼值(數值和引用地址值)將不能再被改變。
1.1.1 final修飾成員變量
當final修飾成員變量時,必須要顯式初始化,也就是你必須要給它賦個值。
那麼有哪些方式可以賦值呢?
1.1.1.1 成員變量爲基本類型時
當成員變量爲基本類型時,那麼此時被final修飾的它們,一旦初始化後,數值將不可改變。
public class Demo {
public static void main(String[] args) {
Box b1=new Box();
System.out.println(b1);
System.out.println("=================");
Box b2=new Box(20);
System.out.println(b2);
}
}
class Box{
//Variable 'length' might not have been initialized
//final int length;
//一般對於常量,我們都全大寫表示,爲了演示方便,就不用了
//final int LENGTH=0;
final int length=5; //聲明時初始化
final int width; //代碼塊中初始化
final int height; //構造器初始化
{
//Cannot assign a value to final variable 'length':不能將值賦給最終變量length
//length=10;
}
//代碼塊初始化
{
width=10;
}
public Box() {
this.height = 15;
}
public Box(int height) {
this.height = height;
}
@Override
public String toString() {
return "Box{" +
"length=" + length +
", width=" + width +
", height=" + height +
'}';
}
}
輸出:
Box{length=5, width=10, height=15}
=================
Box{length=5, width=10, height=20}
通過上例代碼,我們可以發現,當成員變量被final修飾時,我們可以通過聲明初始化,代碼塊,構造器,爲final修飾的成員變量進行賦值初始化操作,而在初始化後值將不能再改變
1.1.1.2 成員變量爲引用類型
class Duck{
private String name;
public Duck() {
}
public Duck(String name) {
this.name = name;
}
}
class Dog {
private String name;
public Dog(String name) {
this.name = name;
}
//getter方法
public String getName() {
return name;
}
}
class Cat {
private String name;
public Cat(String name) {
this.name = name;
}
//getter方法
public String getName() {
return name;
}
}
class Mouse {
private String name;
public Mouse(String name) {
this.name = name;
}
//getter和setter方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Box {
Duck duck=new Duck();
final Dog dog = new Dog("Speike"); //聲明初始化
final Cat cat; //代碼塊初始化
final Mouse mouse; //構造器初始化
//代碼塊初始化
{
cat = new Cat("Tom");
}
//代碼塊初始化
{
duck=new Duck("唐老鴨");
//Variable 'dog' might already have been assigned to
//dog = new Dog("大黃"); //編譯不通過
}
//無參構造初始化
public Box() {
mouse = new Mouse("Jerry");
}
//有參構造初始化
public Box(Mouse mouse) {
this.mouse = mouse;
}
@Override
public String toString() {
return "Box{" +
"dog地址值:" + System.identityHashCode(dog) +
",dog值:" + dog.getName() +
", cat地址值:" + System.identityHashCode(cat) +
", cat值:" + cat.getName() +
", mouse地址值:" + System.identityHashCode(mouse) +
", mouse值:" + mouse.getName() +
'}';
}
}
public class Demo {
public static void main(String[] args) {
Box box=new Box();
System.out.println(box);
System.out.println("========================================分割線==============================================");
Mouse mouse = new Mouse("米老鼠");
Box b1 = new Box(mouse);
System.out.println("修改前:"+b1);
//修改mouse的值
mouse.setName("傑瑞");
System.out.println("修改後:"+b1);
}
}
輸出:
Box{dog地址值:460141958,dog值:Speike, cat地址值:1163157884, cat值:Tom, mouse地址值:1956725890, mouse值:Jerry}
========================================分割線==============================================
修改前:Box{dog地址值:356573597,dog值:Speike, cat地址值:1735600054, cat值:Tom, mouse地址值:21685669, mouse值:米老鼠}
修改後:Box{dog地址值:356573597,dog值:Speike, cat地址值:1735600054, cat值:Tom, mouse地址值:21685669, mouse值:傑瑞}
在上例中,我們在Box中初始化無final修飾的Duck和有final修飾的Dog,Cat,Mouse。通過比較我們可以發現,final修飾的引用類型的成員變量亦是可以通過聲明,代碼塊,構造器進行初始化,並且比較Duck和Dog後,還可以發現,final修飾的引用類型的成員變量在第一次初始化後,不可以被再次賦值,而Duck沒被final修飾,則沒有此限制。
接着我們在main方法中創建了一個mouse對象和b1對象,然後我們打印了下b1對象,接下了我們修改了mouse的name值,接着再次進行打印。比較一下修改前後的打印的值,發現在將mouse值由米老鼠修改成傑瑞時,他們的mouse對象的地址值並沒有改變。由此我們可以確認,final修飾引用類型的成員變量時,在將它們初始化後,將不能再指向其他對象,但它們所指向對象的內容卻是可以修改的。
1.1.2 final修飾局部變量
當使用final修飾局部變量時,在初始化後,將不可給它們再次賦值,也就是說,在第一次賦值後,它們的值(無論是數值還是地址值)都將不能改變。
1.1.2.1 局部變量類型爲基本類型
public class Demo{
public static void main(String[] args) {
Box box=new Box();
box.show(10);
}
}
class Box{
public void info(){
final int ID=10;
//ID=10; //Cannot assign a value to final variable 'ID'
}
public void show(final int price){
//Cannot assign a value to final variable 'price'
//price=10;
System.out.println(price);
}
}
輸出:
10
通過上例,我們可以發現在final修飾基本類型的局部變量(參數列表也是局部變量)時,數值在第一次賦值後將不能再被改變。
1.1.2.2 局部變量類型爲引用類型
class Box {
public void info() {
final Gift gift=new Gift();
//Cannot assign a value to final variable 'gift'
//gift=new Gift();
}
public void showFinal(final Gift gift){
//Cannot assign a value to final variable 'gift'
//gift=new Gift();
System.out.println(gift);
}
public void show(Gift gift){
gift=new Gift();
System.out.println(gift);
}
}
在上例,final修飾的引用類型的局部變量在初始化後,會發現不能改變它們指向的引用地址值了。
1.2 final修飾方法
當方法被final所修飾時,那麼這個方法將不能被重寫(覆蓋)。
class Animal{
final void info(){
}
}
class Cat extends Animal{
//'info()'cannot override 'info()'in 'Animal';overridden method is final
//info()方法不能被重寫
// void info() {
// super.info();
// }
}
1.3 final修飾類
當類被final所修飾時,那麼這個類將不會被其他類所繼承。
public class Demo {
public static void main(String[] args) {
Animal cat=new Animal();
cat.name="Tom";
cat.info();
}
}
final class Animal{
String name;
final int age=1;
void info(){
System.out.println(name+":"+age+"歲");
}
}
//Cannot inherit from final 'Animal' //無法繼承最終類A
//class Cat extends Animal{
//
//}
輸出:
Tom:1歲
上述代碼中,當類Animal被final修飾後,Cat類將不可以繼承Animal類,這時編譯是不會通過的,理所當然的,既然類不能被繼承,那麼類中的方法自然也不會被重寫(覆蓋)。對於屬性name,age可以發現在最終類Animal中,屬性可以爲final所修飾,也可以不被final修飾。
在java中也有許多類被final修飾,比如說:String類,System類等等。它們都不能被繼承。
二、總結
通過以上可以總結出:
final可以修飾變量,方法,類。
當final修飾變量時,此時的變量被稱爲常量。當變量經過初始化後,它們的數值或者引用地址值是不能再次改變的。
- final修飾成員變量:成員變量爲基本數據類型時,在初始化後,就不能改變數值了。成員變量爲引用數據類型時,在初始化後,成員變量就不能指向其他的對象了。對於初始化,成員變量可以通過聲明初始化,代碼塊初始化,構造器初始化三種方式。
- final修飾局部變量:局部變量在初始化後,它的數值或引用地址值將不能改變。
final修飾方法:當方法被final修飾時,將不能被重寫。
final修飾類:當類被final修飾時,將不能被繼承,而由此方法也必定不會被重寫。
最後:static關鍵字可以和final連用。可以用來修飾屬性和方法()。
當修飾屬性時,此時變量爲全局常量,並且它在類的加載時就會初始化。