今天课堂测试做了几道String的练习题,做完直接心态爆炸......

整理自下面两篇博客:

首先先来看看下面的代码:

public classStringTest {public static voidmain(String[] args){

String s1="Hello";

String s2="Hello";

String s3=new String("Hello");

System.out.println("s1和s2 引用地址是否相同:"+(s1 ==s2));

System.out.println("s1和s2 值是否相同:"+s1.equals(s2));

System.out.println("s1和s3 引用地址是否相同:"+(s1 ==s3));

System.out.println("s1和s3 值是否相同:"+s1.equals(s3));

}

}

打印结果如下:

s1和s2 引用地址是否相同:trues1和s2 值是否相同:trues1和s3 引用地址是否相同:falses1和s3 值是否相同:true

我们可以看到 在java中,比较String有两种方式,一种是用"==",另一种是用s.equals()方法。

那么这两种方法有什么不同呢?

上面程序中的"=="是判断两个对象引用的地址是否相同,也就是判断是否为同一个对象,s1与s2 返回为true,s1与s3返回则是false。说明s1与s2 引用的同一个对象的地址,s3则与其它两个引用不是同一个对象地址。

而s.equals()方法则是判断字符串的内容是否相等,只要内容相等就返回true,当然,地址相等就更不用说了,肯定返回true。

Java为了避免产生大量的String对象,设计了一个字符串常量池。工作原理是这样的,创建一个字符串时,JVM首先为检查字符串常量池中是否有值相等的字符串,如果有,则不再创建,直接返回该字符串的引用地址,若没有,则创建,然后放到字符串常量池中,并返回新创建的字符串的引用地址。所以上面s1与s2引用地址相同。

那为什么s3与s1、s2引用的不是同一个字符串地址呢?

注意看 s3的定义方法:

String s3=new String("Hello");

JVM首先是在字符串常量池中找"Hello" 字符串,如果没有创建字符串常量,然后放到常量池中,若已存在,则不需要创建;当遇到 new 时,还会在内存(不是字符串常量池中,而是在堆里面)上创建一个新的String对象,存储"Hello",并将内存上的String对象引用地址返回,所以s3与s1、s2引用的不是同一个字符串地址。 内存结构图如下:

从内存图可见,s1与s2指向的都是常量池中的字符串常量,所以它们比较的是同一块内存地址,而s3指向的是堆里面的一块地址,说的具体点应该是堆里面的Eden区域,s1跟s3,s2跟s3比较都是不相等的,都不是同一块地址。

拓展问题:

请问String s = new String("xyz");产生了几个对象?

在String的工作原理中,已经提到了,new一个String对象,是需要先在字符串常量中查找相同值或创建一个字符串常量,然后再在内存堆中创建一个String对象,所以String s = new String("xyz"); 会创建两个对象。

下面看几道习题:

1、

public classTest {public static voidmain(String[ ] args) {

String s1= new String("Welcome to Java!");

String s2= new String("Welcome to Java!");if (s1 ==s2)

System.out.println("s1 and s2 reference to the same String object");elseSystem.out.println("s1 and s2 reference to different String objects");

}

}

s1 and s2 have different contents

虽然常量池中已经存在"Welcome to Java!"了,但s2 new 时,还会在内存(不是字符串常量池中,而是在堆里面)上创建一个新的String对象,存储"Welcome to Java!",并将内存上的String对象引用地址返回给s2,所以s1和s2引用地址不同。

2、

public classTest {public static voidmain(String[ ] args) {

String s1= "Welcome to Java!";

String s2=s1;if (s1 ==s2)

System.out.println("s1 and s2 reference to the same String object");elseSystem.out.println("s1 and s2 reference to different String objects");

}

}

s1 and s2 reference to the same String object

常量池中已经存在"Welcome to Java!"了,不需要再创建,直接返回该字符串的引用地址给s2,所以s1和s2有相同的引用地址。

再来看这样一个问题:

public classTest {public static voidmain(String[] args) {

String s1= "hello";

String s2= "world";

String s3= "helloworld";

System.out.println(s3== s1 + s2);//false

System.out.println(s3.equals((s1 + s2)));//true

System.out.println(s3 == "hello" + "world");//ture

System.out.println(s3.equals("hello" + "world"));//true

}

}

equals()比较方法不解释,比较值,均相等,均为true。

s1与s2相加是先在字符串常量池中开一个空间,然后拼接,这个空间的地址就是s1与s2拼接后的地址。与s3的地址不同,所以输出为false。

s3与”hello”+”world”作比较,”hello”+”world”先拼接成”helloworld”,然后再去字符串常量池中找是否有”helloworld”,有,所以和s3共用一个字符串对象,则为true。

