Java-String-对象,你真的了解了吗?,mysql教程入门到精通

HarmonyOS学习 2021-11-25 19:07:15
java 面试 编程语言 后端开发

String str = “pingtouge”;
String str1 = new String(“pingtouge”);
system.out.println(str==str1)

我们逐一来分析这几行代码,首先从String str = "pingtouge"开始,这里使用了字符串常量的方式创建字符串对象,在创建pingtouge字符串对象时,JVM会去常量池中查找是否存在该字符串,这里的答案肯定是没有的,所以JVM将会在常量池中创建该字符串对象并且返回对象的地址引用,所以str指向的是pingtouge字符串对象在常量池中的地址引用。

然后是String str1 = new String("pingtouge")这行代码,这里使用的是构造函数的方式创建字符串对象,根据我们上面对构造函数方式创建字符串对象的理解,str1得到的应该是堆中pingtouge字符串的引用地址。由于str指向的是pingtouge字符串对象在常量池中的地址引用而str1指向的是堆中pingtouge字符串的引用地址,所以str肯定不等于str1

String 对象的不可变性

从我们知道String对象的那一刻起,我想大家都知道了String对象是不可变的。那它不可变是怎么做到的呢?Java?这么做能带来哪些好处?我们一起来简单的探讨一下,先来看看String?对象的一段源码:

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];

/** Cache the hash code for the string */
private int hash; // Default to 0

/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
}

从这段源码中可以看出,String类用了 final 修饰符,我们知道当一个类被 final 修饰时,表明这个类不能被继承,所以String类不能被继承。这是String不可变的第一点

再往下看,用来存储字符串的char value[]数组被private?和final修饰,我们知道对于一个被final的基本数据类型的变量,则其数值一旦在初始化之后便不能更改。这是String不可变的第二点。

Java 公司为什么要将String设置成不可变的,主要从以下三方面考虑:

  • 1、保证 String 对象的安全性。假设 String 对象是可变的,那么 String 对象将可能被恶意修改。
  • 2、保证 hash 属性值不会频繁变更,确保了唯一性,使得类似 HashMap 容器才能实现相应的 key-value 缓存功能。
  • 3、可以实现字符串常量池

String 对象的优化

字符串是我们常用的Java类型之一,所以对字符串的操作也是避免不了的,在对字符串的操作过程中,如果使用不当,性能会天差地别。那么在字符串的操作过程中,有哪些地方需要我们注意呢?

优雅的拼接字符串

字符串的拼接是对字符串操作使用最频繁的操作之一,由于我们知道String对象的不可变性,所以我们在做拼接时尽可能少的使用+进行字符串拼接或者说潜意识里认为不能使用+进行字符串拼接,认为使用+进行字符串拼接会产生许多无用的对象。事实真的是这样吗?我们来做一个实验。我们使用+来拼接下面这段字符串。

String str8 = “ping” +“tou”+“ge”;

一起来分析一下这段代码会产生多少个对象?如果按照我们理解的意思来分析的话,首先会创建ping对象,然后创建pingtou对象,最后才会创建pingtouge对象,一共创建了三个对象。真的是这样吗?其实不是这样的,Java 公司怕我们程序员手误,所以对编译器进行了优化,上面的这段字符串拼接会被我们的编译器优化,优化成一个String str8 = "pingtouge";对象。除了对常量字符串拼接做了优化以外,对于使用+号动态拼接字符串,编译器也做了相应的优化,以便提升String的性能,例如下面这段代码:

String str = “pingtouge”;

for(int i=0; i<1000; i++) {
str = str + i;
}

编译器会帮我们优化成这样

String str = “pingtouge”;

for(int i=0; i<1000; i++) {
str = (new StringBuilder(String.valueOf(str))).append(i).toString();
}

可以看出 Java 公司对这一块进行了不少的优化,防止由于程序员不小心导致String性能急速下降,尽管 Java 公司在编译器这一块做了相应的优化,但是我们还是能看出 Java 公司优化的不足之处,在动态拼接字符串时,虽然使用了 StringBuilder 进行字符串拼接,但是每次循环都会生成一个新的 StringBuilder 实例,同样也会降低系统的性能。

所以我们在做字符串拼接时,我们需要从代码的层面进行优化,在动态的拼接字符串时,如果不涉及到线程安全的情况下,我们显示的使用 StringBuilder 进行拼接,提升系统性能,如果涉及到线程安全的话,我们使用 StringBuffer 来进行字符串拼接

