Java中的Final关键字,区分基本数据类型与引用类型,值传递与引用传递

Final可以声明成员变量、方法、类以及本地变量。一旦你将引用声明作final,你将不能改变这个引用了。对于基本数据类型声明为Final后其值无法再次改变,对于引用类型,可以改变改引用的内容,但是无法改变这个引用,即不能再次指向新的引用地址,也就是重新赋值,new一个新的对象。

首先我们来看看基本数据类型与引用类型的区别:

这里写图片描述
如上如所述;
对于基本类型,变量中保存的是其值。对于引用类型,变量中保存的只是实际对象的地址。一般称这种变量为”引用”,引用指向实际对象,实际对象中保存着内容。
引用类型的变量(实际对象的地址)是保存在栈中的,引用所指向的实际对象是保存在堆中的。所以说基本类型保存在栈中,引用类型保存在栈中。

这里写图片描述
对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。
对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变(重要)。
如上图所示,”hello” 字符串对象没有被改变。(没有被任何引用所指向的对象是垃圾,会被垃圾回收器回收)

关于值传递与引用传递

首先看看什么是按值传递,什么是引用传递。
按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本。
按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本。.

个人的理解是:Java中只有值传递
当参数是基本数据类型时传递的是变量的值,当参数是引用类型的时候传递的是引用地址(栈中保存的引用变量地址)。
String,Integer, Double等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待。可以认为是传值。
Integer 和 String 一样。保存value的类变量是Final属性,无法被修改,只能被重新赋值/生成新的对象。 当Integer 做为方法参数传递进方法内时,对其的赋值都会导致 原Integer 的引用被 指向了方法内的栈地址,失去了对原类变量地址的指向。对赋值后的Integer对象做得任何操作,都不会影响原来对象。

final关键字的好处

下面总结了一些使用final关键字的好处
final关键字提高了性能。JVM和Java应用都会缓存final变量。
final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
使用final关键字,JVM会对方法、变量及类进行优化。

关于final的重要知识点

final关键字可以用于成员变量、本地变量、方法以及类。
final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。
你不能够对final变量再次赋值。
本地变量必须在声明时赋值。
在匿名类中所有变量都必须是final变量。
final方法不能被重写。
final类不能被继承。
final关键字不同于finally关键字,后者用于异常处理。
final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。
接口中声明的所有变量本身是final的。
final和abstract这两个关键字是反相关的,final类就不可能是abstract的。
final方法在编译阶段绑定,称为静态绑定(static binding)。
没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。
将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。
按照Java代码惯例,final变量就是常量,而且通常常量名要大写:

public class TestFinal {

    public static void main(String[] args) {
        StringBuilder str = new StringBuilder("test");
        System.out.println(testFinal(str));
        Student stu = new Student(20, "xfl");
        System.out.println(testFinal(stu));
        Map<String,String> map = new HashMap<String, String>();
        map.put("final", "final");
        System.out.println(changeValue(map).get("final"));
        System.out.println(change(map).get("final"));
        System.out.println(map.get("final"));
    }
    public static StringBuilder testFinal(final StringBuilder str){
        //改变str的内容 但是无法改变str所指向的引用 ,也就是str不能指向新的引用地址
        str.append("Fianl");
        return str;
    }

    public static int testFinal(final int tmp){
        //这里无法改变tmp的值
        return tmp;
    }
    public static Student testFinal(final Student stu){
        //可以改变内容  但是不能让其指向一个新的对象
        stu.age = 21;
        return stu;
    }
    public static Map<String,String> changeValue(final Map<String,String> map){
        map.put("final", "alredyChange");
        return map;
    }
    public static Map<String,String> change(Map<String,String> map){
        //改变了引用地址所指向的内容
        map.put("final", "alredyChange");
        //改变了map的引用  指向了一个新的对象
        map = new HashMap<String, String>();
        map.put("final", "newMap");
        return map;
    }
    public static void changInt(Integer a){
        //这里相当与创建了一个新的对象
        a = 6;
    }
    static class Student{
        private int age;
        private String name;
        public Student(int age,String name) {
            this.age = age;
            this.name = name;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public int getAge() {
            return age;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        @Override
        public String toString() {
            return "age:"+ age +" name: " +name;
        }
    }

}

参考资料:
https://www.zhihu.com/question/31203609
http://www.importnew.com/7553.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值