【Java面试】来讲一讲你对String的理解

news2024/11/28 16:42:18

文章目录

  • 字符型常量和字符串常量的区别
  • 什么是字符串常量池?
  • String 是最基本的数据类型吗
  • String有哪些特性
  • String为什么是不可变的?
  • String真的是不可变的吗?
  • String不可变的必要性
  • 是否可以继承 String 类
  • 数组有没有 length()方法?String 有没有 length()方法
  • String 类的常用方法都有那些?
  • 在使用 HashMap 的时候,用 String 做 key 有什么好处?
  • String和StringBuffer、StringBuilder的区别是什么?
  • 学习更多

字符型常量和字符串常量的区别

  1. 形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
  2. 含义上: 字符常量相当于一个整形值(ASCII值),可以参加表达式运算 字符串常量代表一个地址值(该字
    符串在内存中存放位置)
  3. 占内存大小 字符常量只占一个字节 字符串常量占若干个字节(至少一个字符结束标志)

什么是字符串常量池?

字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。

String 是最基本的数据类型吗

不是。Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、 double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(referencetype),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。
Java 的 8 种基本数据类型中不包括 String,基本数据类型中用来描述文本数据的是 char,但是它只能表示单个字符,比如 ‘a’,‘好’ 之类的,如果要描述一段文本,就需要用多个char 类型的变量,也就是一个 char 类型数组,比如“你好” 就是长度为2的数组 char[] chars = {‘你’,‘好’};
但是使用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是使用的时候开发者不需要直接操作底层数组,用更加简便的方式即可完成对字符串的使用。

String有哪些特性

  • 不变性:String 是只读字符串,是一个典型的 immutable (不变的)对象,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。
  • 常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。
  • final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。

String为什么是不可变的?

简单来说就是String类利用了final修饰的char类型数组存储字符,源码如下图所以:
在这里插入图片描述
我们可以看到,String类字符其实就是byte数组对象的二次封装,存储变量value[]是被final修饰的,所以一个String对象创建以后是无法被改变值的,这点跟包装类是一样的。

String真的是不可变的吗?

我觉得如果别人问这个问题的话,回答不可变就可以了。 下面只是给大家看两个有代表性的例子:

  1. String不可变但不代表引用不可以变
 String str = "Hello";
 str = str + " World";
 System.out.println("str=" + str);**

结果:

str=Hello World

解析:
实际上,原来String的内容是不变的,只是str由原来指向"Hello"的内存地址转为指向"Hello World"的内存地址而已,也就是说多开辟了一块内存区域给"Hello World"字符串。

  1. 通过反射是可以修改所谓的“不可变”对象
  // 创建字符串"Hello World", 并赋给引用s
	String s = "Hello World";
        
    System.out.println("s = " + s); // Hello World
     
    // 获取String类中的value字段
    Field valueFieldOfString = String.class.getDeclaredField("value");
    // 改变value属性的访问权限
    valueFieldOfString.setAccessible(true);
	
	// 获取s对象上的value属性的值
	char[] value = (char[]) valueFieldOfString.get(s);

	// 改变value所引用的数组中的第5个字符
	value[5] = '_';
	System.out.println("s = " + s); // Hello_World

结果:

s = Hello World
s = Hello_World

解析:
用反射可以访问私有成员, 然后反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。但是一般我们不会这么做,这里只是简单提一下有这个东西。

String不可变的必要性

String之所以被设计为不可变的,目的是为了效率和安全性:

  • 效率:
    String不可变是字符串常量池实现的必要条件,通过常量池可以避免了过多的创建String对象,节省堆空间。
    String的包含了自身的HashCode,不可变保证了对象HashCode的唯一性,避免了反复计算。
  • 安全性:
    String被许多Java类用来当参数,如果字符串可变,那么会引起各种严重错误和安全漏洞。
    再者String作为核心类,很多的内部方法的实现都是本地调用的,即调用操作系统本地API,其和操作系统交流频繁,假如这个类被继承重写的话,难免会是操作系统造成巨大的隐患。
    最后字符串的不可变性使得同一字符串实例被多个线程共享,所以保障了多线程的安全性。而且类加载器要用到字符串,不可变性提供了安全性,以便正确的类被加载。

