String对象的创建和比较

news2024/9/22 7:33:28

String类的概述

String类:代表字符串。
Java 程序中的所有字符串字面值(如 “abc” )都作 为此类的实例实现。

String是JDK中内置的一个类:java.lang.string 。
String表示字符串类型,属于引用数据类型,不属于基本数据类型 。
String 类, 创建出来的 对象, 也就是 String对象 。
String是一个final类,代表不可变的字符序列
字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
String对象的字符内容是存储在一个字符数组value[]中的。

创建String

日常创建String对象,使用的就是 2种方式 :

🧨字面量方式:
什么是字符串字面量?一个字符串字面量就是两个双引号之间的字符序列,形如“张三”、“zs”。

String str1="字面量";

new 的方式:

String str2 = new String("new");

因为String 是引用数据类型 , 所以str1str2 都是 String 引用数据类型的变量 。这两个String类型的变量存在栈里面

栈 (stack)

存储变量str1str2

栈 (stack) :

  1. 是一个先进后出的数据结构,通常用于保存方法(函数)中的参数,局部变量.
  2. 在java中,所有基本类型和引用类型都在栈中存储.
  3. 栈中数据的生存空间一般在当前scopes内(就是由{…}括起来的区域).
  4. 函数中定义的基本类型变量,对象的引用变量都在函数的栈内存中分配。
  5. 栈内存特点,数数据一执行完毕,变量会立即释放,节约内存空间。
  6. 栈内存中的数据,没有默认初始化值,需要手动设置。

然后String 类 创建的对象,也就是 new String(“new”), 也是需要有东西存。这些东西存在堆里面

堆(heap)

堆内存用来存放new创建的对象和数组。
堆内存中所有的实体都有内存地址值。

🎨创建String对象的2种方式存储情况:
new String(“ACV”) 存在里面。
String str1=“JCccc”; 也是在堆里面,但是是在堆里面的字符串常量池里面。

(现在的java版本是 jdk 8,不考虑字符串常量池的一个位置演变过程了,明确知道一点,jdk7之后,字符串常量池在堆里面 )

字符串常量池(jdk7之后)

为什么明明说好了 堆是用来存对象的,为什么又搞个字符串常量池 ? 也是存对象?

是的,JAVA 设计者确实是这样设计的。

🎈为什么有字符串常量池?

因为我们会发现 String这个引用类型,用起来基本跟其他八个基本类型 (byte、char、short、int、long、float、double、boolean)没有什么区别,甚至String还用的更多。
而且String对象,对象的使用,分配要付出时间和空间上的开销。
既然用的这么勤,我们如果搞一个缓存池给这个String, 分配过的不再分配不再开销,
是不是就能提升性能,更加合理?
所以字符串常量池出来了。

什么东西能存到字符串常量池?

String 对象 通过字面量赋值的,能进去 ,例如 String str=“张三”

再回顾一下 :
什么是字符串字面量?一个字符串字面量就是两个双引号之间的字符序列,形如“张三”、“abc”。

还有就是 通过 String提供的方法 intern() ,可以将字符串丢进去常量池里面。

调用intern方法时,如果池已包含 等于此 string 对象的字符串(通过由使用equals方法),则返回池中的字符串的对象引用。
否则,此Stringobject将添加到池中, 并返回对该String对象的引用。

理解String的不可变性

import org.junit.Test;
//String的使用
public class StringTest {
	 /*
    String:字符串,使用一对""引起来表示。
    1.String声明为final的,不可被继承
    2.String实现了Serializable接口:表示字符串是支持序列化的。
            实现了Comparable接口:表示String可以比较大小
    3.String内部定义了final char[] value用于存储字符串数据
    4.String:代表不可变的字符序列。简称:不可变性。
        体现:1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
             2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
             3. 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
    5.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
    6.字符串常量池中是不会存储相同内容的字符串的。
     */
    @Test
    public void test1(){
        String s1 = "abc";//字面量的定义方式
        String s2 = "abc";
        s1 = "hello";

        System.out.println(s1 == s2);//比较s1和s2的地址值,false

        System.out.println(s1);//hello
        System.out.println(s2);//abc

        System.out.println("*****************");

        String s3 = "abc";
        s3 += "def";
        System.out.println(s3);//abcdef
        System.out.println(s2);

        System.out.println("*****************");

        String s4 = "abc";
        String s5 = s4.replace('a', 'm');//将a替换成m
        System.out.println(s4);//abc
        System.out.println(s5);//mbc
    }
}

