JDK源码学习String篇中,有一处错误,String类用final【不能被改变的】修饰,而我却写成静态的,感谢CTO-淼淼的指正。

  风一样的码农提出的String为何采用final的设计,阅读JDK源码的时候,有粗略的思考过,今天下班后又把《Thinking in Java》中关于final的内容重新看了一遍,对此写下一些关于自己的理解和想法。

 String类中final关键字的使用

  final关键字,用来描述一块数据不能被改变,两种可能理由:设计、效率

  final使用的三种情况:数据、方法、类,final修饰类,类不能被继承,final修饰方法,方法不能被重载

  final对于基本类型的修饰,使得数值不能被改变,但是用于对象引用,虽然能保证初始化指定一个对象后,就无法指向其他对象,但是对象本身确实可以修改的。

, , };
a[] = ;

  数组使用final修饰,引用地址不可改变,但是数组的数据却可以改变。

  回过头来看String的源码设计中:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
}

  String本质上就是一个char数组,使用final修饰,虽然引用不可变,但是内容可变。

  所以 final char value[];无法保证String的不变性。

  这时候将 class String 使用final修饰,value[] 使用private授予私有访问权限。禁止String类被继承,防止被子类改写,从而保证String的不可改变,这是出于安全性的考虑。

  JAVA中参数传递的是传引用,所以多个变量可能指向的是同一个String,如果其中一个变量改变String的内容,另一个变量取到的是改变后的内容,不符合设计的初衷。

    public static String testStr(String s, String b) {
        s = b;
        b += ";
        return s;
    }

    public static void main(String[] args) {
        String s = new String("aaa");
        String b = new String("bbb");
        String ns = Test.testStr(s, b);
        System.out.println(s.toString());
    }

  关于效率的问题,涉及到JVM的处理机制,这一块不是很了解,以下内容节选自《Thinking in Java》

  在Java的早期实现中,如果将一个方法声明为final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。当编译器发现一个final方法调用命令时,它会根据自己的谨慎判断,跳过插入程序代码的这种正常方式而执行方法调用机制(将参数压入栈,跳至方法代码处并执行,然后跳回并清理栈中的参数,处理返回值),并且以方法体中的实际代码的副本来代替方法调用。这将消除方法调用的开销。

源码记:苦人所不苦,能人所不能,所谓成也
声明:原创博客请在转载时保留原文链接或者在文章开头加上本人博客地址,如发现错误,欢迎批评指正。  

JDK源码学习--String篇(二) 关于String采用final修饰的思考的更多相关文章

  1. JDK源码学习系列03----StringBuffer+StringBuilder

                         JDK源码学习系列03----StringBuffer+StringBuilder 由于前面学习了StringBuffer和StringBuilder的父类A ...

  2. JDK源码学习系列01----String

                                                     JDK源码学习系列01----String 写在最前面: 这是我JDK源码学习系列的第一篇博文,我知道 ...

  3. JDK源码学习系列02----AbstractStringBuilder

     JDK源码学习系列02----AbstractStringBuilder 因为看StringBuffer 和 StringBuilder 的源码时发现两者都继承了AbstractStringBuil ...

  4. JDK源码学习笔记——Enum枚举使用及原理

    一.为什么使用枚举 什么时候应该使用枚举呢?每当需要一组固定的常量的时候,如一周的天数.一年四季等.或者是在我们编译前就知道其包含的所有值的集合. 利用 public final static 完全可 ...

  5. JDK源码学习笔记——LinkedHashMap

    HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序. LinkedHashMap保证了元素迭代的顺序.该迭代顺序可以是插入顺序或者是访问顺序.通过维护一个 ...

  6. JDK源码学习系列05----LinkedList

                                             JDK源码学习系列05----LinkedList 1.LinkedList简介 LinkedList是基于双向链表实 ...

  7. JDK源码学习系列04----ArrayList

                                                                             JDK源码学习系列04----ArrayList 1. ...

  8. JDK源码学习--String篇(-)

    工作三年了,用了三年的JAVA,突然发现竟然没有好好的看下JDK的源码,整天用着的String,只是大概知道怎么回事,其中的实现逻辑却是一头雾水. 知耻而后勇,加油!!! java.lang.Stri ...

  9. JDK源码学习--String篇(四) 终结篇

    StringBuilder和StringBuffer 前面讲到String是不可变的,如果需要可变的字符串将如何使用和操作呢?JAVA提供了连个操作可变字符串的类,StringBuilder和Stri ...

随机推荐

  1. 利用PowerDesigner15在win7系统下对MySQL 进行反向project(二)

    利用PowerDesigner15在win7系统下对MySQL 进行反向project 1.打开PowerDesigner,建立新模型.选择Physical Data Model中的Physical ...

  2. HashMap 的遍历key与value的方法

    HashMap最经常使用的使用方法是依据key增删改查value,有时候会须要知道一个HashMap有多少个keys以及这些keys都是什么,能够用以下的代码实现. 方法1: Map map = ne ...

  3. ORA-01950: 对表空间 'NAMETABLESPACE' 无权限

    只要将Role下的Resource权限赋予给当前用户即可解决上述问题.

  4. the jar file rt.jar has no source attachment

    解决方法:rt的source在jdk目录的src.zip文件里,找到jdk目录下的src.zip,添加就行了.

  5. 状态压缩DP------学习小记

    状态DP主要用的还是DP思想,顾名思义,加了一个状态,主要是用来求状态个数的. 状态是用二进制数来表示的,也就是用0或1来表示,每一行有一个状态数,就是由这一行的0或1组成的,首先我们要获得每行的状态 ...

  6. Java学习之finally关键字总结

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  7. GET方式URL乱码问题解决

      打开 tomcat/conf/server.xml 查找下面这部分,在最后增加一段代码就可以了. <Connector port="80" maxHttpHeaderSi ...

  8. C语言Printf格式

    使用printf打印时发现,如果数据类型和打印使用的类型不一致,结果就是混乱的. 这是因为printf本身并不进行数据的类型转换,他只是把输入按照给定的数据格式输出,如果二者不匹配,那么由于不同数据类 ...

  9. linux搭建php

    http://www.cnblogs.com/wubaiqing/archive/2011/11/08/2241195.html 四,启动php-fpm & Nginx /usr/local/ ...

  10. RMA编码为必输

    应用 Oracle Inventory 层 Level Function 函数名 Funcgtion Name RCV_RCVTXERE 表单名 Form Name RCVTXERE 说明 Descr ...