Java 关于String字符串原理上的问题


Posted in Java/Android onApril 07, 2022

1、String 是最基本的数据类型吗?

不是。

Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;除了基本类型,剩下的都是引用类型,Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。

2、字符型常量和字符串常量的区别?

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

3、什么是字符串常量池?

字符串常量池:jvm为了提升性能和减少内存开销,避免字符的重复创建,其维护了一块特殊的内存空间,即字符串常量池。当需要使用字符串时,先去字符串常量池中查看该字符串是否已经存在,如果存在,则可以直接使用,如果不存在,初始化,并将该字符串放入字符串常量池中。

所处位置说明

  • 在jdk6中,常量池的位置在永久代(方法区)中,此时常量池中存储的是对象。
  • 在jdk7中,常量池的位置在堆中,此时,常量池存储的就是引用了。
  • 在jdk8中,永久代(方法区)被元空间取代了。

4、String str=new String(“aaa”)创建了几个对象?

1个或者2个

  • 第一种情况:字符串常量池中已经有了 "aaa" 字符串常量了,那么此时会在堆中通过 new String()方法 创建 1 个字符串对象。
  • 第二种情况:那就是字符串常量池中没有 "aaa" 字符串常量了,此时会创建 2 个对象。首先 "aaa" 该表达式会查看字符串常量池中是否含有 "aaa" 常量,如果没有的话,那么在字符串常量池中就会生成一个值为 "aaa" 的字符串常量,然后再在堆中通过 new String()方法 创建一个值为 "aaa" 的对象。

5、字符串的 intern 方法的执行过程是怎样的?

你学 Java 的别这个高频知识点都不知道呀,不知道的赶紧偷摸补一下。

在解析这个问题之前,我们先来做个题目:

public class Test {
    public static void main(String[] args) {
        String s = new String("2");
        s.intern();
        String s1 = "2";
        System.out.println(s == s1);

        String s3 = new String("3") + new String("3");
        s3.intern();
        String s4 = "33";
        System.out.println(s3 == s4);
    }
}

输出结果

//jdk6

false

false

//jdk7

false

true

intern 方法在JDK1.6以前 和 JDK1.7以后有不同的处理:

  • 在JDK1.6中,intern 的处理是 先判断字符串常量是否在字符串常量池中,如果存在直接返回该常量,如果没有找到,则将该字符串常量加入到字符串常量区,也就是在字符串常量区建立该常量;
  • 在JDK1.7中,intern 的处理是 先判断字符串常量是否在字符串常量池中,如果存在直接返回该常量,如果没有找到,说明该字符串常量在堆中,则处理是把堆区该对象的引用加入到字符串常量池中,以后别人拿到的是该字符串常量的引用,实际存在堆中。

6、String,StringBuffer,StringBuilder 的区别是什么?

可变与不可变

String

// 源码
private final char value[];

String 类中使用字符数组保存字符串,因为有 “final” 修饰符,所以 String 对象是不可变的。对于已经存在的 String 对象的修改都是重新创建一个新的对象,然后把新的值保存进去。

StringBufferStringBuilder

// 源码
char[] value;

StringBufferStringBuilder 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串,这两种对象都是可变的。

是否多线程安全

  • String 中的对象是不可变的,也就可以理解为常量,显然线程安全。
  • StringBuilder 是非线程安全的。
  • StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
// StringBuffer 的追加操作
public synchronized StringBuffer append(StringBuffer sb) {
     toStringCache = null;
     super.append(sb);
     return this;
 }

性能

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

7、String为什么要设计成不可变的?

  • 便于实现字符串常量池。
  • 使多线程安全
  • 避免安全问题:在网络连接和数据库连接中字符串常常作为参数,例如,网络连接地址 URL,文件路径path,反射机制所需要的String参数。其不可变性可以保证连接的安全性。如果字符串是可变的,黑客就有可能改变字符串指向对象的值,那么会引起很严重的安全问题。
  • 加快字符串处理速度:由于String是不可变的,保证了hashcode的唯一性,于是在创建对象时其hashcode就可以放心的缓存了,不需要重新计算。这也就是Map喜欢将String作为Key的原因。

