JAVA String对象的创建

String对象的创建是比较特殊的,普通对象创建都是在堆中创建,String对象确不一定,下面看一段代码

[java] view plaincopy

  1. public class StringTest1 {
  2. public static void main(String[] args) throws Exception{
  3. String a = "abc";
  4. String b = "abc";
  5. String c = "ab";
  6. String d = new String("ab");
  7. System.out.println("a=" + a);               //a=abc
  8. System.out.println("b=" + b);               //b=abc
  9. System.out.println("c=" + c);               //c=ab
  10. System.out.println("d=" + d);               //d=ab
  11. System.out.println("a==b is " + (a == b));  //a==b is true
  12. System.out.println("c==d is " + (c == d));  //c==d is false
  13. Field field = String.class.getDeclaredField("value");
  14. field.setAccessible(true);
  15. char[] valueA = (char[]) field.get(a);
  16. char[] valueB = (char[]) field.get(b);
  17. char[] valueC = (char[]) field.get(c);
  18. char[] valueD = (char[]) field.get(d);
  19. System.out.println("a.value(" + valueA.hashCode() + ")=" + Arrays.toString(valueA));
  20. //a.value([1829164700)=[a, b, c]
  21. System.out.println("b.value(" + valueB.hashCode() + ")=" + Arrays.toString(valueB));
  22. //b.value([1829164700)=[a, b, c]
  23. System.out.println("c.value(" + valueC.hashCode() + ")=" + Arrays.toString(valueC));
  24. //c.value([2018699554)=[a, b]
  25. System.out.println("d.value(" + valueD.hashCode() + ")=" + Arrays.toString(valueD));
  26. //d.value([2018699554)=[a, b]
  27. valueA[0] = ‘z‘;
  28. valueD[0] = ‘x‘;
  29. System.out.println("a=" + a);               //a=zbc
  30. System.out.println("b=" + b);               //b=zbc
  31. System.out.println("c=" + c);               //c=xb
  32. System.out.println("d=" + d);               //d=xb
  33. }
  34. }

a跟b都是“abc”,测试结果a跟b的引用是相等的,value数组也是相等的,改变a的第一位,b也跟着变了。

c跟d都是“ab”,但是两个引用是不相等的,d是用new创建的,这个时候才会在堆中创建对象,a,b,c三个引用都是直接指向常量池的对象的,
但是下面c和d的value似乎又是同一个数组,改变d的第一位,c也变了,说明d在堆中创建的对象还是指向常量池的,所以用new的话就多创建了个对
象。

还有一个经典的问题, String a = "a" + "b";创建了几个对象。

一般来说应该是3个吧,一个"a",一个"b",一个结果"ab",下面写一个简单的类

[java] view plaincopy

  1. public class StringTest2 {
  2. @SuppressWarnings("unused")
  3. public static void main(String[] args){
  4. String a = "a" + "b";
  5. }
  6. }

使用javap看一下字节码

[plain] view plaincopy

  1. javap -c StringTest2.class
  2. Compiled from "StringTest2.java"
  3. public class test.StringTest2 {
  4. public test.StringTest2();
  5. Code:
  6. 0: aload_0
  7. 1: invokespecial #8                  // Method java/lang/Object."<init>":
  8. ()V
  9. 4: return
  10. public static void main(java.lang.String[]);
  11. Code:
  12. 0: ldc           #16                 // String ab
  13. 2: astore_1
  14. 3: return
  15. }

只有一个指令ldc           #16 ,从常量池里加常量#16,很明显这个常量就是ab,我就不去解析class文件了,应该是没错,直接反编译一下,得到的结果是

[java] view plaincopy

  1. package test;
  2. public class StringTest2
  3. {
  4. public static void main(String[] args)
  5. {
  6. String a = "ab";
  7. }
  8. }

所以引用直接指向常量池"ab"了,就一个对象吗,可能是编译器优化的结果吧,如果有时间去单独把class文件一个字节一个字节解析出来结果应该更明了。

