关于String的对象创建

1)String

  String是Java中的字符串类,属于引用数据类型。所以String的对象存放的是引用的地址。在底层是一个字符型数组。

String是不可变的。所谓的不可变是指一个对象有了一个引用过后它的引用不可变,每次对String对象增加字符串,该对象的引用将会指向一个新的引用地址。

  在方法区有一个常量池,当字节码加载如虚拟机时字符串常量就已经加载进常量池并给它分配一个内存地址。字符串对象就引用该地址。

=========================================

String str = "abc";

str = str + "d";//引用地址将会改变,这时的str是一个新的对象。

===========================================

2)String对象创建分析

public class Test {

public static void main(String[] args) {

//str1存放(引用)常量池中的地址

String str1 = "abcd";

//str2存放(引用)堆中对象的地址,而堆中的数据存放的是常量池中的地址,多重引用

String str2 = new String("abcd");

}

}

如果常量区中有该字符串,就不重新存储,而是直接引用,这样节省了内存。该程序只在堆中开辟了一个空间。

3)Java对String的优化

源代码:

public class Test {

//返回一个cd字符串

public static String getString() {

return "cd";

}

public static void main(String[] args) {

String str1 = "abcd";

String str2 = "a" + "b" + "c" + "d";

String str3 = "ab" + "cd";

String temp = "ab";

String str4 = "ab" + temp;

String str5 = "ab" + getString();//调用上面定义的方法得到cd

//注意:这里的‘==’比较的是它们的引用地址,而不是比较的它们的值

System.out.println(str1 == str2);//结果为true

System.out.println(str1 == str3);//结果为true

System.out.println(str1 == str4);//结果为false

System.out.println(str1 == str5);//结果为false

}

}

==========================================

使用反编译工具将上面字节反编译得到的代码:

public class Test{

    public static String getString()  {

      return "cd";

    }

   public static void main(String[] args)  {

   String str1 = "abcd";

String str2 = "abcd";

String str3 = "abcd";

String temp = "ab";

String str4 = "ab" + temp;

String str5 = "ab" + getString();

System.out.println(str1 == str2);

System.out.println(str1 == str3);

System.out.println(str1 == str4);

System.out.println(str1 == str5);

}

}

==============================================

结论:

  我们对加红的代码进行比较,也就是Java虚拟机对String经行了优化,这里str1、str2、str3引用了同一个地址,共用了常量区中的数据,所以它们的引用地址进行比较结果是相同的。但是变量和方法无法确认它们准确的值只有运行到该行代码时才能却定,在堆中新创建一个空间。所以str1、str4、str5引用地址的比较不相等。

  Java虚拟机的优化共用了资源,减少了内存的使用,从而释放了更多的空间。

时间: 2024-11-24 07:01:34

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

String str=new String("abc")到底创建了几个对象

这句代码到底创建了几个对象?研究了好一阵,现在才能说清楚. package com.sun.test; public class Test<T> { T a; /** * @param args */ public static void main(String[] args) { String str=new String("abc"); } } 我们来看下这段简单代码的字节码: <pre name="code" class="java

【代码优化】私有构造器使用及对象创建优化

1.使用私有构造器或者枚举类型强化singleton 1>单例模式---私有构造器,提供一个公有的成员是一个静态工厂方法: public class SingleTon{ private static final  SingleTon single=new SingleTon(): private SingleTon(){ } public static SingleTon getInstance() { return single: } } 工厂方法的优势一在于它提供了灵活性:在不改变其他ap

java对象创建与内存模型总结

 1.JVM管辖的内存大致分为三个逻辑部分:java栈(Heap).java堆(JavaStack)和方法区(MethodArea).在JVM启动时创建,关闭时全部回收.  栈.本地方法栈.程序计数器:以线程为粒度,每个线程拥有自己的部分.而堆和方法区被所有线程共享.  堆:运行时的数据区域,程序(线程)运行时动态分配.  方法区:静态存储区,存储被装载到JVM中的class信息. 2.栈 i).存放基本类型的变量数据和对象的引用变量(变量本身存放在堆和常量池中). ii).java系统必须知道

【Java基础】Java类的加载和对象创建流程的详细分析

相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下. 实例问题 实例代码 Parent类 1 package mytest.javaBase; 2 3 public class Parent { 4 int a = 10; 5 static int b = 11; 6 // 静态代码块 7 static { 8 System.out.println("Parent静态代码块:b=" + b)

Gradle 庖丁解牛(构建生命周期核心托付对象创建源代码浅析)

[工匠若水 http://blog.csdn.net/yanbober 未经同意严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 上一篇<Gradle 庖丁解牛(构建源头源代码浅析)>我们分析了 Gradle 框架自身初始化(非构建生命周期初始化)的核心流程,这一篇我们续着前面的分析继续(假设没看过前一篇的建议先去看前一篇,由于这一系列存在非常高的关联性).上一篇说到当我们运行 gradle taskName 命令后经过一系列艰难的框架初始化终于走到了 DefaultGradleLaunc

《C++编程思想》 第十二章 动态对象创建 (习题+解答)

一.相关知识点 重载new和delete 当创建一个new表达式时有两件事发生.首先,使用运算符new分配内存,然后调用构造函数.在delete表达式里,调用析构函数,然后使用运算符delete释放内存.我们永远无法控制构造函数和析构函数的调用(否则我们可能意外地搅乱它们),但可以改变内存分配函数运算符new和delete. 被new和delete使用的内存分配系统是为通用目的而设计的.但在特殊的情形下,它不能满足我们的需要.改变分配系统的原因是考虑效率:我们也许要创建和销毁一个特定的类的非常多

Java Object 对象创建的方式 [ 转载 ]

Java Object 对象创建的方式 [ 转载 ] @author http://blog.csdn.net/mhmyqn/article/details/7943411 显式创建 有4种显式地创建对象的方式: 1.构造器:用new语句创建对象,这是最常用的创建对象的方式. 2.反射:运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法. 3.克隆:调用对象的clone()方法. 4.序列化:运用反

Gradle 庖丁解牛(构建生命周期核心委托对象创建源码浅析)

[工匠若水 http://blog.csdn.net/yanbober 未经允许严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 上一篇<Gradle 庖丁解牛(构建源头源码浅析)>我们分析了 Gradle 框架自身初始化(非构建生命周期初始化)的核心流程,这一篇我们续着前面的分析继续(如果没看过前一篇的建议先去看前一篇,因为这一系列存在非常高的关联性).上一篇说到当我们执行 gradle taskName 命令后经过一系列艰难的框架初始化最终走到了 DefaultGradleLaunch

Java类的加载和对象创建流程的详细分析

相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下: package com.test; public class Parent { int a = 10; static int b =11; //静态代码块 static { System.out.println("parent静态代码块:b=" + b); b++; } //代码块 { System.out.println("P