`
longgangbai
  • 浏览: 7339851 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java 字符串类型知道少

阅读更多
package com.easyway.commons.ispace.dev.oop.questions;
/**
 * 
 * String的学习应用:
 * String的intern()方法 
 *“当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),
 *则返回池中的字符串;否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。它遵循对于任何两个字符
 *串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true”,这是jdk文档原文
 *注解。现在我们回到最开头的那个例子,为什么String str=new String("aaa");会产生2个对象?一个是"aaa"又作
 *为字符串构造函数的参数,但"aaa"自己就是一个字符串,在传进构造函数前就已创建了一个字符对象,实质上与就好比是
 *第二个实例:String str="aaa"; ,它创建的字符串对象会放入到池中,并且引用的也是池中的那个字符串对象;
 *另一个就是通过new String()构造函数创建的。所以new String("aaa")会产生两个对象,也就是说通过此种方式创
 *建字符串对象时,会先将字符串参数对象放入对象池,然后另外创建一个字符串对象。理解完new String("aaa")为什么
 *会产生两个对象,我们再来看看new String(char value[])这样的方式创建时,又会不会把字符串对象放入到池中呢?
 *答案是不会的。因为传递给构造函数的是一个字符数组,而不是像前面传递的是一个字面常量字符串参数那样,将字符串参
 *数本身放入池中。那么我们现在如果证明new String(char value[])未将字符串对象放入池中,我们可以写一个简单
 *的测试,运行时打开XP的任务管理器,查看操作系统的内存使用情况就可以初步确认:
 *方法测试如下:monitorCPU()
 *所以创建字符串对象放入并放入池中有二种方式:第一种就是直接使用字面常量定义字符串时,如 String str="aaa"; ,
 *str会引用放入池中的对象;第二种就是使用带字符串参数的字符串构造函数,并且此时传入的参数值要是字符串常量形式,
 *而不能是变量的形式,也就是说只能是 String str=new String("aaa");形式,而不能是先定义 String s = "aaa",
 *然后再使用 String str=new String(s);来创建对象,new String(s);此时只创建一个对象,但如果池中不存在时我
 *们可以使用intern方法将它放入池中。当然上面放入池中的前提是池中还不存在这些字符串对象。其实,当我们仔细研究时,
 *发现放入池中只实质上只存在一种时机,那就是:直接使用字面常量字符串时。上面所说的两种时机实质上就是直接使用了字面常的字符串而将其放入池中的。
*上面多处提到了JVM中的堆栈,下面小结一下各自原作用:
*栈用来保存基本类型与对象的引用的,基本型在创建前会查看Stack中是否已经有, 有则指向, 没有则创建。
*String内部是以字符串数组来存储字符串的,因此可以认为与char[]等同, String a= "abc",首先在Heap中创一个对
*象,再到Stack中找char[]是否存在,有则指向该地址, 无则在Stack中创建数组 new出来的都是在Heap中,堆是用于存储对象的。
 *
 *
 * @author longgangbai
 * @date 2010-5-14
 * @version 1.0
 * @since JDK6.0
 */
public class JavaString {
	
	
	/**
	 * 下面声明相等于两个字符串:一个有java虚拟机创建的字符串常量“aaa”和创建在堆时的原实例对象。
	 * str是一个字符串的声明,是一个字符串的引用,放在堆里,用来指向对中创建出来的对象。
	 * 相当于一个字符创创
	 * 
	 * 常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。
	 * 它包括了关于类、方法、接口等中的常量,也包括字符串常量。
	 */
     String  str=new String("aaa");
     /**
      * 只创建1个对象。这里涉及到字符串常量池,在JVM中有一个字符串池,它用来保存很多可以被共享的
      * String对象,这样如果我们在使用同样字面字符串时,它就使用字符串池中同字面的字符串。当然我
      * 们可以使用String对象的intern()方法来访问String对象在字符串池中所对应的常量对象。 
      * 上面这行代码被执行的时候,JVM先到字符串池中查找,看是否已经存在值为"aaa"的对象,如果存在,
      * 则不再创建新的对象,直接返回已存在对象的引用;如果不存在,则先创建这个对象,然后把它加入到
      * 字符串池中,再将它的引用返回。
      */
     String constStr1="aaa";
     /**
      * 也只创建1个对象。能过上面的解释这个就更清楚了,在执行第二行代码时,aaa字符串对象在池中已存在,
      * 所以直接返回池中已存在的那个字符串对象。
      */
     String constStr2="aaa";
     
     
     /**
      * 还是只创建1个对象。由于常量字符串是在编译的时候就也被确定的,又因"aaa"和"bbb"都是常量,因此变
      * 量str的值在编译时就可以确定。这行代码编译后的与String str="aaabbb";是一样的,这与我们平时
      * 好像不太一样啊?一般使用“+”连接两个字符串都会产生另一个新的字符对象。
      */
     String constStr3="aaa"+"bbb";
     
     //但如果先定义final字符串,但未在定义处初始化,而初始化在块中,如下:
     //此时str1与str2相当于变量,而不是常,因为块是在运行时才能确定,在编译时不能确定
	 final static String str9;  
	 final static String str10;  
	 static {  
	         str9 ="aaa";  
	         str10 ="bbb";  
	 }
     
     
     /**
      * 使用“+”连接的两个字符串本身就是字面常量字符串时,如果池中存在这样连接
      * 后的字符串,则是不会重新创建对象,而是直接引用池中的字符串对象;如果“+”连接的两字符串中只要有一个
      * 不是字面常量串(即定义过的),是会产生新的字符串对象。凡事也有例外,这个也不例外:如果“+”连接的字
      * 符串中两个或一个不是“字面常量”,但如果定义成常量字符串时,情况又有变化:
      * @param args
      */
     public static void main(String[] args) {
    	 String str1 = "aaa";
    	 String str2 = "bbb";
    	 String str3 = "aaabbb";

    	 String str4 = "aaa" + "bbb";//不会产生新的字符串对象
    	 System.out.println(str3 == str4);//true

    	 str4 = str1 + "bbb";//会产生新的字符串对象
    	 System.out.println(str3 == str4);//false

    	 str4 = str1 + str2;//会产生新的字符串对象
    	 System.out.println(str3 == str4);//false
    	 
    	 
    	 
    	 final String str5 = "aaa";
    	 final String str6 = "bbb";
    	 String str7 = "aaabbb";

    	 /*
    	  * 因为str1与str2都定义成了常量,所以编译时就能确定,编译时就会将常量替换,等同于
    	  * str4 = "aaa"+"bbb",因此不产生新对象
    	  */
    	 String str8 = str5 + str6;
    	 System.out.println(str7 == str8);//true
    	 
    	 
    	 
    	 String str11 = str9 + str10;
         String str12 ="aaabbb";  
         System.out.println(str11==str12);   //输出为false
    	 
    	 
    	 
    	 
	}
     
     public void monitorCPU() throws InterruptedException{
    	 int size = 10000000;
    	 char c[] = new char[size];
    	 for (int i = 0; i < size; i++) {
    	     c[i] = 'a';
    	 }
    	 //使用带字符数组参数构造函数创建字符串时,字符串对象不会放入字符串池
    	 String str1 = new String(c);
    	 System.out.println("String字符串对象创建完毕...");
    	 Thread.sleep(5000);
    	 str1.intern();//到里会看见内存增加
    	 System.out.println("第一次调用intern()完毕...");
    	 Thread.sleep(5000);
    	 str1.intern();//再过5秒将看不到内存增长,因为池中有了,不会再放入,所以内存无变化
    	 System.out.println("第二次调用intern()完毕...");
    	 Thread.sleep(5000);
     }
     
}

 

分享到:
评论

相关推荐

    字符串使用情况查询,类型和内容可选

    在IT行业中,字符串是编程语言中最基本且至关重要的数据类型之一。它们被广泛用于存储文本信息,例如用户输入、日志记录、文件路径等。"字符串使用情况查询"工具就是为了帮助开发者更有效地管理和查找项目中字符串的...

    Java工程师必知必会.docx

    20. 使用Messageformat处理包含占位符的字符串 21. 使用类文件代替资源文件 22. 使用NumberFormat格式化数字 23. 使用DateFormat格式化日期、时间 24. 使用SimpleDateFormat格式化日期 Java集合概: 1. Collection...

    500道Java后端面试必知必会-V1版.pdf

    1. Java基础知识点:包括数据类型、运算符、流程控制、数组、字符串处理等。Java的集合框架也是必须熟练掌握的,这包括List、Set、Map等接口及其实现类,以及它们的工作原理和适用场景。 2. 异常处理:理解和掌握...

    JAVA标识符关键字和数据类型.ppt

    所有Java关键字都是小写英文字符串。goto和const虽然从未使用,但也作被为Java关键字保留。Java关键字包括: * 原始数据类型:byte、short、int、long、float、double、char、boolean * 循环关键字:do、while、for...

    JAVA核心知识点整理——java自学资料.rar

    1. **基础语法**:包括数据类型、变量、运算符、流程控制(if/else、switch、for、while)、数组、字符串和异常处理等。这些都是Java编程的基础,对于理解和编写任何Java程序至关重要。 2. **面向对象编程**:Java...

    j2se课程笔记蕴含了大量的JAVA重要知

    String类提供了许多实用方法,如concat()用于连接字符串,substring()用于截取子串,indexOf()用于查找子串位置等。此外,字符串常量池也是String的一个重要特性,它提高了程序性能。 2. **方法重载(Overload)**:...

    C++必知必会_c++类型转换_C++字符pdf_Vc_

    总的来说,《C++必知必会》这本书涵盖了C++编程中的关键概念,包括类型转换、字符串处理、VARIANT、内存管理和异常处理,以及指针和引用的基础知识。通过深入学习这些内容,开发者能够更好地理解C++的特性和用法,...

    java基础语法

    - 字符串连接符:`+`,可以将字符串与其他类型的数据拼接。 - 三目运算符:`X ? Y : Z`,条件表达式,根据`X`的结果选择`Y`或`Z`。 以上内容详细介绍了Java的基础语法和相关知识点,包括JDK的安装与配置、Java...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    9.2.6 在字符串中查找子字符串或字符 226 9.2.7 替换字符串中的内容 226 9.2.8 String对象——磐石刻字 227 9.3 String类的最佳拍档——StringBuffer类 227 9.3.1 StringBuffer:专业操纵字符 228 9.3.2 String...

    java基本语法1

    Java 中的关键字是赋予特定的含义,有专门用途的字符串。全部为小写。保留字是没有定义用途,但保留备用的字符串。例如 goto、const 等。 Java 的基本数据类型有八种:布尔型、字符型、整数型、浮点数型等。整数型...

    Java入门讲解.pdf

    Java的字符串是不可变的,这意味着每次对字符串的操作都会创建新的字符串对象。 总的来说,Java入门需要掌握这些基础概念,包括语法、数据类型、变量、注释、运算符以及命名规范,这些都是构建复杂Java程序的基石。...

    利用java反射、注解及泛型模拟ORM实现

    这可以使用模板引擎或字符串拼接实现。 4. **执行SQL**:使用Java的JDBC API执行SQL,处理结果集,并将数据转换为Java对象,或将Java对象转换为数据库记录。 5. **泛型接口**:创建泛型的DAO接口,如`GenericDAO...

    JAVA SE6.0 API文档

    例如,`List&lt;String&gt;`表明列表只能包含字符串对象。 2. **枚举**:Java 6引入了枚举类型,这是一种特殊的类,用于定义有限的固定数量的实例。枚举在处理常量集合时非常有用,如`enum Days {SUN, MON, TUE, WED, THU...

    java基础笔记

    Java中的字符串默认为Unicode编码。 6. 函数(也称为方法)是Java中的代码块,可以包含可执行语句序列,接收参数,并可能返回值。函数的定义包括访问修饰符、返回类型、方法名、参数列表和方法体。在Java中,函数的...

    Java最常见200面试必备题.pdf

    对于String类型,由于JVM进行了特殊处理,使用“==”比较时,如果两个字符串变量指向的是同一个对象,结果为true,否则为false;而使用“equals”方法比较,总是比较字符串的内容。 文档还提到将按技能模块划分文章...

    JAVA初学者在学习的过程中总是会遇到一些很疑惑的问题

    通过上面的说明,我们可以知道,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用 String 来代表字符串的话会引起很大的内存开销。因此,在这种情况下,应该考虑使用 StringBuffer类,它允许...

Global site tag (gtag.js) - Google Analytics