在这里插入图片描述

String s1 = "abc";
//首次声明,在方法区的字符串常量池中新造abc
//栈中S1指向字符串常量池中的abc
String s2 = "abc";
//声明S2时,会先在常量池中寻找是否有abc,有的话将地址赋给S2
s1 = "hello";
//再次为S1赋值,新造hello,将S1的指针指向hello

String不同实例化方式的对比

String对象的创建

String str = "hello";

//本质上this.value = new char[0];
String	s1 = new String();

//this.value = original.value;
String	s2 = new String(String original);

//this.value = Arrays.copyOf(value, value.length);
String	s3 = new String(char[] a);

String	s4 = new String(char[] a,int startIndex,int count);

在这里插入图片描述

  /*
    String的实例化方式:
    方式一:通过字面量定义的方式
    方式二:通过new + 构造器的方式

     面试题:String s = new String("abc");方式创建对象,在内存中创建了几个对象?
     两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"
 */
    @Test
    public void test2(){
        //通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
        String s1 = "javaEE";
        String s2 = "javaEE";
        //通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
        String s3 = new String("javaEE");
        String s4 = new String("javaEE");

        System.out.println(s1 == s2);//true
        System.out.println(s1 == s3);//false
        System.out.println(s1 == s4);//false
        System.out.println(s3 == s4);//false

        System.out.println("***********************");
        Person p1 = new Person("Tom",12);
        Person p2 = new Person("Tom",12);

        System.out.println(p1.name.equals(p2.name));//true
        System.out.println(p1.name == p2.name);//true
        //name的地址指向方法区

        p1.name = "Jerry";
        System.out.println(p2.name);//Tom
    }   

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/351811.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

饲养员喂养动物-课后程序(JAVA基础案例教程-黑马程序员编著-第四章-课后作业)

【案例4-2】饲养员喂养动物 记得 关注,收藏,评论哦,作者将持续更新。。。。 【案例目标】 案例描述 饲养员在给动物喂食时,给不同的动物喂不同的食物,而且在每次喂食时,动物都会发出欢快的叫声。例如&…

Native扩展开发的一般流程(类似开发一个插件)

文章目录大致开发流程1、编写对应的java类服务2、将jar包放到对应位置3、配置文件中进行服务配置4、在代码中调用5、如何查看服务调用成功大致开发流程 1、编写服务,打包为jar包2、将jar包放到指定的位置3、在配置文件中进行配置,调用对应的服务 1、编…

linux 之 ps命令介绍

哈喽,大家好,我是有勇气的牛排(全网同名)🐮 有问题的小伙伴欢迎在文末评论,点赞、收藏是对我最大的支持!!!。 前言 如过想实现对进程监控,就需要使用到ps命…

macOS 13.3 Beta (22E5219e)发布

系统介绍2 月 17 日消息,苹果今日向 Mac 电脑用户推送了 macOS 13.3 开发者预览版 Beta 更新(内部版本号:22E5219e),本次更新距离上次发布隔了 37 天。macOS Ventura 带来了台前调度、连续互通相机、FaceTime 通话接力…

Vue3+Lodash:2023年了,我依然在使用Lodash

目录 前言: 为什么选择lodash? 看看lodash的地位 如何使用lodash? 1.安装lodash 2.引入lodash 我们到底还需不需要lodash? 再举一些例子 前言: 前两天,在水群的时候,发现居然有人不知lodash&#…

OpenCV-PyQT项目实战(6)项目案例02:滚动条应用

欢迎关注『OpenCV-PyQT项目实战 Youcans』系列,持续更新中 OpenCV-PyQT项目实战(1)安装与环境配置 OpenCV-PyQT项目实战(2)QtDesigner 和 PyUIC 快速入门 OpenCV-PyQT项目实战(3)信号与槽机制 …

基于感知动作循环的层次推理用于视觉问答

