• 字符串常量

在一般的语言中常量一旦声明则不可改变,在java中的字符串常量是以匿名对象来表示的

javaz中字符串两种定义方法:

  1. String strA= new String("hello");(符合习惯的声明方法)
  2. String strA="hello";(常用的声明方法)

一个基本事实:在java中字符串常量的本质是String类型的匿名对象

  • 基本解释:习惯的定义方法和前面的一样,常用的定义方法中,将用于储存匿名对象"hello"的堆空间的使用权交给strA,strA指向该匿名空间

其实这里聪明的小伙伴已经发现了两者的差异了,在习惯声明的方式中,"hello"不仅是作为匿名对象,还会为new关键字开辟的对象所赋值

所有说习惯性的声明方法开辟了2次的内存空间

小插曲---分析字符串的比较

了解完上面的概念,对应字符串的比较就没有什么压力了

例子的引出

 //分析字符串中==运算符
public class Compare{
public static void main(String[]args){ String strA="yootk";
String strB=new String("yootk");
String strC=strB;//进行引用传递指向strB所指向的堆地址
System.out.println(strA==strB);//false
System.out.println(strC==strB);//true
System.out.println(strA==strC);//false }
}

内存指向分析

从前面的分析和空间的内存分析可以看出==运算符在字符串中是直接进行地址的比较的,其实也不难理解strA strB strC是该类对象的引用,储存的是对应的堆空间的地址,直接这样比较不就是比较地址吗

得到一个结论:==运算符在java中用于对象地址的比较

进行字符串内容的比较可以用String类的内置函数 equals()

该函数定义方式:Public boolean equals(String str)

根据两字符串的数值是否相等返回false或者true

 //分析字符串中==运算符
public class Compare{
public static void main(String[]args){ String strA="yootk";
String strB=new String("yootk");
String strC=strB;//进行引用传递指向strB所指向的堆地址
System.out.println("yootk".equals(strB));//true
System.out.println("yootk".equals(strB));//true
System.out.println("yootk".equals(strC));//true }
}

用equals完美的解决了问题,同时可以发现equals()函数是由"yootk"来调用的,也可以验证字符串常量就是一个匿名对象

建议当字符串常量和字符串变量在进行equals比较时,用字符串常量进行equals函数的调用,也就是将常量写在前面

原因:当输入的字符串没有进行实例化或者说没有被赋值的时候,此时字符串=null,此时如果进行equals方法的调用,就会出现空指针异常

public class Compare{
public static void main(String[]args){
String strA=null;
//后面没有进行实例化
System.out.println(strA.equals("hello"));
}
}

解决:用字符串常量进行equals方法调用,字符串常量本质上就是一个匿名对象永远不可能为空

public class Compare{
public static void main(String[]args){
String strA=null; System.out.println("hello".equals(strA));//false 该处输入的strA为 空直接返回false
}
}

而且还有一个好处:equals()方法内部会自动进行Null的判断,所有这个时候如果发现输入的内容为空则直接返回false

两种声明方式的比较

问题的引出

public class Compare{
public static void main(String[]args){
String strA="yook.com";
String strB="yook.com";
System.out.println(strA==strB);//true
System.out.println(strB=="yook.com");//true
}
}

两个对象的地址相同,说明strA和strB都指向同一个对象

此时内存结构如图:

对于该情况的解释:



该处就相当于strB=strA 进行了引用传递 而没有开辟新的堆空间

用这种设计可以看出,当定义的多个常量值相同的时候都使用的是同一个对象,可以极大的节省内存空间的使用

分析:String strA=new String("hello")

用这种方式来定义字符串,前面已经解释了"hello"是一个匿名对象,当存在一个匿名对象会自动开辟一个堆空间储存hello,然后又通过new关键字开辟了一次堆空间,"hello"为堆空间赋值然后将new开辟的堆空间的地址给strA

可以从上述的分析中可以看到这种方式定义的字符串会多开辟一段空间,多开辟的空间将成为垃圾空间,会造成性能问题

通过new关键字声明的字符串不会进入常量共享池,java提供了一个手工入池的操作



总结:

分析:字符串常量池

*静态常量池举例*
public class Compare{
public static void main(String[]args){
String strA="helloworld";
String strB="hello"+"world";
System.out.println(strA==strB);//true
}
}

动态常量池举例

public class Compare{
public static void main(String[]args){
String strA="hello";
String strB=strA+"world";
String strC="helloworld";
System.out.println(strB==strC);//false
}
}

如果以后编写字符串过长的时候用+链接最方便

public class Compare{
public static void main(String[]args){
String strA="today "+" is"+ " a" +" good"+ " day!";
System.out.println(strA);
}
}

此时的程序是不会产生多个对象的,仅仅形成一个字符串常量,不影响程序的性能

String基础: String两种创建对象方式的比较的更多相关文章