到此这篇关于Java 关于String字符串原理上的问题的文章就介绍到这了,更多相关Java String内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Java/Android 相关文章推荐
在Java中Collection的一些常用方法总结
Jun 13 Java/Android
解决Maven项目中 Invalid bound statement 无效的绑定问题
Jun 15 Java/Android
SpringBoot2 参数管理实践之入参出参与校验的方式
Jun 16 Java/Android
详解java如何集成swagger组件
Jun 21 Java/Android
jackson json序列化实现首字母大写,第二个字母需小写
Jun 29 Java/Android
Java使用jmeter进行压力测试
Jul 09 Java/Android
Sleuth+logback 设置traceid 及自定义信息方式
Jul 26 Java/Android
SpringBoot实现quartz定时任务可视化管理功能
Aug 30 Java/Android
Java实现给Word文件添加文字水印
Feb 15 Java/Android
Java字符缓冲流BufferedWriter
Apr 09 Java/Android
Spring Cloud Netflix 套件中的负载均衡组件 Ribbon
Apr 13 Java/Android
Android开发实现极为简单的QQ登录页面
Apr 24 Java/Android
Java虚拟机内存结构及编码实战分享
Java Lambda表达式常用的函数式接口
Apr 07 #Java/Android
Android Rxjava3 使用场景详解
Apr 07 #Java/Android
Java GUI编程菜单组件实例详解
Flutter集成高德地图并添加自定义Maker的实践
Apr 07 #Java/Android
详解Flutter和Dart取消Future的三种方法
Apr 07 #Java/Android
java如何实现获取客户端ip地址的示例代码
Apr 07 #Java/Android
You might like
浅析php中如何在有限的内存中读取大文件
2013/07/02 PHP
小谈php正则提取图片地址
2014/03/27 PHP
thinkPHP自定义类实现方法详解
2016/11/30 PHP
php array_chunk()函数用法与注意事项
2019/07/12 PHP
thinkPHP5框架接口写法简单示例
2019/08/05 PHP
javascrip客户端验证文件大小及文件类型并重置上传
2011/01/12 Javascript
javascript history对象(历史记录)使用方法(实现浏览器前进后退)
2014/01/07 Javascript
js贪吃蛇网页版游戏特效代码分享(挑战十关)
2015/08/24 Javascript
JS代码随机生成姓名、手机号、身份证号、银行卡号
2016/04/27 Javascript
AngularJS bootstrap启动详解及实例代码
2016/09/14 Javascript
基于input框覆盖掉数字英文的实例讲解
2017/07/21 Javascript
vue.js框架实现表单排序和分页效果
2017/08/09 Javascript
Angular4实现鼠标悬停3d倾斜效果
2017/10/25 Javascript
Vue注册组件命名时不能用大写的原因浅析
2019/04/25 Javascript
jquery实现Ajax请求的几种常见方式总结
2019/05/28 jQuery
jQuery实现可以计算进制转换的计算器
2020/10/19 jQuery
[15:15]教你分分钟做大人:狙击手
2014/10/30 DOTA
[58:57]2018DOTA2亚洲邀请赛3月29日小组赛B组 Effect VS VGJ.T
2018/03/30 DOTA
[01:51]历届DOTA2国际邀请赛举办地回顾 TI9落地上海
2018/08/26 DOTA
Python中处理时间的几种方法小结
2015/04/09 Python
qpython3 读取安卓lastpass Cookies
2016/06/19 Python
python SMTP实现发送带附件电子邮件
2018/05/22 Python
利用Python+阿里云实现DDNS动态域名解析的方法
2019/04/01 Python
python使用opencv对图像mask处理的方法
2019/07/05 Python
使用Html5、CSS实现文字阴影效果
2018/01/17 HTML / CSS
美国领先的礼品卡网站:GiftCards.com
2016/11/02 全球购物
荷兰演唱会和体育比赛订票网站:viagogo荷兰
2018/04/08 全球购物
团员的自我评价
2013/12/01 职场文书
工厂保洁员岗位职责
2013/12/04 职场文书
大二自我鉴定
2014/01/31 职场文书
美术课外活动总结
2014/07/08 职场文书
单身证明格式样本
2015/06/15 职场文书
安全教育观后感
2015/06/17 职场文书
家属联谊会致辞
2015/07/31 职场文书
优秀员工演讲稿
2019/06/21 职场文书
用python自动生成日历
2021/04/24 Python