JAVA基础之String
一.概述
1.1 简介:
String是一个复制类型,在java项目中使用最多。在java中String变量值都是存放的String在堆空间中的地址。本文讲解下String的地址相关常量池和intern。
2.2 String的组成:
a.数组被放在堆空间。
b.数组不能改变大小,每一次改变大小都会重新分配空间(地址改变)。
2.4 常用的方法
可以去下载帮助文档(chm文件)查看。
二.案例
2.1 初始化
a. ==要相等,必须在class文件在加载时,能让JVM解析并生成的char[]在常量池中。
b. =初始化,JVM直接解析,然后从常量池中寻找相同的值地址空间,并返回;如果没有值,则创建并返回。
c. new初始化时,将变量值存放为new String()开辟的堆空间地址,然后在堆空间地址中存放常量池中同样值的char[]地址,如果没有则创建并返回
d. 只有JVM在解析的时候,能够准确的知道=右值的准确地址(包括可以通过final引用查找到其值,不包括引用地址),则其地址空间都相等。
public static void main(String[] args) { final String o1="a"; String o = "a"; String a = "a1"; String b = "a" + 1; String c = o + 1; String c1 = o1 + 1; String d = new String("a1"); /** * String a: 右值是确定的基础变量,没有引用、new等初始化方式,在加载的时候、JVM解析class文件,a直接存放char[]的地址 * String b: 虽然右值使用了+,但是JVM直接将其整合为char[],放在堆空间 * String c: 引用,JVM只有在加载后,运行时才能去人地址 * String c1:虽然使用的是引用,但是有final,JVM可以直接解析 * String d: d指向的是,new 在运行时分配堆空间。 */ System.out.println(a == b); // true System.out.println(a == c); // false System.out.println(a == c1); // true System.out.println(a == d); // false System.out.println(a.intern()); System.out.println(a.hashCode()); // 3056 System.out.println(b.hashCode()); // 3056 }
2.2 intern
源码解释:
Returns a canonical representation for the string object.A pool of strings, initially empty, is maintained privately by the class String.When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of theThe Java™ Language Specification.返回一个标准的String对象。String池,开始是空的,用来保存私有的String类。1.用intern()时:如果这String池里面有一个能够equals(objects)《即,有一个相同值的char[]》,则返回这个char[];如果没有,则添加创建一个,并返回。2.两个String字符串 s和t,只有在s.equals(t) <值相同> 的情况下,t.intern()==s.intern()为true。 值相同>
案例:
public static void main(String[] args) { String a = "a1"; /* * intern 返回String常量池中地址;相同Unicode的地址引用 将一个 String 类的保存到一个全局 String 表中 , * 如果具有相同值的 Unicode 字符串已经在这个表中,那么该方法返回表中已有字符串的地址, * 如果在表中没有相同值的字符串,则将自己的地址注册到表中 */ System.out.println("============== 基础变量 ==============="); String c00 = "a".intern() + 1; // 方法在,runtime确认 String c01 = "a" + 1; //加载时,确认地址 System.out.println(a == c00); // false System.out.println(a == c01);// true System.out.println(a == c00.intern()); //(true) runtime方法运行、返回指向的常量池地址 System.out.println("============== final 引用 ==============="); final String b1 = "a"; // 运行时确认值 String c10 = b1.intern() + 1; String c11 = b1 + 1; System.out.println(a == c10); // false System.out.println(a == c11); // true System.out.println(a == c01.intern()); //true runtime方法运行、返回指向的常量池地址 System.out.println("============== 引用 ==============="); String b2 = a; // 运行时确认值 String c20 = b2.intern() + 1; String c21 = b2 + 1; System.out.println(a == c20); // false System.out.println(a == c21); // System.out.println("==============final new 初始化==============="); final String b3 = new String("a"); // NEW 运行时确认值 String c30 = b3.intern() + 1; String c31 = b3 + 1; System.out.println(a == c30); // false System.out.println(a == c31); // false System.out.println("============== new ==============="); String b4 = new String("a"); // final new 运行时确认值 String c40 = b4.intern() + 1; String c41 = b4 + 1; System.out.println(a == c40); // false System.out.println(a == c41); // true System.out.println("============== method ==============="); final String b5 = getB3(); // 方法运行时确认值 String c50 = b5.intern() + 1; // 对于引用,但是运行时JVM才知道其值 String c51 = b5 + 1; // 对于引用,但是运行时JVM才知道其值 System.out.println(a == c50); // false System.out.println(a == c51); // true (说明在同一个常量池) System.out.println("============== final method ==============="); final String b6 = getB4(); // final方法,运行时确认 String c60 = b6.intern() + 1; // 对于引用,但是运行时JVM才知道其值 String c61 = b6 + 1; // 对于引用,但是运行时JVM才知道其值 System.out.println(a == c60); // false System.out.println(a == c60); // true (说明在同一个常量池) } public static String getB3() { return "a"; } public final static String getB4() { return "a"; }