String基础: String两种创建对象方式的比较
- 字符串常量
在一般的语言中常量一旦声明则不可改变,在java中的字符串常量是以匿名对象来表示的
javaz中字符串两种定义方法:
- String strA= new String("hello");(符合习惯的声明方法)
- 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两种创建对象方式的比较的更多相关文章
- 【转载】 Java中String类型的两种创建方式
本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...
- String变量的两种创建方式
在java中,有两种创建String类型变量的方式: String str01="abc";//第一种方式 String str02=new String("abc&qu ...
- String类对象两种实例化方式比较
第一种:直接赋值 String str = "hello!" ; 在java中,有一个字符串常量池,对于这种直接赋值的,会直接写进常量池(常量池里面不存在其value,) 自JD ...
- Thead基础及两种创建方式
今天本人给大家讲解一下多线程,如有不对的或者讲的不好的可以多多提出,我会进行相应的更改,先提前感谢提出意见的各位了!!! 说说多线程本人自己对它理解的定义:因计算机的CPU支持能够在同一时间执行多于一 ...
- js两种创建对象方式
js创建方法的两种方式 <%@ page language="java" contentType="text/html; charset=ISO-8859-1&qu ...
- String中的两种实例化方式的区别
直接赋值:(String str = "字符串");只会开辟一块堆内存空间,并且会自动保存在对象池中以供下次重复使用. 构造方法:(String str = new String ...
- 菜鸡的Java笔记 第十三 String 类的两种实例化方法
String 类的两种实例化方法 String 类的两种实例化方式的区别 String 类对象的比较 Stirng 类对象的使用分析 /* 1.String 类的两种实例化方式的区别 ...
- Java中String对象两种赋值方式的区别
本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...
- 关于String的两种赋值方式
String的两种赋值是不同的,String str1=“hello”,指向堆内存中的"hello",而String str2=new String("hello&quo ...
随机推荐
- 论文解读(NWR)《Graph Auto-Encoder via Neighborhood Wasserstein Reconstruction》
论文信息 论文标题:Graph Auto-Encoder via Neighborhood Wasserstein Reconstruction论文作者:Shaked Brody, Uri Alon, ...
- springboot中,子项目的boot依赖全部爆红
应仔细检查父项目的dependencyManagement是否指定了打包方式<type>为pom,<scope>为import
- 【Java】学习路径55-练习:制作一个聊天室(多线程、UDP、双向传输数据)
创建四个类,实现双向聊天的功能. 接收线程: import java.io.IOException; import java.net.*; public class ReceiveThread imp ...
- 解决QIcon引用qrc不显示图片
引用Qrc 对于Qt来说,添加qrc之后,可以使用":"来直接访问qrc的文件,比如 QIcon icon(":/icon/red.png"); 绝对路径 当然 ...
- 创建swarm集群并自动编排
1.基础环境配置 主机名 master node1 node2 IP地址 192.168.***.1 192.168.***.2 192.168.***.3 角色 管理节点 工作节点 工作节点 ...
- FastJson远程命令执行漏洞学习笔记
FastJson远程命令执行漏洞学习笔记 Fastjson简介 fastjson用于将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean.fastjson.ja ...
- winform,水晶报表制作
1.安装最新的 SP:(SP 29 示例 – https://origin.softwaredownloads.sap.com/public/file/0020000001636412020) 2.新 ...
- Windows Server体验之管理
安装了只有命令行界面的Windows Server之后怎么去管理,对于传统的Windows管理员来说确实是比较棘手的.因为没有了图形化的管理界面,需要更多的去依赖Powershell或者cmd命令去做 ...
- .NET 7 来了!!!
.NET 7 首个RC(发布候选)版本 最近 .Net 的大事件,就是微软发布了.NET 7的首个RC(发布候选)版本,而据微软发布的消息,这是 .NET 7 的最后一个预览版,下一个版本将是第一个候 ...
- K8S容器HeadlessService间动态IP通信
文件网址:https://www.kubebiz.com/KubeBiz/MongoDB?k8sv=v1.20 使用文件网址中提供的yaml文件安装三节点的mongodb集群,其service是hea ...