总结:

String s = new String(“hello”)会创建2(1)个对象,String s = “hello”创建1(0)个对象。

注:当字符串常量池中有对象hello时括号内成立!

字符串如果是变量相加,先开空间,在拼接。

字符串如果是常量相加,是先加,然后在常量池找,如果有就直接返回,否则,就创建。

java new string 图_Java中String直接赋字符串和new String的一些问题相关推荐

  1. java 数组 length 减少_java中数组有没有length()方法?string没有lenght()方法?

    java中数组有没有length()方法,求数组的长度可以使用数组的length属性. int length=arr.length;//求数组的长度 ------------------------- ...

  2. java如何获取手机号码_java中如何提取一个字符串中的电话号码?

    展开全部 java中如何提取一个字符串中的电话号码e68a84e8a2ad3231313335323631343130323136353331333363376466,先写出手机号码和固定号码的正则表 ...

  3. java stringbuffer长度限制_Java中的String、StringBuffer和StringBuilder

    作为作为一个已经入了门的java程序猿,肯定对Java中的String.StringBuffer和StringBuilder都略有耳闻了,尤其是String 肯定是经常用的.但肯定你有一点很好奇,为什 ...

  4. java中string类_Java中String类浅谈

    1)String对象的初始化 由于String对象特别常用,所以在对String对象进行初始化时,Java提供了一种简化的特殊语法,格式如下:      String s = "abc&qu ...

  5. java string类型_java中String类型

    String类型是字符串类型..字符串一旦创建不可以在改变."abc"字符串对象一旦创建,不可以再改成"abcd" 提升字符串的访问效率:在程序中使用了&quo ...

  6. java new string作用_java中直接new String对象?

    首先明确一点,在Java中==比较的是两个对象的地址,equals()比较的是两个对象的值,如果使用equals()来替换==,则两个输出结果都为true. 言归正传,为什么第一个返回为false? ...

  7. Java中string与String区别_JAVA中String与StringBuffer的区别

    JAVA中String与StringBuffer的区别 2009-12-3文字大小:大中小 在java中有3个类来负责字符的操作. 1.Character 是执行 单个字符操作的, 2.String ...

  8. java中string范围_java中long parseLong(String s)方法中string(十进制数字)的范围?

    java中long parseLong(String s)方法中string(十进制数字)的范围? 來源:互聯網  2009-06-19 05:05:28  評論 分類: 電腦/網絡 >> ...

  9. java的string类_Java中的String类笔记

    说明 源码 //jdk8 public final class String implements java.io.Serializable, Comparable, CharSequence { / ...

最新文章

  1. Ubuntu快速重装软件的技巧
  2. web安全_皮卡丘_xss
  3. 中国宜坚持发展自主操作系统
  4. Java基础5一数组的常见应用算法
  5. springMVC中添加命名空间(edit namespace)
  6. 编程利器 Beyond Compare 的使用
  7. 机器学习中的概率模型和概率密度估计方法及VAE生成式模型详解之二(作者简介)...
  8. NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译
  9. VMware Fusion CentOS7 下载安装及手动配置静态IP
  10. 使用arecord、aplay命令实现音频的采集和播放
  11. APICloud常用
  12. 安卓和ios的ui设计区别_UI设计中IOS和安卓的设计差异
  13. re正则表达式必备基础知识
  14. 机柜风扇 的组成及如何正确安装 机柜散热风扇
  15. 从感知机到Transformer,一文概述深度学习简史
  16. 【计算机网络】谢希仁笔记 运输层
  17. JSP程序+tomcat服务器如何禁止客户端访问非页面形式路径
  18. phprm=20161221
  19. 金融粉去哪里引流?哪个平台做金融引流好?贴吧精准引流金融粉技巧
  20. OpenHarmony开源鸿蒙与HarmonyOS商业鸿蒙的区别

热门文章

  1. 浅谈Transformer 及Attention网络
  2. Pytorch的LSTM的理解
  3. Redis缓存穿透击穿雪崩
  4. 通过 DLPack 构建跨框架深度学习编译器
  5. 用户自定义协议client/server代码示例
  6. AlexeyAB DarkNet YOLOv3框架解析与应用实践(五)
  7. 2021年大数据ZooKeeper(五):ZooKeeper Java API操作
  8. Python数据挖掘1:创建一位数组和二维数组,取最大最小值,切片
  9. Kotlin let、with、run、apply、also函数的使用
  10. 2017-2018-1 20155204 《信息安全系统设计基础》第十一周学习总结