title:Hierarchical Reasoning Based on Perception Action Cycle for Visual Question Answering 基于感知动作循环的层次推理用于视觉问答 文章目录title:[Hierarchical Reasoning Based on Perception Action Cycle for Visual Question Answering](…

机器学习技术:多任务学习综述!

Datawhale干货 作者:陈敬,中国移动云能力中心前言本文对多任务学习(multi-task learning, MTL)领域近期的综述文章进行整理,从模型结构和训练过程两个层面回顾了其发展变化,旨在提供一份 MTL 入门指南,帮助大家快速了解…

MySQL的锁机制详解

目录 一.概述 分类 锁的特性 二.MyISAM表锁 如何加表锁 读锁演示 写锁演示 三.InnoDB行锁 行锁特点 行锁模式 一.概述 锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。 在数据库中,除传统的计算资源(如…

常见的并发模型

介绍 常见解决并发的策略一般有两种:共享数据和消息传递 基于消息传递的实现有 CSP模型,典型的有Go语言中基于Channel的通讯Actor模型,典型的有Akka中的Actor模型 CSP模型和Actor模型的简单理解: Dont communicate by sharing…

如何使用MQTTX可视化工具

@ [TOC] 使用背景 最近在调试MQTT相关的程序,调试程序时使用的是MQTTX这个工具,它可以创建服务器连接,并且在连接后发布和订阅主题。在调试过程中总结了一些使用方法和技巧,在这里分享给大家。 MQTTX是EMQX公司推出的可视化MQTT调试工具,大家可以到官网下载使用,同时参…

技术实践干货:从零开始创建Node.js应用

作为一个程序员,我们常常会有很多想法和创意,然后用技术实现出来,这是一个很有成就感的事情。 在实践过程中,会发现很多想法都不能很好地落地,可能是技术、可能是团队氛围等等,于是就开始想着能够不能有一个…

类内默认函数

目录 前言: 1. 构造函数 1.1 概念 1.2 特性 1) 2) 2. 析构函数 2.1 概念 2.2 特性 3. 拷贝构造 3.1 概念 3.2 特征 4. 赋值运算符重载 4.1 运算符重载 4.2 赋值运算符重载 5.3 前置和后置的重载 前言: 问&#xf…

AI智能机器人,在这里也可以体验~

“大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂。”现在是:2023年2月17日00:14:42前言最近AI智能chatgpt特别的火,相信好多人都已经体验过了,之前我的群里也接入过,奈何总是收到警告和限制…

泛微发布内外协同的客服管理系统-睦客邻

客户服务是企业业务环节中的关键一环,也是确保客户最终满意度的关键一环。好的客户服务是一个组织能持续经营的有力保证。 如何让客服成为客户的好邻里,让客户真实地感受到全方位的服务,从而让组织的服务产生力量和价值。企业对客服有着系统…

LV8731V-TLM-H 带保护步进电机驱动器特性简述

LV8731V-TLM-H是一个2−通道H−桥驱动器IC,它可以切换步进电机驱动器和两个有刷电机驱动器,前者支持1/16−步进分辨率的微步进驱动,后者支持电机的前进、后退、制动和待机。它非常适合驱动办公室设备和娱乐应用中使用的刷直流电机和步进电机。…

Web--Maven

1.maven管理项目的区别 2. 安装后,conf目录下的setting文件中,对本地仓库的配置 此处可替换成自定义的本地仓库地址,默认为c:/user/17860/.m2/repository(我的电脑上的) 3.maven项目的标准目录结构 4.项目的生命周期 5.Maven概…

内网渗透(三十七)之横向移动篇-Pass the Hash 哈希传递攻击(PTH)横向移动

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…

面试攻略,Java 基础面试 100 问(七)

String 是最基本的数据类型吗? 不是。Java 中的基本数据类型只有 8 个:byte、short、int、long、float、 double、char、boolean;除了基本类型(primitive type)和枚举类型(enumeration type)&#xff0c…

分享一个外贸客户案例

春节期间一个外贸人收到了客户的回复,但因为自己的处理方式造成了一个又一个问题,我们可以从中学到一些技巧和知识。“上次意大利的客人询价后,一直没回复(中间有打过电话,对方说口语不行,我写过邮件跟进过…