是否可以继承 String 类

  • String 类是 final 类,不可以被继承。
  • String str="i"与 String str=new String(“i”)一样吗?
    不一样,因为内存的分配方式不一样。
    String str="i"的方式,java 虚拟机会将其分配到常量池中;
    而 String str=new String(“i”) 则会被分到堆内存中。
  • String s = new String(“xyz”);创建了几个字符串对象?
    两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。
    对于这个问题,看下面的代码就懂了。
1 String str1 = "hello"; //str1指向静态区
2 String str2 = new String("hello"); //str2指向堆上的对象
3 String str3 = "hello";
4 String str4 = new String("hello");
5 System.out.println(str1.equals(str2)); //true
6 System.out.println(str2.equals(str4)); //true
7 System.out.println(str1 == str3); //true
8 System.out.println(str1 == str2); //false
9 System.out.println(str2 == str4); //false
10 System.out.println(str2 == "hello"); //false
11 str2 = str1;
12 System.out.println(str2 == "hello"); //true

== 只能单纯的比较地址,而equals会在地址不同的时候比较内容。

数组有没有 length()方法?String 有没有 length()方法

数组没有 length()方法 ,有 length 的属性。String 有 length()方法。 JavaScript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

String 类的常用方法都有那些?

indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。

在使用 HashMap 的时候,用 String 做 key 有什么好处?

HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。
如果不理解为什么,看下面的图片就懂了
在这里插入图片描述
3在这里插入图片描述

String和StringBuffer、StringBuilder的区别是什么?

  • 可变性
    String类中使用字符数组保存字符串,private final char value[],所以 string对象是不可变的。
    StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。

  • 线程安全性
    String中的对象是不可变的,也就可以理解为常量,线程安全。
    AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。
    StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
    StringBuilder并没有对方法进行加同步锁,所以是非线程安全
    的。

  • 性能
    每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。
    StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。
    相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

  • 对于三者使用的总结
    如果要操作少量的数据用 = String
    单线程操作字符串缓冲区下操作大量数据 = StringBuilder
    多线程操作字符串缓冲区下操作大量数据 = StringBuffer

学习更多

String详解

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

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

相关文章

windows线程 互斥锁CreateMutex、ReleaseMutex、CloseHandle

互斥 相关问题 多线程下代码或资源的共享使用。 互斥的使用 1.创建互斥 HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes,//安全属性(废弃参数,置NULL) BOOL bInitialOwner,//初始的拥有者TRUE/FALSE LPCTSTR lpName //命名 );…

集成电路技术——如何制造芯片(1)

1.概述 电子工业是现在高新技术的核心,它在人类的科技发展中发挥了巨大作用,电子工业已经成为成为当今世界发展最快的高新技术产业,在全世界各国国民经济中起着举足轻重的作用。当今的电子技术离不开集成电路,集成电路是电子工业…

hadoop集群迁移

集群迁移 主要是要找到两个集群中active状态的namenode 集群迁移不同于服务器之间的文件发送,在hdfs中,文件是以块的形式,只可以通过namenode访问文件,所以迁移时需要通过hadoop命令 主要命令是distcp distcp有很多参数&#xf…

Kafka - 06 Kafka 集群环境搭建(三台服务器)

文章目录1. 克隆虚拟机2. Zookeeper 集群搭建3. Kafka 集群搭建4. 测试消息发送和消费1. 主题操作2. 生产者生产消息3. 消费者消费消息1. 克隆虚拟机 kafka集群搭建,需要3台虚拟机环境,但是我目前只安装了一台虚拟机,因此还需要准备两台虚拟…

[附源码]计算机毕业设计springboot-Steam游戏平台系统论文

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

纯CSS制作3D动态相册【流星雨3D旋转相册】HTML+CSS+JavaScriptHTML5七夕情人节表白网页制作

这是程序员表白系列中的100款网站表白之一,旨在让任何人都能使用并创建自己的表白网站给心爱的人看。 此波共有100个表白网站,可以任意修改和使用,很多人会希望向心爱的男孩女孩告白,生性腼腆的人即使那个TA站在眼前都不敢向前表白…

MySQL数据库管理及用户管理以及数据库用户授权

