Java中的final关键字整理笔记

final关键字可以修饰成员变量,方法,以及本地变量。如果将引用声明为finall类型,那么该引用就不会再被改变,被final修饰之后,就是一个不可变的东西。

final变量

final修饰的变量(成员变量和局部变量)都称作为final变量,其存储在常量池当中。final变量经常和static关键字一起使用,作为常量。

final修饰的变量,只能进行一次赋值操作,并且整个生命周期中不可改变。

不过在针对基本类型和引用类型时,final关键字的效果有细微差别:

class Value {
    int v;
    public Value(int v) {
        this.v = v;
    }
}

public class TestFinal {
    final int f1 = 1;          
    // value1 = 4;        //无法再为value1赋值
    
    final int f2;

    public TestFinal() {
        f2 = 2;
    }
    public static void main(String[] args) {
        final int value1 = 1;
        final double value2;
        value2 = 2.0;
        
        final Value value3 = new Value(1);
        value3.v = 4;
    }
}

value3是一个引用变量,final修饰的引用变量,限定了引用变量的值不可变,即不能把value3再次引用一个Value对象,但是引用对象的值是可以改变的。

另一方面,因为final修饰的数据的值不可改变,所以必须在使用前就已经对其赋值。有两种方法:

  • 声明时直接赋值
  • 构造方法中赋值

最后要注意: 同时使用staticfinal修饰的成员在内存中只占据一段不可改变的存储空间。

final方法参数

很多时候,我们把变量作为参数传递时,会要求传过去的值不会改变。于是就会用final来修饰了。即在参数前面添加final关键字即可,它表示整个方法中,不改变参数的值。

public void finalFunc(final int i,final Value value){
    //i=5;     //error,不能改变i的值
    //value=new Value();   //error,不能改变该引用的值
    value.v=111;           //可以改变引用对象的值
}
final方法

final修饰的方法,代表该方法不可被子类重写。若你认为一个方法的功能已经足够完整了,子类中不需要改变的话,可以声明此方法为finalfinal方法比非final方法要快,因为在编译的时候已经静态绑定了,不需要在运行时再动态绑定。关于privatefinal关键字还有一点联系就是类中所有的private方法都隐式地指定为是final的,由于无法在类外使用private方法,所以也就无法覆盖它。下面是final方法的例子:

class PersonalLoan {
    public final String getName() {
        return "personal loan";
    }
}

class CheapPersonalLoan extends PersonalLoan {
    @Override
    public final String getName() {
        return "cheap personal loan"; // compilation error: overridden method is final
    }
}
final

使用final来修饰的类叫作final类。final类通常功能是完整的,它们不能被继承.java中有许多类是final的,譬如String, Interger以及其他包装类。下面是final类的实例:

final class PersonalLoan{

}

class CheapPersonalLoan extends PersonalLoan{ //compilation error: cannot inherit from final class
final关键字优点
  • 提高了性能,JVMjava应用都会缓存final变量
  • final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
  • 使用final关键字,JVM会对方法、变量及类进行优化。

创建不可变类要使用final关键字。不可变类是指它的对象一旦被创建就不能被更改。String是不可变类的代表。不可变类有很多好处,譬如它们的对象是只读的,可以在多线程环境下安全的共享,不用额外的同步开销

几个易混点

1.类的final变量和普通变量有什么区别

当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再被赋值了。

public class Test {
    public static void main(String[] args) {

        String a = "hello2";
        final String b = "hello";
        String d = "hello";
        String c = b + 2;
        String e = d + 2;
        System.out.println((a == c));  //true
        System.out.println((a == e));  //false
    }
}

得出的结果就是final变量和普通变量的区别,当final变量是基本数据类型以及String类型时,如果在编译期间能知道其确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。这种和C语言中的宏替换有点像。

因此上面一段代码中,由于变量b被final修饰,因此会被当做编译器常量,所以在使用到b的地方会直接将变量b 替换为它的 值。而对于变量d的访问却需要在运行时通过链接来进行。不过要注意,只有在编译期间能确切知道final变量值的情况下,编译器才会进行这样的优化,比如下面的这段代码就不会进行优化:

public class Test {
    public static void main(String[] args) {
        String a = "hello2";
        final String b = getHello();
        String c = b + 2;
        System.out.println((a == c));   //false
    }
    public static String getHello() {
        return "hello";
    }
}

2. 被final修饰的引用变量指向的对象内容可变吗

public class Test {
    public static void main(String[] args) {
        final MyClass myClass = new MyClass();
        System.out.println(++myClass.i);  //输出为 1
    }
}

class MyClass {
    public int i = 0;
}

说明引用变量被final修饰之后,虽然不能再指向其他对象,但是它指向的对象的内容是可变的。

3.finalstatic

很多时候会容易把staticfinal关键字混淆,static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。

public class Test {
    public static void main(String[] args) {
        MyClass myClass1 = new MyClass();
        MyClass myClass2 = new MyClass();

        System.out.println(myClass1.i);

        System.out.println(myClass1.j);

        System.out.println(myClass2.i);

        System.out.println(myClass2.j);
	}
}

class MyClass {
    public final double i = Math.random();

    public static double j = Math.random();
}

运行这段代码就会发现,每次打印的两个j值都是一样的,而i的值却是不同的。从这里就可以知道finalstatic变量的区别了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一倾而尽

你的鼓励将是我最大的动力,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值