写了那么久的String字符串,你可能根本不懂它!

人生处万类,知识最为贤。这篇文章主要讲述写了那么久的String字符串,你可能根本不懂它!相关的知识,希望能为你提供帮助。
(一)引言String str和new String()有什么区别?这个问题之前在面试中有被问到过一次,当时面试结束后也写了自己关于这个题目的理解,不过最近在看Effect java的时候发现书中也提到了关于String的用法,刚好就放到一起聊一下。
(二)关于String字符串String应该是Java中最常用的一个对象,他不是八种基本数据类型的其中之一,但是我随便翻了一下项目代码,用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 }

【写了那么久的String字符串,你可能根本不懂它!】关于String的几个基本知识点在String类的源码定义中就能看到:
1、在JDK8中,String实例的值是通过char数据存储的。(JDK9时,String实例的存储由char变成了byte数组,原因是使用byte数组可以减少一半的内存)
2、String类被final修饰,因此String不能被继承,value变量被final修饰,因此String实例不能被修改
3、String类实现了Serializable, Comparable, CharSequence接口。
(三)关于字符串常量池字符串常量池是虚拟机中的内容,但是接下来的几个问题需要用到,就简单了解下。为了让String字符串可以复用,Java虚拟机中设置了一种叫做字符串常量池的东西。
Java为了避免产生大量的String对象,设计了一个字符串常量池。工作原理是这样的,创建一个字符串时,JVM首先为检查字符串常量池中是否有值相等的字符串,如果有,则不再创建,直接返回该字符串的引用地址,若没有,则创建,然后放到字符串常量池中,并返回新创建的字符串的引用地址。因此看下面这段代码:
String s1="abc"; String s2="abc"; System.out.println(s1==s2); //返回true

返回的结果就是true,因为指向了同一个对象。
关于字符串常量池的位置,在不同版本的JDK中有所不同:
JDK1.7之前字符串常量池属于运行时常量池的一部分,存放在方法区
JDK1.7之后字符串常量池被从方法区拿到了堆中
(四)String str和new String()有什么区别回到开始的问题,String str和new String()有什么区别?区别在于,String str创建的字符串保存在字符串常量池中,并且可复用。new String()创建的字符串按照最标准的对象创建方式,生成在堆中,并且一个new String会在堆中创建一个对象。下面这张图应该可以把这个流程讲清楚。
写了那么久的String字符串,你可能根本不懂它!

文章图片

s1==s2返回true,s1==s3返回false。
(五)new String()方法创建了几个对象又是个好问题,这道题的答案是一个或者两个。
写一段代码:
public class test { public static void main(String[] args) { String s1=new String("ab"); } }

编译后通过javap -v test.class查看字节码:
写了那么久的String字符串,你可能根本不懂它!

文章图片

1、在常量池中创建了ab对象,位置在#3
写了那么久的String字符串,你可能根本不懂它!

文章图片

2、在堆中创建了ab对象
这样的情况下创建了两个对象,一个在常量池中,一个在堆中。
再写一段代码:
public class test { public static void main(String[] args) { String s1="ab"; String s2=new String("ab"); } }

同样的方式查看字节码:
写了那么久的String字符串,你可能根本不懂它!

文章图片

首先s1=" ab" 在常量池中创建了ab对象,存放在常量池的#2位置里,这个时候new String就只在堆中创建了一个String对象,常量池中因为已经有了,就不会再创建了。
这样的情况下,只创建了一个对象。
(六)总结虽说怎么写代码都能实现一定的功能,但是有时候换种写法可以省下很多资源。比如将:
String str=new String("abc")

写成:
String str="abc"

虽然只是小小的改动,但是在频繁调用的方法中,就有可能避免创建了百万个String实例。
对于有一定开发经验的程序员,建议可以读一下《Effect-Java》,里面有许多写代码的更优方式。
我是鱼仔,我们下期再见!
写了那么久的String字符串,你可能根本不懂它!

文章图片


    推荐阅读