• 字符串常量

在一般的语言中常量一旦声明则不可改变,在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. Dynamic CRM使用FetchXML在js中查询与调用传递编码问题

    在页面交互脚本js中实现窗体交互逻辑是很常见的crm场景,一般情况下使用拓展工具RESTBuilder编辑器,可以很方便的进行操作,增删改查均能实现,但在某些较为特殊的场景下,需要根据条件去拼接查询过 ...

  2. VS2019 Community社区版登录提示:我们无法刷新此账户的凭证 解决方法

    最正确的方式: 1.点击 帮助-->发送反馈-->报告问题 2.点击 检查新的许可证 ,即可登陆成功 3.如果提示:无法下载或者下载失败. 4.那么就需要在左边 账户选项 中将 嵌入式We ...

  3. Codeforces Round #604 (Div. 2) -D

    Problem - D - Codeforces 题意 : 有 a 个0,b个1,c个2,d个3,构成一个序列,使得每两个数字之间的差值为1 题解: 就是以四种数字分别为起点,暴力模拟 #includ ...

  4. Docker网络讲解 及实验redis集群部署

    理解docker0 准备工作:清空所有的容器,清空所有的镜像 docker rm -f $(docker ps -a -q) # 删除所有容器 docker rmi -f $(docker image ...

  5. MFRC522学习笔记

    MFRC522主要特性 容量为8K位(bits)=1K字节(bytes)EEPROM 分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位 每个扇区有独立的一组密码及访问控制 每张卡有唯一序 ...

  6. Postman中的Pre-request Scrip详解

    Postman中的Pre-request Scrip详解 一.Pre-request Scrip的简介 1.Pre-request Script是在请求发送之前需要执行的代码片段: 2.请求参数中包含 ...

  7. 三分钟,带你了解PLM

    PLM应用于单一地点或者多个地点的企业内部.以及在产品研发领域具有协作关系的企业之间的.支持产品全生命周期的信息的创建.管理.分发和应用的综合性的应用解决方案,能够集成与产品相关的流程.应用系统和信息 ...

  8. WSUS连接错误需要重置服务器

    在WSUS完成部署后,总是遇到控制台错误,提示需要重置服务器节点.https://www.cnblogs.com/qishine/p/12727982.html错误:连接错误尝试连接WSUS服务器时出 ...

  9. 我的Vue之旅、04 CSS媒体查询完全指南(Media Quires)

    什么是SCSS Sass: Sass Basics (sass-lang.com) SCSS 是 CSS 的预处理器,它比常规 CSS 更强大. 可以嵌套选择器,更好维护.管理代码. 可以将各种值存储 ...

  10. ProxySQL(13):ProxySQL集群

    文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9362822.html ProxySQL有原生的集群功能,但是这个原生的集群功能还正在试验阶段.本文会详细介绍 ...