为什么80%的码农都做不了架构师?>>>   

对象变量其实是一个引用,它们的值是指向对象所在的内存地址,而不是对象本身。

1、Java内存机制 Java把内存分成两种,一种叫做栈内存,一种叫做堆内存。 栈内存存放一些在函数中定义的基本类型的变量和对象的引用变量。这就意味着随着代码块的结束,内存得到释放。 堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。 栈中的变量指向堆内存中的变量。   String并不是基本数据类型,而是一个对象,并且是不可变的对象(String类为final型的(当然也不可被继承),所以存放在堆内存中。几乎每一个修改String对象的操作,实际上都是创建了一个全新的String对象。

2、字符串的存储(字符串常量池) 由于String类型使用非常广泛,如果按照面向对象的标准语法,为每一个String都申请内存空间,在内存使用上存在比较大的浪费。因此,在java中有一个“字符数据池”的内存管理机制,是Java方法区中的一部分特殊存储。在字符串直接赋值时,会触发,首先会去这个字符串池中查找,如果找到,直接返回对该字符串的引用。当然字符数据池也在堆内存中。这个机制是非常有用的,因为可以提高效率,减少了内存空间的占用。由于这种机制的存在,使用字符串的过程中,推荐使用直接赋值(即String s=”abc”),除非有必要才会新建一个String对象(即String s = new String(”abc”))。同时由于该机制的存在,如果字符串可变的话, 当两个引用指向指向同一个字符串时,对其中一个做修改就会影响另外一个。

3、字符串池在哪? String s = new String("abc");中的abc存储在堆空间中,而s则是在操作数栈中。这里"abc"本身就是常量池中的一个对象,而在运行时执行new String()时,将常量池中的对象复制一份放到堆中,并且把堆中的这个对象的引用交给s持有。所以这条语句就创建了2个String对象。String s = "abc";直接对于字符串池进行操作。

常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集合,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。对于String常量,它的值是在常量池中的。 而JVM中的常量池在内存当中是以表的形式存在的,对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用。说到这里,对常量池中的字符串值的存储位置应该有一个比较明了的理解了。 常量池属于类型信息的一部分,类型信息也就是每一个被转载的类型,这个类型反映到JVM内存模型中是对应存在于JVM内存模型的方法区中,也就是这个类型信息中的常量池概念是存在于在方法区中,而方法区是在JVM内存模型中的堆中由JVM来分配的。所以,abc的值是应该是存在堆空间中的。

4、线程安全 不可变类的实例一旦创建,其成员变量的值就不能被修改。不可变对象天生就是线程安全的,因为不可变对象不能被改变,所以他们可以自由地在多个线程之间共享。不需要任何同步处理。由于,String是一个不可变类,所以保证了在多线程之间的安全性。例如: String被广泛的使用在其他Java类中充当参数。比如网络连接、打开文件等操作。如果字符串可变,那么类似操作可能导致安全问题。因为某个方法在调用连接操作的时候,他认为会连接到某台机器,但是实际上并没有(其他引用同一String对象的值修改会导致该连接中的字符串内容被修改)。可变的字符串也可能导致反射的安全问题,因为他的参数也是字符串。 Java中经常会用到字符串的哈希码(hashcode)。例如,在HashMap中,字符串的不可变能保证其hashcode永远保持一致,这样就可以避免一些不必要的麻烦。这也就意味着每次在使用一个字符串的hashcode的时候不用重新计算一次,这样更加高效。

5、String缺点 由于String的不可变性,因此在对String进行频繁拼接操作的时候,会不断的创建新对象,造成内存浪费。所以系统提供了StringBuffer 和StringBuilder 来对需要频繁变化的操作。 StringBuffer和String一样都是用来存储字符串的,只不过由于他们内部的实现方式不同,导致他们所使用的范围不同,对于StringBuffer而言,他在处理字符串时,若是对其进行修改操作,它并不会产生一个新的字符串对象,所以说在内存使用方面它是优

  在StringBuffer的使用方面,它更加侧重于对字符串的变化,例如追加、修改、删除,相对应的方法:1、append():追加指定内容到当前StringBuffer对象的末尾,类似于字符串的连接,这里StringBuffer对象的内容会发生改变。2、insert:该类方法主要是在StringBuffer对象中插入内容。3、delete:该类方法主要用于移除StringBuffer对象中的内容。StringBuilder也是一个可变的字符串对象,他与StringBuffer不同之处就在于它是线程不安全的,基于这点,它的速度一般都比StringBuffer快。与StringBuffer一样,StringBuider的主要操作也是append与insert方法。这两个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串生成器中。

6、如何优化 对于字符串而言我们经常是要对其进行拼装处理的,在java中提高了三种拼装的方法:+、concat()以及append()方法。

append()速度最快,concat()次之,+最慢。原因请看下面分解:

  (一)+方式拼接字符串在前面我们知道编译器对+进行了优化,它是使用StringBuilder的append()方法来进行处理的,我们知道StringBuilder的速度比StringBuffer的速度更加快,但是为何运行速度还是那样呢?主要是因为编译器使用append()方法追加后要同toString()转换成String字符串,也就说  str +=”b”等同于str = new StringBuilder(str).append("b").toString();它变慢的关键原因就在于new StringBuilder()和toString(),这里可是创建了10W个StringBuilder对象,而且每次还需要将其转换成String,速度能不慢么?(二)concat()方法拼接字符串

public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } char buf[] = new char[count + otherLen]; getChars(0, count, buf, 0); str.getChars(0, otherLen, buf, count); return new String(0, count + otherLen, buf); } 这是concat()的源码,它看上去就是一个数字拷贝形式,我们知道数组的处理速度是非常快的,但是由于该方法最后是这样的:return new String(0, count + otherLen, buf);这同样也创建了10W个字符串对象,这是它变慢的根本原因。

 (三)append()方法拼接字符串