MySQL数据库管理及用户管理以及数据库用户授权MySQL数据库管理1、库和表2、常用的数据类型查看数据库结构SQL语句1、SQL语句分类:创建及删除数据库和表管理表中的数据记录(表数据的增删改查)向数据表中插入新的数据记录(增&#x…

大二Web课程设计——动漫海贼王(可以很好的应付老师的作业)

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置,有div的样式格局,这个实例比较全面,有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 精彩专栏推荐&#x1f4…

Java基础:入门程序、常量、变量

第一章 HelloWorld入门程序 1.1 程序开发步骤说明 Java程序开发三步骤:编写、编译、运行。 1.2 编写Java源程序 在D:\java\javaCode目录下新建文本文件,完整的文件名修改为HelloWorld.java,其中文件名为 HelloWorld,后 缀名必须…

音视频技术开发周刊 | 273

每周一期,纵览音视频技术领域的干货。新闻投稿:contributelivevideostack.com。「紧急通知」LiveVideoStackCon 2022 音视频技术大会北京站改期各位LVSer们:因疫情影响,北京近期不再允许举办大型线下活动,我们无奈且抱…

如何向瑞芯微平台添加驱动

如何向瑞芯微平台添加驱动驱动配置驱动文件放置配置相应的编译选项与设备树结合设备树配置以avafpga视频驱动为例:驱动配置 驱动文件放置 为了保证驱动文件能够被系统正确识别编译,需要将驱动文件的源文件avafpga.c放在./kernel/drivers/media/i2c/下 …

外观专利申请定要注意哪些因素呢?

问题一:申请外观专利需要提交哪些申请材料呢? 1、外观专利请求书; 2、外观设计七视图的照片或者设计图; 3、申请人的身份证明材料; 4、外观设计的简要说明材料。 问题二:外观专利申请定要注意哪些因素…

Automatic Online Calibration of Cameras and Lasers 论文翻译

目录题目AbstractI. INTRODUCTIONII. SENSOR PROCESSINGA. Image processingB. Laser processingIII. MISCALIBRATION DETECTIONIV. AUTOMATIC CALIBRATION TRACKINGV. EXPERIMENTAL RESULTSVI. CONCLUSION题目 Automatic Online Calibration of Cameras and Lasers 下载地址&…

C++ Reference: Standard C++ Library reference: Containers: list: list: size

C官网参考链接&#xff1a;https://cplusplus.com/reference/list/list/size/ 公有成员函数 <list> std::list::size C98 size_type size() const; C11 size_type size() const noexcept; 返回大小 返回列表&#xff08;list&#xff09;容器中的元素个数。 形参 没有…

Python tkinter -- 第18章 画布控件之图像(image)

18.2.16 create_image(position, **options) 在画布的指定位置创建一个图片对象。这里的图片对象是gif&#xff0c;png&#xff0c;pgm和ppm。 &#xff08;1&#xff09;position&#xff1a;图片的坐标(x,y)。 &#xff08;2&#xff09;**options&#xff1a;图片选项 选项…

IO流~字节流

字节流 IO流分类 按照数据的流向&#xff1a;输入流&#xff1a;读数据\输出流&#xff1a;写数据按照数据类型来分 字节流&#xff1a;字节输入流&#xff1b;字节输出流字符流&#xff1a;字符输入流&#xff1b;字符输出流 一般来说&#xff0c;IO流的分类是按照数据类型…

触发器,寄存器,三态输出电路

目录 一&#xff1a;触发器 二&#xff1a;寄存器&#xff08;register&#xff09; 缓冲寄存器 三态输出电路&#xff08;只看标红的即可&#xff09;数据总线上很常用 考试会问你触发器&#xff0c;寄存器&#xff0c;存储器是什么关系你知道就行。这个简答题在存储器笔…

基于Java+SpringMvc+Vue求职招聘系统详细设计实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取联系&#x1f345;精彩专栏推荐订阅&#x1f447;&#x1f…

Java项目:ssm药品管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 该项目是前后台的医药管理系统&#xff08;写在了一个web项目里&#xff09;&#xff0c; 简单明了&#xff0c;界面高端大气&#xff0c;共6张…

图的基本表示方法

一、图的基本表示方法 由G(V,E)G (V,E)G(V,E)由下列要素构成&#xff1a; 一组节点:V1,⋯nV 1,\cdots nV1,⋯n一组边E⊆VVE \subseteq V \times VE⊆VV 边(i,j)∈E(i,j) \in E(i,j)∈E 连接了节点i和ji和ji和j i和ji和ji和j被称为相邻节点节点的度&#xff1a;相邻节点的数…