巧妙的使用 intern() 方法

  • <p>
  • When the intern method is invoked, if the pool already contains a
  • string equal to this {@code String} object as determined by
  • the {@link #equals(Object)} method, then the string from the pool is
  • returned. Otherwise, this {@code String} object is added to the
  • pool and a reference to this {@code String} object is returned.
  • <p>
    public native String intern();

这是 intern() 函数的官方注释说明,大概意思就是 intern 函数用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。否则,在常量池中加入该对象,然后 返回引用。

有一位Twitter工程师在QCon全球软件开发大会上分享了一个他们对?String对象优化的案例,他们利用String.intern()方法将以前需要20G内存存储优化到只需要几百兆内存。这足以体现String.intern()的威力,我们一起来看一个例子,简单的了解一下String.intern()的用法。

public static void main(String[] args) {
String str = new String(“pingtouge”);
String str1 = new String(“pingtouge”);
System.out.println(“未使用intern()方法:”+(str==str1));
System.out.println(“未使用intern()方法,str:”+str);
System.out.println(“未使用intern()方法,str1:”+str1);

String str2= new String(“pingtouge”).intern();
String str3 = new String(“pingtouge”).intern();
System.out.println(“使用intern()方法:”+(str2==str3));
System.out.println(“使用intern()方法,str2:”+str2);
System.out.println(“使用intern()方法,str3:”+str

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

3);
}

Java-String-对象,你真的了解了吗?,mysql教程入门到精通_Java

从结果中可以看出,未使用String.intern()方法时,构造相同值的字符串对象返回不同的对象引用地址,使用String.intern()方法后,构造相同值的字符串对象时,返回相同的对象引用地址。这能帮我们节约不少空间

最后

做任何事情都要用心,要非常关注细节。看起来不起眼的、繁琐的工作做透了会有意想不到的价值。
当然要想成为一个技术大牛也需要一定的思想格局,思想决定未来你要往哪个方向去走, 建议多看一些人生规划方面的书籍,多学习名人的思想格局,未来你的路会走的更远。

更多的技术点思维导图我已经做了一个整理,涵盖了当下互联网最流行99%的技术点,在这里我将这份导图分享出来,以及为金九银十准备的一整套面试体系,上到集合,下到分布式微服务

Java-String-对象,你真的了解了吗?,mysql教程入门到精通_面试_02

Java-String-对象,你真的了解了吗?,mysql教程入门到精通_面试_03

Java-String-对象,你真的了解了吗?,mysql教程入门到精通_Java_04

Java-String-对象,你真的了解了吗?,mysql教程入门到精通_后端开发_05

本文已被 CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

版权声明
本文为[HarmonyOS学习]所创,转载请带上原文链接,感谢
https://blog.51cto.com/u_15438507/4690507

  1. jQuery-实例方法
  2. jQuery-dom和jQuery,入口函数(基本知识)
  3. JavaScript-this指向问题
  4. JavaScript-封装与继承(两种)
  5. JavaScript-包装类型
  6. JavaScript-传值(引用类型,基本类型)
  7. JavaScript-面向对象(构造函数,实例成员,静态成员)
  8. JavaScript-解构赋值
  9. JavaScript-箭头函数
  10. JavaScript-参数
  11. JavaScript-预解析(变量提升)
  12. JavaScript-闭包closure
  13. JavaScript-声明变量的关键字
  14. JavaScript - mot - clé pour déclarer une variable
  15. Fermeture de fermeture JavaScript
  16. JavaScript Pre - parse (promotion des variables)
  17. Paramètres JavaScript
  18. Fonction de flèche JavaScript
  19. JavaScript - déconstruction assignations
  20. Common annotations in springboot
  21. Building CentOS 7.6 with Linux
  22. JavaScript - orienté objet (constructeur, membre d'instance, membre statique)
  23. JavaScript value Transfer (reference type, Basic type)
  24. JavaScript - type d'emballage
  25. linux deepin/ubuntu安装flameshot火焰截图
  26. JavaScript - encapsulation et héritage (deux)
  27. JavaScript JS method for writing 99 multiplication table
  28. 從零開始學java - 第二十五天
  29. Apprendre Java à partir de zéro - jour 25
  30. Les voitures d'hiver, les voitures électriques et les voitures à essence ne sont pas les mêmes?
  31. JavaScript - ceci pointe vers le problème
  32. Copie JavaScript
  33. Spring boot quickly integrates swagger
  34. linux deepin/ubuntu安裝flameshot火焰截圖
  35. Capture d'écran de flamme de l'installateur de flamme Linux deepin / Ubuntu
  36. Jquery DOM et jquery, fonctions d'entrée (bases)
  37. Méthode d'instance jquery
  38. Méthode et démonstration de code dans l'interface de liste en Java
  39. 【错误记录】Java 中 ArrayList 排序 ( 使用 Comparator 接口时注意 compare 返回值是 -1 和 +1 )
  40. Démarrage du Zookeeper
  41. Java oom Cognition
  42. Java 开发者最困惑的四件事,值得一看!,BAT面试文档
  43. Java 将两个对象list里面的 某个字段值抽取到一个list里,java选择排序原理
  44. Java 多线程 —— 生产者消费者问题,从基础到深入案例
  45. Java 中设计模式 之 工厂模式,java反射机制的底层原理
  46. 【錯誤記錄】Java 中 ArrayList 排序 ( 使用 Comparator 接口時注意 compare 返回值是 -1 和 +1 )
  47. 【 enregistrement des erreurs 】 tri ArrayList en Java (Notez que les valeurs de retour de comparaison sont - 1 et + 1 lors de l'utilisation de l'interface de comparaison)
  48. Pourquoi Xiaopeng P5 est - il devenu un grand succès dans le cercle? Le Salon de l'automobile de Guangzhou montre encore des compétences polyvalentes
  49. Java 開發者最困惑的四件事,值得一看!,BAT面試文檔
  50. Les quatre choses les plus déroutantes pour les développeurs Java valent la peine d'être regardées! Document d'entrevue sur les MTD
  51. k8s-Pod污点与容忍
  52. k8s-Pod污点与容忍
  53. K8s POD Contamination and Tolerance
  54. K8s POD Contamination and Tolerance
  55. mysql常用语句——GROUP BY和HAVING
  56. Spring boot quickly integrates swagger
  57. mysql常用語句——GROUP BY和HAVING
  58. MySQL Common statements - group by and having
  59. Le défi du pinceau leetcode - Javascript: 110. Arbre binaire équilibré
  60. [notes d'apprentissage de première ligne] day44: XMLHttpRequest