public synchronized StringBuffer append(String str) { super.append(str); return this; } StringBuffer的append()方法是直接使用父类AbstractStringBuilder的append()方法,该方法的源码如下:

public AbstractStringBuilder append(String str) { if (str == null) str = "null"; int len = str.length(); if (len == 0) return this; int newCount = count + len; if (newCount > value.length) expandCapacity(newCount); str.getChars(0, len, value, count); count = newCount; return this; } 与concat()方法相似,它也是进行字符数组处理的,加长,然后拷贝,但是请注意它最后是返回并没有返回一个新串,而是返回本身,也就说这这个10W次的循环过程中,它并没有产生新的字符串对象。

  通过上面的分析,我们需要在合适的场所选择合适的字符串拼接方式,但是并不一定就要选择append()和concat()方法,原因在于+根据符合我们的编程习惯,只有到了使用append()和concat()方法确实是可以对我们系统的效率起到比较大的帮助,才会考虑,同时鄙人也真的没有怎么用过concat()方法。

转载于:https://my.oschina.net/yida/blog/629426

为什么Java要把字符串设计成不可变的相关推荐

  1. java 字符串连接_为什么 Java 要把字符串设计成不可变的

    String是Java中一个不可变的类,所以它一旦被实例化就无法被修改.不可变类的实例一旦创建,其成员变量的值就不能被修改.不可变类有很多优势.本文总结了为什么字符串被设计成不可变的.将涉及到内存.同 ...

  2. java语言特点 字符串不变_面试必问:Java中String类型为什么设计成不可变的?

    这几天在各大平台上都看到过这样一些帖子,全都是关于String类型对象不可变的问题,当然现在也是找工作的准备时期,因此花了一部分时间对其进行整理一下. 想要完全了解String,在这里我们需要解决以下 ...

  3. java中数组的返回值是什么类型_面试必问:Java中String类型为什么设计成不可变的?...

    这几天在各大平台上都看到过这样一些帖子,全都是关于String类型对象不可变的问题,当然现在也是找工作的准备时期,因此花了一部分时间对其进行整理一下. 想要完全了解String,在这里我们需要解决以下 ...

  4. java String中文字符串分割成数组 中文字符串分割成一定长度的字符串数组

    java String中文字符串分割成一定长度的字符串数组 /*** 几个字一组 变量控制 大于零有意义*/ int num = 6; /*** 待操作的字符串*/ String str = &quo ...

  5. java怎么把字符串转换成字符数组

    此博客用于个人编程学习记录. 文章内容来自于: java怎么把字符串转换成字符数组-Java基础-PHP中文网https://www.php.cn/java/base/435415.html java ...

  6. String的内存模型,为什么String被设计成不可变的

    String是Java中最常用的类,是不可变的(Immutable), 那么String是如何实现Immutable呢,String为什么要设计成不可变呢? 前言 关于String,收集一波基础,来源 ...

  7. string replace_面试必问:String类型为什么设计成不可变的?

    这几天在各大平台上都看到过这样一些帖子,全都是关于String类型对象不可变的问题,当然现在也是找工作的准备时期,因此花了一部分时间对其进行整理一下. 想要完全了解String,在这里我们需要解决以下 ...

  8. 为什么String要设计成不可变的?

    翻译人员: 铁锚 翻译日期: 2013年11月18日 原文链接: Why string is immutable in Java ? 这是一个老生常谈的话题(This is an old yet st ...

  9. java把字符串变代码,Java/javaScript将字符串转变成可执行的语句

    java 以下语句如何执行? int money = 2500; String str = "money>=2000&&money<=4000" ; S ...

最新文章

  1. RS232交叉串口线的做法与测试!
  2. BoneCP学习笔记——配置参数
  3. 攻防世界(Pwn)dice_game, 栈溢出覆盖srand种子
  4. php 正则表达式 取所有内容,php正则表达式获取内容所有链接
  5. 机器人学习--F1TENTH弗吉尼亚大学无人驾驶课程
  6. 基于pygame的射击小游戏制作(一)让飞船动起来
  7. 2020年推荐系统工程师炼丹手册RecSys-Long Paper版
  8. sklear多项式回归
  9. 分布式离线计算—MapReduce—为什么被淘汰了?
  10. Mac下安装caffe(cpu-only)
  11. 设计一款编程语言有多难?Ruby 创始人揭秘
  12. PPT转换PDF格式怎么转换?后悔现在才知道
  13. 又优化了一下 Android ListView 异步加载图片
  14. 电子罗盘电磁干扰_车载电子罗盘中的一种新型抗干扰设计
  15. Qt 3D Overview
  16. 【鲲鹏应用迁移】实验:通过鲲鹏开发套件实现Hyper Tuner性能调优(超详细)
  17. 编译内核 解决 Gentoo 在 AUSU P5B SE 板载网卡 无法上网
  18. python --- 常见题目 2019.01.03
  19. java生成word报告echart_Java这几个用 Pyecharts 做出来的交互图表,领导说叼爆了!...
  20. Java集合的基础知识

热门文章

  1. 【自动化测试技术QTP基础系列六】---QTP脚本录制及回放
  2. php获取svn文件,然后ftp上传服务器代码
  3. mongodb基本操作=增删改查
  4. 重拾-Spring Transaction
  5. 第5章:可复用性的软件构建方法 5.2面向复用的构造
  6. Ubuntu使用PBIS认证
  7. xmemcached发布1.3.4
  8. (一)win7下cocos2d-x 21 + vs2010
  9. Android 数据库之Cursor
  10. SSM中(Spring-SpringMVC-Mybatis)(一:概念)