  1. 【转载】 Java中String类型的两种创建方式

    本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...

  2. String变量的两种创建方式

    在java中,有两种创建String类型变量的方式: String str01="abc";//第一种方式 String str02=new String("abc&qu ...

  3. String类对象两种实例化方式比较

    第一种:直接赋值 String str =  "hello!" ; 在java中,有一个字符串常量池,对于这种直接赋值的,会直接写进常量池(常量池里面不存在其value,) 自JD ...

  4. Thead基础及两种创建方式

    今天本人给大家讲解一下多线程,如有不对的或者讲的不好的可以多多提出,我会进行相应的更改,先提前感谢提出意见的各位了!!! 说说多线程本人自己对它理解的定义:因计算机的CPU支持能够在同一时间执行多于一 ...

  5. js两种创建对象方式

    js创建方法的两种方式 <%@ page language="java" contentType="text/html; charset=ISO-8859-1&qu ...

  6. String中的两种实例化方式的区别

    直接赋值:(String str = "字符串");只会开辟一块堆内存空间,并且会自动保存在对象池中以供下次重复使用. 构造方法:(String str = new  String ...

  7. 菜鸡的Java笔记 第十三 String 类的两种实例化方法

    String 类的两种实例化方法 String 类的两种实例化方式的区别 String 类对象的比较 Stirng 类对象的使用分析 /*    1.String 类的两种实例化方式的区别       ...

  8. Java中String对象两种赋值方式的区别

    本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...

  9. 关于String的两种赋值方式

    String的两种赋值是不同的,String str1=“hello”,指向堆内存中的"hello",而String str2=new String("hello&quo ...

随机推荐

  1. CSS 标签、类名和ID选择器有空格和没有空格的区别

    前言 标签选择器.类名选择器以及 ID 选择器在使用上要注意"加空格"和"不加空格".两种使用形式上有很大的差别. 下面是讲解案例的 HTML 代码: < ...

  2. Excelize 2.3.1 发布,Go 语言 Excel 文档基础库,支持加密表格文档

    Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准.可以使用它来读取.写入由 Microsoft Exc ...

  3. java数组---数组的使用(打印,求和,最大值)

    public static void main(String[] args) { int[] arrays={1,2,3,4,5}; //打印该数组 for (int i = 0; i < ar ...

  4. Math_Music

    查看代码 #REmoo的优化任务 #1.公式写在<formula_set>类中,统一管理 --- Finished 2022.8.15 12:39 #2.建立<sample_set& ...

  5. QFile 对文件进行读写操作

    QFile 对文件进行读写操作 1 QFile 进行读写操纵 2 QFile file(pah ) 文件路径 3 读  file.open(打开方式)  file.readAll(). file.re ...

  6. 第三十一篇:vue3和vue2的不同

    好家伙 1.为什么会有vue3? Vue2和Vue3的区别 - 简书 (jianshu.com) 貌似是因为他的对手太优秀,所以他也必须进步 2.什么是api? 从文件操作开始谈API. 以C语言为例 ...

  7. docker 匿名和具名挂载

    匿名挂载,只指定容器内了,没指定容器外 -v 容器内路径 docker run -d -P --name nginx01 -v /etc/nginx nginx #-P 随机映射端口 ; -v 不指定 ...

  8. 闭包 与 js内存管理

    参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management            https://blog ...

  9. KingbaseES 数据库大小写敏感特性

    针对不同版本.是否启用大小写敏感,特征汇总如下:

  10. Python实践项目——LSB隐写术

    此为北京理工大学某专业某学期某课程的某次作业 一.项目背景 1.隐写术 隐写术是一门关于信息隐藏的技巧与科学,所谓信息隐藏指的是不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容. 2.L ...