String的这些知识你真的知道?

年纪越大越发现知识要系统性的学习,接下来我们聊下面试中经常被问到的String相关的问题。

一. String 是基本数据类型?占多少字节数?

String 是引用数据类型

   // 下面两种定义方法
   String str = null;
   String str = new String("hello");

不管你怎么定义,String都是引用数据类型。下面我们来列举下java的两种数据类型。


image.png

String 全称是 java.lang.String,是java的一个类,是引用数据类型。
通过查看String源码我们知道,String里面是一个char 数组。 而一般一个char字符默认占一个字节。
那么如果字符串里面有中文,具体占几个字节呢?

        String str = "小叶檀";
        char[] chars = str.toCharArray();
        byte[] bytes = str.getBytes();
        System.out.println("字符串转换成字符数组为:"+ Arrays.toString(chars));
        System.out.println("字符串所占字节数:"+Arrays.toString(bytes));
        // 运行结果为
        字符串转换成字符数组为:[小, 叶, 檀]
        字符串所占字节数:[-27, -80, -113, -27, -113, -74, -26, -86, -128]

从运行结果可以知道,中文是占两个字节

二. 为什么说String是不可变的? 为什么会被设计成不可变? 真的不可变?

我们来看看java.lang.String的源码

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

    /** Cache the hash code for the string */
    private int hash; // Default to 0
}
  1. 为什么不可变?

String类 是一个被final修饰的类,里面是一个被final修饰的私有的字符数组。我们知道,被final修饰的类不能被继承,被final修饰的变量不能被重新赋值。另外,也没发现对于这个字符数组的setter()和getter()。所以说String是不可变的。

  1. 为什么会被设计成不可变?

看String源码我们发现有一个hash属性,上面注释说缓存的String的hashcode值。所以我们联想如果String是可变的,那么是不是每次改变都要重新计算hashcode,这样会很消耗性能。平时我们会使用String来存储数据库连接等关键变量,如果是可变的,那么是不是对于程序来说很不安全,万一被注入了呢?
所以String设计成不可变是在安全和性能上考虑的。

  1. 真的不可变?

不是的,我们可以通过反射机制来改变String的值。

    public static void main(String[] args) {
        String str = "hello";
        System.out.println("更新前:"+str);  // hello
        try {
            // 获取到String里面的私有属性value
            Field field = String.class.getDeclaredField("value");
            // 指定属性的访问权限为true
            field.setAccessible(true);
            // 修改值
            char[] value = (char[])field.get(str);
            value[1]='x';
            System.out.println("更新后:"+str); // hxllo
        }catch (NoSuchFieldException ex){
            ex.printStackTrace();
        }catch (IllegalAccessException e){
            e.printStackTrace();
        }
    } 
三. String的equals()和== 区别

equals() 比较对象里面的值,== 比较内存地址。

考虑到String的不可变,每次new就是新建一个对象放到堆里面,这样太耗内存、性能也不好。 为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。为 了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串常量池。

jdk1.6及以前字符串常量池放在方法区里面。jdk1.7 常量池被挪到堆里面,应该是考虑到这个池子会比较大,方法区太小。

        String s1 = "abc";
        String s2 = "abc";
        System.out.println(s1==s2);  // true

        String s3 = new String("abc");
        String s4 = new String("xyz");
        System.out.println(s1==s3);    // false
        System.out.println(s1==s3.intern());    // true

当我们用双引号直接定义一个字符串时,jvm会先去检查字符串常量池中是否存在,如果不存在会在常量池里面创建一个String 对象,如果存在会直接引用。

intern() 是native方法,返回字符串对象的规范化表示形式,也就是把对象转化成字符串常量。可以联想下,当我们调用intern(),jvm会去字符串常量池查找或创建一个当前字符串对象的引用。

四. String a = new String("hello") 创建了几个对象?

存在两个对象。 当我们使用new的这种方式来创建一个字符串时,首先会在堆创建一个对象,然后去字符串常量池里面去查找,如果找到就引用,没有就在常量池里面创建一个。

五. String 是被哪个加载器加载的?自定义的String可以被加载?

java.lang.String会被顶级类加载器Bootstrap Classloader 加载。

自定义的String不会被加载。安装jvm的双亲委派原则,当加载到一个新类,加载器会默认让它的父类去加载,当父类返回无法加载时,AppClassLoader 才会加载。所以当加载到String时,AppClassLoader默认会把加载权让给其父类ExtClassLoader,
但是ExtClassLoader在jre/lib/ext目录下没有找到String.class类。接着又会把加载权让给其父类BootStrap ClassLoader,
BootStrap在JRE/lib目录的rt.jar找到了String.class,将其加载到内存中。

六. String, Stringbuffer, StringBuilder 的区别

首先它们都是final类,不能被继承。

String 是字符串常量;
Stringbuffer 是 字符串缓冲池,读写都使用了synchronized来实现线程安全;
StringBuilder 效率最快,但是线程不安全。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容

  • 从网上复制的,看别人的比较全面,自己搬过来,方便以后查找。原链接:https://www.cnblogs.com/...
    lxtyp阅读 1,308评论 0 9
  • String 是Java编程中的引用类型,不属于基本类型,默认值为null,在Java中是用来创建于操作字符串。源...
    小杰的快乐时光阅读 523评论 0 1
  • 前言 RTFSC (Read the fucking source code )才是生活中最重要的。我们天天就是要...
    二毛_coder阅读 424评论 1 1
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,333评论 0 4
  • 注:都是在百度搜索整理的答案,如有侵权和错误,希告知更改。 一、哪些情况下的对象会被垃圾回收机制处理掉  当对象对...
    Jenchar阅读 3,145评论 3 2