`
wangkaick
  • 浏览: 3425 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

java String 对象机制探讨

阅读更多

String常量池问题的几个例子

下面是几个常见例子的比较分析和理解:

String a = "a1";   String b = "a" + 1;   System.out.println((a == b)); //result = true  String a = "atrue";   String b = "a" + "true";   System.out.println((a == b)); //result = true  String a = "a3.4";   String b = "a" + 3.4;   System.out.println((a == b)); //result = true 

 

分析:JVM对于字符串常量的"+"号连接,将程序编译期,JVM就将常量字符串的"+"连接优化为连接后的值,拿"a" + 1来说,经编译器优化后在class中就已经是a1。在编译期其字符串常量的值就确定下来,故上面程序最终的结果都为true。

String a = "ab";   String bb = "b";   String b = "a" + bb;   System.out.println((a == b)); //result = false 

 

分析:JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,即"a" + bb无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给b。所以上面程序的结果也就为false。

String a = "ab";   final String bb = "b";   String b = "a" + bb;   System.out.println((a == b)); //result = true 

 

分析:和[3]中唯一不同的是bb字符串加了final修饰,对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量 池中或嵌入到它的字节码流中。所以此时的"a" + bb和"a" + "b"效果是一样的。故上面程序的结果为true。

String a = "ab";   final String bb = getBB();   String b = "a" + bb;   System.out.println((a == b)); //result = false   private static String getBB() {  return "b";   } 

 

分析:JVM对于字符串引用bb,它的值在编译期无法确定,只有在程序运行期调用方法后,将方法的返回值和"a"来动态连接并分配地址为b,故上面 程序的结果为false。

通过上面4个例子可以得出得知:

String  s  =  "a" + "b" + "c";
 
就等价于String s = "abc";  

String  a  =  "a";  
String  b  =  "b";  
String  c  =  "c";  
String  s  =   a  +  b  +  c; 

这个就不一样了,最终结果等于: 

StringBuffer temp = new StringBuffer();     temp.append(a).append(b).append(c);     String s = temp.toString(); 

 

由上面的分析结果,可就不难推断出String 采用连接运算符(+)效率低下原因分析,形如这样的代码:

public class Test {  public static void main(String args[]) {  String s = null;  for(int i = 0; i < 100; i++) {  s += "a";  }  }  } 

 

每做一次 + 就产生个StringBuilder对象,然后append后就扔掉。下次循环再到达时重新产生个StringBuilder对象,然后 append 字符串,如此循环直至结束。如果我们直接采用 StringBuilder 对象进行 append 的话,我们可以节省 N - 1 次创建和销毁对象的时间。所以对于在循环中要进行字符串连接的应用,一般都是用StringBuffer或StringBulider对象来进行 append操作。

String对象的intern方法理解和分析:

public class Test4 {  private static String a = "ab";   public static void main(String[] args){  String s1 = "a";  String s2 = "b";  String s = s1 + s2;  System.out.println(s == a);//false  System.out.println(s.intern() == a);//true    }  } 

 

这里用到Java里面是一个常量池的问题。对于s1+s2操作,其实是在堆里面重新创建了一个新的对象,s保存的是这个新对象在堆空间的的内容,所 以s与a的值是不相等的。而当调用s.intern()方法,却可以返回s在常量池中的地址值,因为a的值存储在常量池中,故s.intern和a的值相等。

总结

栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String,数组.对象等等)但不存放对象内容

堆中存放使用new关键字创建的对象.

字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常 量池中,而有的是运行时才被创建.使用new关键字,存放在堆中。

分享到:
评论

相关推荐

    JAVA面试题解惑系列(二)——到底创建了几个String对象-JAVA程序员JAVA工程师面试必看.pdf,这是一份不错的文件

    本文将深入探讨 JAVA 中 String 对象的创建机制,解答常见的面试题目,并探索 String 对象池的概念和机制。 一、String 对象的创建方式 在 JAVA 中,String 对象可以通过多种方式创建,包括使用 new 关键字、使用...

    深入探讨Java中的String类.pdf

    Java 中的 String 类有很多特点和用途,本文将深入探讨 Java 中的 String 类。 一、String 类的本质 Java 中的 String 类是一个特殊的类,它是一个 immutable 类,也就是说,一旦创建了 String 对象,它的值就不能...

    简单说说JAVA的String和byte[]的关系

    在Java编程语言中,`String`对象与`byte[]`数组之间的转换是常见的操作之一。理解这两者之间的关系对于处理文本数据、网络通信及文件读写等任务至关重要。 #### 一、String与byte[]的基本概念 - **String**: 在...

    JNI处理hashmap,string等对象的操作

    对于String对象的处理,JNI提供了`NewStringUTF`函数来创建一个新的Java String对象,以及`GetStringUTFChars`和`ReleaseStringUTFChars`来获取和释放字符串的UTF-8表示。例如,你可能需要在本地代码中解析或修改...

    Java String 字符串创建理解 equels和\"==\" 差异

    在Java编程语言中,字符串(String)是一个非常基础且...总之,理解Java中的字符串创建机制和"=="与equals()的区别,是写出高效、正确代码的关键。在实际开发中,我们应该根据具体情况选择合适的字符串创建和比较方式。

    拷贝JSON对象值进Java Bean对象

    在Java编程中,将JSON对象转换为Java Bean对象是一个常见的任务,特别是在处理Web服务或API交互时。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,而Java Bean是符合特定规范的Java类,通常用于...

    java面试题--反射机制

    通过本文,我们将深入探讨Java反射机制的核心概念、基本原理及其应用场景。 #### 二、Java反射机制简介 Java反射机制允许程序在运行时获取类的信息,这使得Java具有了一定程度上的动态性。具体来说,Java反射机制...

    JAVA面向对象技术PPT

    下面我们将深入探讨Java面向对象的三大特性:封装、继承和多态。 **1. 封装** 封装是面向对象编程的基础,它隐藏了对象内部的实现细节,只对外提供公共接口进行交互。在Java中,通过访问修饰符(public, private, ...

    jni java传递对象到C

    但是,由于Java对象的内存管理是自动的,而C/C++中没有垃圾回收机制,所以在C代码中直接操作Java对象需要特别小心,避免内存泄漏。 要将Java对象传递到C,我们通常需要经历以下步骤: 1. **声明JNI函数**:在C/C++...

    JAVA面向对象可以供学生 学习

    下面我们将深入探讨Java面向对象编程的一些重要知识点。 1. 类与对象 类是创建对象的模板,它定义了对象的属性(数据成员)和行为(方法)。对象是类的实例,每个对象都有自己的属性值和行为。在Java中,使用`...

    Java面向对象编程中的String类:特性、常用操作及性能优化

    首先介绍了String对象的不可变特性和字符串池机制,避免不必要的内存开销;然后阐述了如字符串比较(区分/忽略大小写)、获取长度、拼接、截取、查找和替换等基本操作的具体使用方法;接着分析了频繁修改字符串导致...

    Java中String,StringBuffer与StringBuilder的区别

    这种机制使得 String 类型的性能不好,特别是在频繁修改字符串的情况下。 其次,让我们看一下 StringBuffer 类型。StringBuffer 类型是可变的对象,意味着可以修改它的内容。与 String 类型不同的是,StringBuffer ...

    JAVA 对象数组按照多个属性进行排序

    在Java编程中,对象数组排序是一项常见的任务,...以上就是关于“JAVA 对象数组按照多个属性进行排序”的详细解析,希望对你理解Java排序机制有所帮助。在实际开发中,灵活运用这些技巧可以提高代码的可维护性和效率。

    使用Java反射机制将Map转换为Java对象,支持Boolean、Date类型

    在本主题中,我们将深入探讨如何使用Java反射机制将Map转换为Java对象,同时支持Boolean和Date类型的数据。这种转换在处理JSON到对象的映射或者数据库查询结果到对象的映射时非常有用。 首先,我们需要了解Java中的...

    java面向对象File (I O)

    Java中的流是一种抽象机制,用于处理输入输出数据。数据可以是一系列的字节或字符。根据流的方向,可以将其分为输入流和输出流: - **输入流**(Input Streams):用于从数据源读取数据。Java中有两种基本类型的...

    java中String类型变量的赋值问题介绍

    首先,Java中的String类是不可变的,这意味着一旦创建了一个String对象,就不能改变它所表示的字符序列。当我们对String对象进行赋值操作,例如`str = "new value"`,实际上并不是修改原有的字符串,而是创建了一个...

    java内存分配和String类型的深度解析Java开发J

    使用`+`操作符连接字符串会创建新的String对象,如果频繁操作,会产生大量临时对象,消耗内存。为优化性能,可以使用StringBuilder或StringBuffer类,它们提供了append方法,可以在已有字符串基础上添加内容,无需...

    10个Java经典的String面试题!.pdf

    9. **自定义java.lang.String类**:虽然理论上可以自定义`java.lang.String`,但由于Java类加载机制,系统会优先使用已存在的标准库版本,导致自定义版本无法正常使用。 10. **String与byte[]之间的转换**:要将...

    北大青鸟java反射机制

    在"北大青鸟java反射机制"的学习资料中,我们将会深入探讨这一核心特性。 首先,我们要理解反射的核心概念:在程序运行时,通过Class对象获取类的信息,包括类名、属性、方法等,并能够动态地创建对象和调用方法。...

Global site tag (gtag.js) - Google Analytics