java常量池和字符串常量池_java声明常量

java常量池和字符串常量池_java声明常量本篇文章带大家认识Java基础知识——字符串类,在前面我们已经知道如何在Java中定义字符串,本文将介绍Java字符串中的字符串常量池,探究字符串相等问题。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

⭐️前面的话⭐️

本篇文章带大家认识Java基础知识——字符串类,在前面我们已经知道如何在Java中定义字符串,本文将介绍Java字符串中的字符串常量池,探究字符串相等问题。

?博客主页:未见花闻的博客主页
?欢迎关注?点赞?收藏⭐️留言?
?本文由未见花闻原创,CSDN首发!
?首发时间:?2021年12月1日?
✉️坚持和努力一定能换来诗与远方!
?参考书籍:?《Java核心技术》,?《Java编程思想》,?《Effective Java》
?参考在线编程网站:?牛客网?力扣
博主的码云gitee,平常博主写的程序代码都在里面。
博主的github,平常博主写的程序代码都在里面。
?作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!



java常量池和字符串常量池_java声明常量0


1.字符串的创建

在Java当中,使用String类来表示,”abc”是一个字符串常量,是String类对象,String类是一种引用类型,其引用变量可以指向String类的对象,如果需要创建一个字符串对象,有以下3种方法:

public class CreatTest { 
   
    public static void main(String[] args) { 
   
        //字符串创建
        String str1 = "CSDN";//方法1
        String str2 = new String("weijianhuawen");//方法2
        char[] ch = { 
   'j','a','v','a'};
        String str3 = new String(ch);//方法3

        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);
    }
}

方法1:直接定义String类引用变量指向一个字符串常量对象。
方法2:使用new创建一个新的字符串对象,传入构造函数的参数类型为String。
方法3:使用new创建一个新的字符串对象,传入构造函数的参数类型为字符数组。
1-1
字符串类是引用变量,在一个方法中修改引用的值是无效的,因为方法里面的引用变量是局部变量,作用域是在方法内。区别与数组,利用[]形式访问的数组对象的内容,并不是引用变量的值,所以数组利用[]修改是有效的。

public class Test2 { 
   
    public static void func(String str, char[] ch) { 
   
        str = "bili";
        ch[0] = 'w';
    }
    public static void main(String[] args) { 
   
        String s = "csdn";
        char[] c = { 
   'a', 'b', 'c'};
        System.out.println(s);
        System.out.println(c);
        System.out.println("=================");
        func(s, c);
        System.out.println(s);
        System.out.println(c);
    }
}

1-2
jdk1.8版本中String类的本质是char[],这一点可以通过访问String源码能够观察到。
1-3
我们发现这个字符数组是被private final修饰的,因此字符串是不可变对象,因为你无法获取和修改这个对象。

2.字符串相等问题

2.1字符串常量池

在Java中为了提高效率,引入了常量池,那什么是常量池呢?常见的常量池有class文件常量池,运行时常量池,字符串常量池等。

这个“池”怎么理解呢?打个比方,你的女朋友想要吃瓜子,然后你剥瓜子,你事先把瓜子剥到一个盘中,然后你的女朋友要吃瓜子的时候可以从这个盘子中取,不需要等待你把剥瓜子剥完,这个盘就是这里所谓的“池”,使用“池”能够提高程序运行的效率。

class文件常量池储存在磁盘上,编译后形成的字节码文件,原本定义的很多基本类型常量,比如int a = 2,这个2就被放在了这个常量池当中。
运行时常量池,当程序把编译好的字节码文件加载到JVM后,会形成一个运行时常量池,也称为方法区,实际上是class文件常量池。
字符串常量池,主要存放字符串常量,本质上是一个哈希表,直接使用双引号""声明定义的字符串常量都会被存入字符串常量池当中去,jdk1.8后使用new新建的String对象也会存入常量池中。

刚刚说到了哈希表,那哈希表是什么呢?哈希表是一种数据结构,是描述和组织数据的一种方式,本质上哈希表就是一个数组,在存储数据的时候会根据一个映射关系将数据存储在数组当中,这个映射关系就叫做哈希函数,当然也有可能存在多个数据通过哈希函数映射后,得到在数组中的位置是一样的,这时就引发了哈希冲突,解决哈希冲突常用的方法就是使用链表,也就是说哈希表里面数组类型为链表,数组中存放的是链表的首元素的地址。这里简单认识一下,后面介绍数据结构时专门讲解哈希表。
1-4

2.2字符串引用相等的判断

了解了字符串常量池就能来分析String引用是否相等了。

public class Test3 { 
   
