Java中final关键字的使用及分析

final关键字的使用:

1、final是java语言中的一个关键字,是一个访问修饰符;

2、final表示最终的,不可改变的;

3、final可以修饰类,变量以及方法等;

4、final修饰的类有什么用?来看下面代码:

final class Animal {

}

class Cat extends Animal {

}

编译结果:无法从最终Animal进行继承。

结论:final修饰的类无法被继承。


5、final修饰的方法有什么作用?来看下面代码:

public class Test {
    public static void main(String[] args) {
        Cat c1 = new Cat();
        c1.doSome();
    }
}

class Animal {
    public final void doSome() {
        System.out.println("Animal的doSome()方法执行!");
    }
}

class Cat extends Animal {
    public void doSome() {
        System.out.println("Cat的doSome()方法执行!");
    }
}

编译结果:Cat中的doSome()无法覆盖Animal中的doSome(),被覆盖的方法为final。

结论:final修饰的方法无法被覆盖。


我们来分析一下以下问题:

(1)final修饰的类为什么不能被继承?
答:因为子类去继承父类,进行方法覆盖时,甚至要添加父类中没有的东西,显然会去修改继承过来的父类,而final修饰的类不能被修改。

(2)final修饰的方法为什么不能被子类覆盖(即不能被重写)?
答:因为子类覆盖父类的方法的目的:就是去修改,重新写一份父类的方法。而父类的final修饰的方法不能被修改。


6、final修饰的变量有什么作用?
经过上面的练习,我们来猜一下。
很多人可能以为是:final修饰的变量不能被继承。
从上面两个例子来看好像很对,其实这是错误的,实际上final修饰的变量可以被子类继承并访问。

我们来看如下代码:

public class Test {
    public static void main(String[] args) {
        Cat c1 = new Cat();
        c1.doSome();
    }
}

class Animal {
    public final String name = "动物";

    public void doSome() {
        System.out.println("Animal的doSome()方法执行!");
    }
}

class Cat extends Animal {
    public void doSome()  {
        System.out.println(name);
        //name = "猫";  //不允许修改
        System.out.println("Cat的doSome()方法执行!");
    }
}

编译并运行结果:
动物
Cat的doSome()方法执行!

我们发现子类能继承并访问父类的final变量。如果在子类中去修改父类的final变量,才是不允许的,编译失败。


好的,我们再来看一个局部变量的例子:

public class Test {
    public static void main(String[] args) {
        final int i = 100;
        i = 200;
    }
}

编译结果:无法为最终变量i分配值。

所以说final修饰的变量并不是限制成不能继承,而是不能修改。


上面的代码中父类的实例变量name是这样定义的:

public final String name = "动物";

那么name永远都是“动物”这个值,因为它不能变。构造方法中也不能再对它进行修改赋值。
如果我把实例变量name定义成这样的:

public final String name;

那么在构造方法中就一定要手动给它赋值,因为实例变量name的第一次赋值就是在构造方法执行。Java中系统不会给final修饰的值赋默认值,这个“锅”sun公司甩得好,特意不去给“只能赋一次值的实例变量”赋值,让我们自己手动去给实例变量赋我们想要的值。

如果final修饰的是一个静态变量,会怎么样?如下:

class People {
    public static final String guoji;
}

我们会发现编译报错:可能尚未初始化变量guoji。

那么我们想一下静态成员变量的初始化时机是在什么时候,对的,类加载时候初始化静态变量,保存在方法区,所有该类实例共用这一份静态变量。

所以final修饰的静态变量定义时就应该立马赋值,且后期不可更改,如下:

class People {
    public static final String GUOJI = “China”;
}

当一个类所有对象的一个变量都相同时,我们使用static final来修饰,我们又称:static final修饰的变量称为“常量”。常量名建议全部大写,每个单词之间采用下划线连接。例如:COUNTRY(国籍),PI(圆周率)。显然常量不用封装,为什么?因为外部改不了它的值。


如果final修饰的是一个引用变量,会怎么样?
看以下代码:

public class Test {
    public static void main(String[] args) {
		//p1被final修饰
        final Person p1 = new Person(20);
        p1.age = 30;
        p1 = new Person(30); //此行编译报错
    }
}

class Person {
    public int age;

    public Person() {
    }
    public Person(int age) {
        this.age = age;
    }
}

我们发现,final修饰的引用变量p1,你可以修改p1对象内部的属性,但你不可以用p1接收新的对象。从而进一步验证了p1保存的是“0x1234(堆内存对象的地址)”,你可以修改final p1对象内部的属性,但你不可以修改p1本身的值。所以说“final 变量”一旦赋值,不可修改。

而你需要知道实例变量,静态变量,引用变量,局部变量,这些变量的第一次初始化时机分别是在什么时期,它们只能在这些时机内赋第一次值,后期不可更改。


总结:

1、final意为“最终的,不可改变的”。

2、final修饰的类不能被继承。

3、final修饰的方法不能被重写覆盖。

4、final修饰的变量一旦赋值,后期不能赋值修改。

5、final修饰的引用一旦指向某个对象,则不能再重新指向其他对象,但该引用对象内部的数据是可以修改的。

6、final修饰的实例变量必须手动初始化,不能让系统默认初始化。

7、final修饰的实例变量一般和static联合修饰使用,这种变量称为常量。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值