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 ...
随机推荐
- q 短引用标签
<q/>标签可以使一段文本作为引用. <p>他说:<q>明天要下雨</q>.</p> 注意,源代码中并没有为这段文字添加引用符号,而是添加了 ...
- 最大连续子序列(简单DP实现)
最大连续子序列 最大连续子数列和一道很经典的算法问题,给定一个数列,其中可能有正数也可能有负数,我们的任务是找出其中连续的一个子数列(不允许空序列),使它们的和尽可能大.我们一起用多种方式,逐步优化解 ...
- 1.1_selenium+Python自动化测试大纲
- 理解C++函数指针和指针函数(一)
函数指针 实际上使用最多的还是指针函数,但我们还是可以先看看函数指针 奇怪的是,大家搜索指针函数,或者Pointer function,出来的还是函数指针的链接. OK,废话不多说,先给大家举个例子. ...
- good thing
- 使用man手册查看内核函数
1.为避免man的一些功能缺失,先装好manpages-dev sudo apt-get install manpages-dev 2.安装mandocs的依赖包xmlto sudo apt-get ...
- KingabseES 锁机制
KingabseES的锁机制 目录 KingabseES的锁机制 一.前言 二.锁机制 三.表级锁 ( Table-Level Locks ) 1.访问共享(ACCESS SHARE) 2.行共享(R ...
- 【读书笔记】C#高级编程 第十四章 内存管理和指针
(一)后台内存管理 1.值数据类型 Windows使用一个虚拟寻址系统,该系统把程序可用的内存地址映射到硬件内存中的实际地址,该任务由Windows在后台管理(32位每个进程可使用4GB虚拟内存,64 ...
- [Python]-opencv-python模块(cv2)-图片读取和格式转换
python常常用opencv模块来处理图像. import cv2 as cv 读取图片:imread() 默认按照彩色三通道读取: img = cv2.imread(path) 读取灰度图: im ...
- 1 Java内存区域管理
目录 1 关于自动内存管理 2 运行时数据区域 2.1 程序计数器 2.2 虚拟机栈 2.2.1 局部变量表 2.2.2 操作数栈 2.3 本地方法栈 2.4 堆 2.5 方法区 2.5.1 运行时常 ...