    public static void main(String[] args) { 
   
        String str1 = "csdn";
        String str2 = "csdn";
        System.out.println(str1 == str2);//(1)
        System.out.println("============");
        String str3 = new String("csdn");
        System.out.println(str1 == str3);//(2)
        System.out.println("=============");
        String str4 = "cs" + "dn";
        System.out.println(str1 == str4);//(3)
        System.out.println("============");
        String str5 = "cs";
        String str6 = str5 + "dn";
        System.out.println(str1 == str6);//(4)
    }

(1):定义str1时,检查字符串csdn是否入池,发现没有入池,先将字符串入池,然后将该字符串对象地址赋值给str1,定义str2时,检查字符串csdn是否入池,发现已经入池,直接将已经入池的字符串对象地址赋值给str2,所以str1str2引用的值是相等的,所以输出true
1-5

(2):定义str3时,会先新建一个String对象,然后检查字符串csdn是否入池,如果没入池则入池,再将入池后的对象的内容拷贝给新建的String对象,当然在这个栗子csdn是已经入池了的,则直接将该对象的内容拷贝给新建的String对象。很明显,str1str3的引用值是不同的,所以输出false
1-6
(3):定义str4时,编译时就会把csdn拼接为csdn,所以编译后str4得到的就是csdn对象的地址,这就与栗子(1)一样了,会先去常量池里找,常量池中有该字符串,所以str4的引用值与str1相等,结果输出true
1-7
1-8
(4):定义str5时,会将字符串cs入池,因为str5是一个变量,编译时期不会将两字符串拼起来,所以定义str6时会将dn入池,运行时会使用StringBuilder类将两个字符串进行拼接(该类在后面详细介绍),会得到一个新对象,该对象中存有拼接后的字符串csdn,注意使用拼接得到的字符串不会自动入池。所以str1str6的值不相等,输出false
1-9
1-10
1-11
当然除了自动入池,还可以手动入池,可以使用 i n t e r n ( ) intern() intern()方法手动入池。

2.3字符串内容相等的判断

判断两个字符串内容是否相等,使用string类中的equals方法,下图为该方法的源码。(Object类是所有类的父类,所以Object变量可以接受所以类的引用变量)
1-12
对于源码实现的思路不细说,重点是知道如何使用它。

public class Test4 { 
   
    public static void main(String[] args) { 
   
        String str1 = "weijianhuawen";
        String str2 = "WJHW";
        String str3 = "weijianhuawen";
        System.out.println(str1.equals(str2));
        System.out.println(str1.equals(str3));//将确定不为null的对象放前面,可防止空指针异常,但是这样做有时候会忽略方法内对象为null的情况
        System.out.println(str1.equals(null));
    }
}

1-13

2.4理解字符串内容不可变

我们根据源码知道字符串本质上就是一个字符数组。但是这个数组被private final修饰,我们不能访问和修改,所以字符串内容是不可变的,如果硬要改变,只能采取反射(现在了解即可,后续博文详细介绍)。
反射是面向对象编程的一种重要特性, 有些编程语言也称为 “自省”.
指的是程序运行过程中, 获取/修改某个对象的详细信息(类型信息, 属性信息等), 相当于让一个对象更好的 “认清自己”
1-14
为什么 String 要不可变?

  1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑何时深拷贝字符串的问题了。
  2. 不可变对象是线程安全的。
  3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中。


本篇文章就到这了,下一篇文章将进一步介绍字符串常用方法及StringBuilder的用法。


觉得文章写得不错的老铁们,点赞评论关注走一波!谢谢啦!

1-99

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/164780.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 5G基站产业链(5g基站天线安装视频)

    来源:国信证券5G宏基站数的翻倍增长及技术演进带来基站天线成倍增长空间。5G关键性能指标十倍的增长需要基站数翻倍增长以支撑。5G的三个关键的效率需求包括频谱利用效率、能耗…

  • keypad 按键显示

    keypad 按键显示main.c#include”config.h”//矩阵按键扫描头文件#include”anjian.h”//1602显示头文件#include”1602.h”#include”music.h”sbitLED=P1^0;u8codekey[]={‘0′,’1′,’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9′,’*’,’#’};//3*4手机拨号键盘号码u8

  • Android 开发者,你真的会用textview(maxEms和maxLength)的属性吗?

    Android 开发者,你真的会用textview(maxEms和maxLength)的属性吗?这里我们不说那些复杂的属性,光说我们通常用的比较多的,android:maxlength官网API对其的解释为:第一句,也就是说,他是个inputfilter(输入过滤器)他的作用是通过specifiednumber(你指定的数字)来限制textlength(文本长度),这里特指的是文本长度,而无论我们输入什么内容,英文,符号,数字,汉字………………这些都属于文本范围,所以ma

  • 如何成为大数据架构师_业务架构师和数据架构师

    如何成为大数据架构师_业务架构师和数据架构师要想成为架构师这几点你必须关注!架构不是一个职业而是一种能力,每一种架构师只不过是在不同的领域里面使用不同的技术,没有什么可对比,就好比如你问一个篮球明星和一个足球明星有什么区别一样!01架构师需要考虑四个问题1.确定系统干什么不干什么,也就是说系统的边界在哪里?2.确定架构内部的模块与模块之间的关系,以及模块与外部之间的关系是什么?3.架构确定以后,有能力去指导…

  • gitlab cicd配置

    gitlab cicd配置简介以前代码更新之后,我们需要手动将代码拉到测试服务器上,运行验收通过之后,再在生产环境重新弄一遍,一两个服务还算轻松,如果涉及到的服务很多的话,每一个服务都需要这样来几遍,这是一个很头疼了,为了解决这个问题,我们引入了比较简单易懂的自动化部署工具,这也是gitlab自带的CI工具gitlab-runner,该工具解决了多环境多服务手动部署繁琐问题,用自动化脚本代替人工部署,我们不需要手…

  • Java实现文件写入——IO流(输入输出流详解)[通俗易懂]

    Java实现文件写入——IO流(输入输出流详解)[通俗易懂]输入输出的重要性:     输入和输出功能是Java对程序处理数据能力的提高,Java以流的形式处理数据。流是一组有序的数据序列,根据操作的类型,分为输入流和输出流。     程序从输入流读取数据,向输出流写入数据。Java是面向对象的程序语言,每一个数据流都是一个对象,它们提供了各种支持“…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号