时间: 2024-10-07 16:24:36

JAVA String对象的创建的相关文章

Java String对象的经典问题(转)

public class StringTest { public static void main(String[] args) { String strA = "abc"; String strB = "abc"; String strC = new String("abc"); System.out.println(strA == strB);//true System.out.println(strA == "abc")

3.Java基础:String对象的创建和使用

一.常用的创建方式 String s1="abc": String s2="abc": s1==s2    ==> true 解析:s1和s2指向的是同一个字符串池地址 二.不常用的创建方式 String s1=new String("abc"): String s2=new String("abc"):: s1==s2    ==> false 解析:s1和s2指向的是不同的字符串池地址,new的时候会重新创建一

深入理解final 类String 对象的创建以及内部方法

学习过程中的笔记 : int indexOf(int ch) :获取字符在字符串中第一次出现的位置,如果不存在,则返回-1 int indexOf(int ch,int fromIndex): 从fromIndex位置开始查找,查找ch第一次出现的位置 获取位置 int indexOf(int ch) :获取字符在字符串中第一次出现的位置,如果不存在,则返回-1 int indexOf(int ch,int fromIndex): 从fromIndex位置开始查找,查找ch第一次出现的位置 in

【转】Java String对象的经典问题(new String())

public class Test { public static void main(String[] args) { String str = "abc"; String str1 = "abc"; String str2 = new String("abc"); System.out.println(str == str1); System.out.println(str1 == "abc"); System.out.p

我的Java开发学习之旅------&gt;Java String对象作为参数传递的问题解惑

又是一道面试题,来测试你的Java基础是否牢固. 题目:以下代码的运行结果是? public class TestValue { public static void test(String str) { str="World"; //代码3 } public static void main(String[] args) { String string = "Hello"; //代码1 test(string); //代码2 System.out.println(

深入理解java虚拟机---对象的创建过程(八)

1.对象的创建过程 由于类的加载是一个很复杂的过程,所以这里暂时略过,后面会详细讲解,默认为是已加载过的类.着重强调对象的创建过程. 注意: 最后一步的init方法是代码块和构造方法. 以上是总图,下面分步骤详细讲解 A: 虚拟机为对象分配内存方式 1. 指针碰撞: 堆内存规整时,这时就可以把其看做一半连续内存被占用,一半连续的内存空闲.所以当创建新对象时,从空闲的内存中分配空间给新对象 2.空闲列表: 堆内存是不连续的,这就需要虚拟机维护一个内存列表,用于记录当前内存是否被占用,当新创建对象时

java中对象的创建过程

举例:类A的的对象a的创建过程 1,因为构造器实质上是静态方法,当首次创建A类的对象时(即执行了A类的静态方法),或者A类的静态方法/静态域首次被访问时,java解释器必须查找类路径,以定位A.class文件. 2,载入A.class文件,有关静态初始化的所有动作都被执行.因此,静态初始化只在Class对象首次加载的时候执行一次. 3,为将要创建的a对象分配足够多的存储空间. 4,执行所有出现在字段定义处的初始化动作. 5,执行构造器(如有继承,先执行基类的构造器). 原文地址:https://

Java——String对象

一.字符串:不可变对象:一旦赋值,其内容是不可改变的: //重新赋值,等于创建新的对象: 二.创建方法: (1)String s=new String(): (2)String s1=new String("abc"): (3)String s2="abc":  //s为String类型的变量:"abc"是一个对象: 注释: 1)s="kk":  //s指向的对象变为"kk","abc"

String对象的创建

方式一:String():空参构造器创建一个空的(长度为0)字符串. 方式二:String(char[] a):用一个字符数组a创建一个字符串对象,构造器参数为一个字符串数组. 方式三: String(char[] a, int offset, int length):提取字符数组a中一部分创建一个字符串对象 offset为开始截取的下标,length为截取长度.(这两个参数要在合法范围内) 方式四:String(String value) 最后,便捷创建一个指向字符串的引用的方式为:,但此种方