java中的关键字——final

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/fengyu_xueer/article/details/80630484

参考来源:https://mp.weixin.qq.com/s/FoQXksfXlTPvboWRMstvjA

说明:本文部分内容参考自上述文章,在上述文章的基础上做了一定的删减修改,如有侵权请联系删除。

1.final关键字的基本用法

修饰类

  • 用final修饰一个类时,这个类不能被继承
  • final类中的成员变量可以根据需要设为final,但是final类中的所有成员方法都会被隐式地指定为final方法。
public final class Animal {
    public Animal(){

    }
}

这里写图片描述

开发中,尽量不要将类设计为final类,除非处于安全考虑或者保证该类一定不会被继承了。

修饰方法

  • final修饰的方法不能被覆盖
  • 类的private方法会隐式地被指定为final方法

修饰变量

  • final修饰变量时,如果是基本数据类型的变量,则数值一旦在初始化之后便不能更改
  • 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

这里写图片描述

如图:上述代码对a和o的重新赋值都被提示出错。

2.知识点

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

public class Aniaml {
    public static void main(String[] args)  {
        final MyAnimal myAnimal = new MyAnimal();
        System.out.println(++myAnimal.i); //输出结果:1
    }
}

class MyAnimal {
    public int i = 0;
}

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

final和static

  • 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值不同

匿名内部类中使用的外部局部变量只能是final变量
final参数问题

public class Test {
    public static void main(String[] args)  {
        MyAniaml myAniaml = new MyAniaml ();
        int i = 0;
        myAniaml.changeValue(i);
        System.out.println(i);
    }
}

class MyAniaml { 
    void changeValue(final int i) {
         i++; //该行会报错,提示:不能对i进行赋值
    }
}

上面这段代码好像让人觉得用final修饰之后,就不能在方法中更改变量i的值了。殊不知,方法changeValue和main方法中的变量i根本就不是一个变量,因为java参数传递采用的是值传递,对于基本类型的变量,相当于直接将变量进行了拷贝。所以即使没有final修饰的情况下,在方法内部改变了变量i的值也不会影响方法外的i。

public class Test {
    public static void main(String[] args)  {
         MyClass myClass = new MyClass();
         StringBuffer buffer = new StringBuffer("hello");
         myClass.changeValue(buffer);
         System.out.println(buffer.toString());
    }
}

运行这段代码就会发现输出结果为 helloworld。很显然,用final进行修饰并没有阻止在changeValue中改变buffer指向的对象的内容。有人说假如把final去掉了,万一在changeValue中让buffer指向了其他对象怎么办。有这种想法的朋友可以自己动手写代码试一下这样的结果是什么,如果把final去掉了,然后在changeValue中让buffer指向了其他对象,也不会影响到main方法中的buffer,原因在于java采用的是值传递,对于引用变量,传递的是引用的值,也就是说让实参和形参同时指向了同一个对象,因此让形参重新指向另一个对象对实参并没有任何影响。

猜你喜欢

转载自blog.csdn.net/fengyu_xueer/article/details/80630484