- 浏览: 128393 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
wind35:
32赞~~~
KDB+ database -
sunnyxiaoxi:
图片看不到
KDB+ database 初步 -
RonQi:
确实很有用的插件
eclipse插件 快速打开文件位置,在命令行打开文件位置 -
zhanshi258:
我们程序员讲究的是严谨,大部分人是讲娱乐
小唠叨 -
li498833284:
因为很多都是屏蔽字
小唠叨
转自 http://hxraid.iteye.com/blog/522167
作者:Java标准类库有几千个类,唯独String不太一样。为什么这么说?就因为每次上网冲杯Java时,都能看到关于String无休无止的争论。还是觉得有必要让这个讨厌又很可爱的String美眉,赤裸裸的站在我们这些Java色狼面前了。嘿嘿....
众所周知,String是由字符组成的串,在程序中使用频率很高。Java中的String是一个类,而并非基本数据类型。 不过她却不是普通的类哦!!!
【镜头1】 String对象的创建
1、关于类对象的创建,很普通的一种方式就是利用构造器,String类也不例外:
String s=new String("Hello world");
问题:参数"Hello world"是什么东西,也是字符串对象吗?莫非用字符串对象创建一个字符串对象???
2、当然,String类对象还有一种大家都很喜欢的创建方式:
String s="Hello world";
问题:有点怪呀,怎么与基本数据类型的赋值操作(int i=1)很像呀???
在开始解释这些问题之前,我们先引入一些必要的知识:
(1) Java class文件结构
我们都知道,Java程序要运行,首先需要编译器将源代码文件编译成字节码文件(也就是.class文件)。然后在由JVM解释执行。
class文件是8位字节的二进制流 。这些二进制流的涵义由一些紧凑的有意义的项 组成。比如class字节流中最开始的4个字节组成的项叫做魔数 (magic),其意义在于分辨class文件(值为0xCAFEBABE)与非class文件。class字节流大致结构如下图左侧。
其中,在class文件中有一个非常重要的项——常量池 。这个常量池专门放置源代码中的常量信息(并且不同的常量存放在不同标志的常量表中)。如上图右侧是HelloWorld代码中的常量表(HelloWorld代码如下),其中有四个不同类型的常量表(四个不同的常量池入口)。关于常量池的具体细节,请参照《深入Java虚拟机》第二版第6章。
public class HelloWorld{ void hello(){ System.out.println("Hello world"); } }
显然,HelloWorld代码中的"Hello world"被编译之后,可以清楚的看到存放在了class二进制流的常量池项中(上图右侧红框区域)。并且我们还发现常量池中专门有为String类型设置的常量表 。也就是说,在编译阶段,就已经将代码中的这种("****")形式作为了字符串常量存放在常量池中了 ,这一点和下面代码中出现的整形常量(142),浮点型常量(12.1)等的处理是没有区别的。
String s="Hello world";
int intData=142;
double dblData=12.1;
(2) Java虚拟机运行class文件
当Java虚拟机需要运行一个class文件时,它首先会用类装载器装载进class文件。当然也就需要在内存中存放许多东西。比如class的二进制字节码。还有需要存储class文件中得到的其他信息,比如程序创建的对象,传递给方法的参数,返回值,局部变量等等。怎么多麻烦的数据当然需要管理,JVM会把这些东西都组织到几个“运行时数据区 ”中。这些数据区中就有我们动不动就谈到的"堆"呀,"栈"呀什么的?想要详细了解这部分东西可以看《深入Java虚拟机》第二版第5章。
在这里我只谈谈“方法区 ”这个运行时数据区。在Java虚拟机中,关于被装载类型的信息会在一个逻辑上被称为"方法区"的内存中,当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入该文件。紧接着虚拟机提取其中的类型信息,并将这些信息存储到方法区中。
方法区中的这些类型信息是很有用的,比如:这个类型的全限定名(net.single.HelloWorld);这个类型的直接超类的全限定名;这个类型是类类型还是接口类型;这个类型的访问修饰符(public,final,static)等。还有两个大家都很熟悉的引用:指向类ClassLoader的引用和指向Class类的引用。这是Java反射机制能够运行的关键所在。这里我们要提到的是一个非常重要的信息——该类型的常量池 。
上面提到的,class文件结构中的常量池二进制流就被JVM存储在方法区中进行管理。当程序运行时需要使用到常量值的时候,直接在方法区常量池所在的内存中寻找就可以了。
(3) 操作码助忆符指令集
将String s=new String("Hello world");编译成class文件后的指令(由eclipse打开class文件查看的):
- 0newjava.lang.String[15]
- 3dup
- 4ldc<String"Helloword">[17]
- 6invokespecialjava.lang.String(java.lang.String)[19]
- 9astore_1[s]
- 10retur
0 new java.lang.String [15] 3 dup 4 ldc <String "Hello word"> [17] 6 invokespecial java.lang.String(java.lang.String) [19] 9 astore_1 [s] 10 retur
下面通俗的解释一下这些指令,详细见《深入Java虚拟机》第二版附表:按操作码助忆符排列的指令集。
★ new指令: 在内存的堆区域中为新字符串对象分配足够大的空间,并将对象的实例变量设为默认值。
★ ldc指令:在内存的方法区常量池中找到String类型字面值常量表 的入口,然后定位到的"Hello word"所在内存中的位置。
★ invokespecial指令:调用指定的类构造器(这里调用的是String(String)这一个构造器。将ldc指令所找到的"Hello word"的内容传入到new指令所开辟在堆中的字符串对象中。
★ astore_1:将new指令所开辟堆的内存位置存入局部变量s中 。
将String s="Hello world";编译成class文件后的指令:
0 ldc <String "Hello world"> [15] 2 astore_1 [str] 3 return
★ ldc指令:在内存的方法区常量池中找到String类型字面值常量表 的入口,然后定位到的"Hello word"所在内存中的位置(如果常量池中没有"Hello word",则会在其中添加一个"Hello word")。
★ astore_1:将ldc指令定位到的常量池中的位置存入局部变量s中 。
镜头总结: String类型脱光了其实也很普通。真正让她神秘的原因就在于String类型字面值常量表 的存在。
相关问题解决
(问题1) 代码1 代码2
String sa=new String("Hello world"); String sc="Hello world";
String sb=new String("Hello world"); String sd="Hello world";
System.out.println(sa==sb); // false System.out.println(sc==sd); // true
变量sa,sb中存储的内容是JVM在堆中开辟的两个String对象的内存地址。==比较就是sa,sb变量存储的内容,也就是两个不同的内存地址,当然是false;
变量sc,sd中存储的内容也是地址,但却都是方法区常量池中"Hello word"所在的地址,自然一样。
(问题2) 代码1 代码2
String sa = "ab"; String sc="ab"+"cd";
String sb = "cd"; String sd="abcd";
String sab=sa+sb; System.out.println(sc==sd); //true
String s="abcd";
System.out.println(sab==s); // false
代码1中sa+sb被编译以后使用的是StringBuilder.append(String)方法。JVM会在堆中创建一个StringBuilder类,将sa所指向常量池中的内容"ab"传入,然后调用append(sb所指向的常量池内容)完成字符串合并功能,最后将堆中StringBuilder对象的地址赋给变量sab。而s存储的是常量池中"abcd"的地址。sab与s地址当然不一样了。
代码2中"ab"+"cd"会直接在编译阶段就合并成常量"abcd",所以相同的字符串在常量池中的地址也相同了。
发表评论
-
入手Git
2013-09-18 21:57 1048原本项目一直托管在sourceforge上面. http: ... -
以插件的方式把myeclipse安装到eclipse
2013-04-27 16:56 85961, 请注意eclipse版本问题,笔者用的是eclips ... -
从与大牛richard stallman 聊来的感受
2012-04-25 10:03 956老头非常敬业热心, 写邮件给他, 就算没有时间马上回, 也会有 ... -
Jar Class Finder
2012-04-15 22:38 951Jar Class Finder Jar与Class的查找工 ... -
sourceforge 历程
2012-04-14 19:36 0入门 http://newbiedoc.sourceforg ... -
版本控制之MKS integrity 2007
2011-01-06 16:28 0在新项目中用到了版本控制MKS integrity 2007 -
Open-source License
2010-03-04 11:22 1962Open-source License(转载) ... -
Java 多线程与并发编程专题
2009-11-18 15:55 693http://www.ibm.com/developerwor ... -
浅析Context Class Loader
2009-11-19 11:33 1141转载自 薛笛的专栏http://blog.csdn.net/k ... -
JVM调优总结
2009-11-19 15:35 805转载自http://gq913.iteye.com ... -
Ant build.xml 模板
2009-11-23 14:04 1016<?xml version="1.0" ... -
用javac编译生成不同版本的源码和目标class
2009-11-24 14:47 909转载请自 Ken Wu`s Blog! 合理使用javac的 ... -
java内存模型详解
2009-11-24 14:50 775转载自 Ken Wu`s Blog! 内存模型 (memo ... -
bootstrap类加载原理
2009-11-24 14:53 909转载自 Ken Wu`s Blog! 让我们一起跟随Clas ... -
很详细的Log4j配置
2009-11-25 11:01 716来自: http://www.blogjava.net/zJu ... -
Log4j日志文件的使用
2009-11-25 17:32 913转自 http://blog.csdn.net/edg_edu ... -
另一个好的ant文件收藏
2009-11-26 13:30 929<?xml version="1.0" ... -
提示补全组件:Kissy Suggest
2009-11-26 14:06 1020转自 http://www.iteye.com/topic/4 ... -
自定义ClassLoader 简单例子
2009-12-10 16:15 1440转载自 http://www.javaresearch.org ... -
dom4j读写xml文件
2010-01-29 09:34 952首先我们给出一段示例程序: importjava.io.F ...
相关推荐
### Java字符串操作详解:String1.java程序分析 在Java编程语言中,字符串处理是一项非常重要的技能,无论是进行数据处理还是用户交互,字符串都是一个不可或缺的数据类型。本篇将基于提供的`String1.java`代码示例...
java java_leetcode题解之Permutation in String.java
"JAVA 对word 内容的提取返回String" 在本文中,我们将详细介绍如何使用 Java 语言来提取 Word 文档的内容,并将其返回为字符串。我们将通过两种方式来实现这个目标,分别是使用 Java 流读取 Word 内容和使用 Jacob...
`characterString_java_in_character_string_`这个标题暗示我们将探讨如何在Java中处理字符字符串,特别是查找字符串中的特定字符。描述中提到的“to find character in a string”进一步明确了我们要讨论的主题。...
java java_leetcode题解之Find All Anagrams in a String.java
本压缩包"String manipulation operations in java.zip"中的内容可能是一个关于Java字符串操作的项目或教程,其中特别提到了`underscore.string.java-master`这个子文件,暗示了它可能使用了`underscore.string`库来...
本压缩包"json in java.rar"包含了关于在Java中使用JSON的相关资料,主要可能涵盖了如何将Java对象转换为JSON字符串,以及如何从JSON字符串解析成Java对象。 在Java中,最常用的两个库是Jackson和Gson。Jackson提供...
1 Rotate Array in Java 15 2 Reverse Words in a String II 19 3 Evaluate Reverse Polish Notation 21 4 Isomorphic Strings 25 5 Word Ladder 27 6 Word Ladder II 29 7 Median of Two Sorted Arrays 33 8 Kth ...
java.lang.System.out.println("Display a String in Java Console!"); ``` 为了使JavaScript能够访问Java Applets的方法和变量,有几点需要注意: - **声明公共类、方法和变量**:Java Applet中需要通过`public`...
Java中的String、Vector和Scanner是三个非常基础且重要的概念,对于初学者来说,理解它们的用法和原理是学习Java编程的关键步骤。 首先,我们来深入理解`String`类。在Java中,`String`是一个不可变的字符序列,这...
### Java的String用法类型总结 #### 一、概述 在Java编程语言中,`String` 类是最常用的数据类型之一,用于表示不可变的字符序列。由于字符串在实际开发中的重要性和高频使用特性,深入理解并掌握其用法至关重要。...
JAVA使用ElasticSearch查询in和not in的实现方式 Elasticsearch是一个基于Lucene的搜索服务器,提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。它是用Java开发的,并作为Apache许可条款下的开放...
10. **Java标准库(JDK)**:熟练使用Java提供的各种API,如Math、String、Date、Collections等,可以极大地提高开发效率。 以上只是《Thinking in Java》中涉及的部分核心知识点,这本书还涵盖了更多高级主题,如...
AndroidLintPlus A demo to custom your Lint rules 中文 扩展Lint 规则,该库写了三个场景 1、JavaChineseStringDetector:检查 java 代码中的中文字符...1.JavaChineseStringDetector:check chinese string in java f
《Thinking in Java》是一本深度解析Java编程语言的经典著作,其深入浅出的讲解和丰富的实例使得读者能够全面理解Java的精髓。以下是对书中部分关键知识点的总结: 1. **Java 泛型**:泛型是Java SE 5.0引入的重要...
在Java中,有多种库支持JSON的处理,包括JSONObject、Jackson和Gson。这三种技术各有特点,使得开发者可以根据具体需求选择最适合的工具。 **JSONObject** JSONObject是Java的一个开源库,它基于Java集合框架,...
### TCP/IP Sockets in Java — 实用编程指南 #### 一、引言 《TCP/IP Sockets in Java — 实用编程指南》(第二版)是一本面向程序员的实用指南,旨在帮助读者掌握如何在Java中使用TCP/IP套接字进行网络编程。...
### Thinking in Java 自学笔记——第二章 一切皆对象 #### 重要概念解析 ##### 2.1 用引用操纵对象 在Java中,一切都被视为对象,这意味着无论是字符串、数字还是其他数据类型都可以被视为对象来进行操作。当...
String message = “Welcome to Java”; System.out.print(message.length()); //输出字符串长度15 返回字符串中字符的个数,即长度。中文、英文都算作一个字符。 其语法形式如下:字符串名.length(); 例1:在某系统...
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它采用完全独立于语言的文本格式,但也使用了类似于C家族语言(包括Java)的习惯,这使得它对人类可读且易于编写,同时也易于机器解析和生成。...