logo头像

学如逆水行舟,不进则退!!!

文章目录

String中常量池那些事

本文于352天之前发表,文中内容可能已经过时。

前言

  • String使用最广泛。我们之前也通过new String来比较了==equals的区别。实际上我们在平时的开发中并不会通过new String 的方式来创建Stirng的
  • 我们大多数是通过Stirng text = "a"; 构建String的。通过双引号的方式不仅快速而且还有一个重大好处是他会将内容存储到常量池

问题描述

  • 上面也说了new String 是不断的开辟空间来存储内容的。但是String使用特别广泛这样操作的话很容易造成OOM
public static void main(String[] args) throws InterruptedException {
    List<String> list = new ArrayList<>();

    for (int i = 0; i < 200000; i++) {
        String text = new String("abcsdlkfjsldkfjsalkdjflkasjdflaksjdfl;kasdjgl;kasjgasldk;djgsadlkjgsadlkdjgfas;lkdfjsaf");
        list.add(text);
    }
    System.out.println(list.size());
}
  • 上面的程序是不断的创建一个字符串然后加入到集合中。如果你想更容易出现OOM现象你可以将字符串调的更大点循环加的更大点。
  • 除了此外我们还需要通过idea调整程序的最大堆内存 。

image-20210514103249065

  • 然后我们启动程序,不出意外就会出现OOM 。 而下面的错误是GC次数超出了限制了。
  • 这里我们这样理解GC说明堆中对象太多了。而GC太频繁是因为内存使用很多而且是使用的对象。所以每次GC但是删不掉任何对象
  • 这也侧面反映了new的弊端

image-20210514103319962

解析

  • 因为我们不停的new对象到堆中。堆中的空间又是有效的肯定会出现问题。你可能会说我的堆空间很大吃得消这些空间
  • 但是如果我的程序死循环了一直new对象呢。其实我们仔细分析下我们上面的代码。我们是不断的new相同内容在堆中。就好像你一直在写nihao在不同的纸上
  • 就算你写了100张纸。那么这样的意义又在哪里呢。所以java为我们提供了常量池。常量池就是专门存储string中内容的。因为我们的String大多数内容都会重复

优化

  • 下面我们将代码中new String的方式改用双引号。再运行程序看看结果
public static void main(String[] args) throws InterruptedException {
    List<String> list = new ArrayList<>();

    for (int i = 0; i < 200000; i++) {
        String text =  "abcsdlkfjsldkfjsalkdjflkasjdflaksjdfl;kasdjgl;kasjgasldk;djgsadlkjgsadlkdjgfas;lkdfjsaf";
        list.add(text);
    }
    System.out.println(list.size());
}
  • 此时程序就会执行成功。如果你借助其他类似visualvm工具就能够看到内存的使用情况了

image-20210514104534629

总结

  • 虽然我们使用双引号来实现字符串的构建。但是我们要知道构建出来的字符串都存在在JVM中的位置。这样就会避免掉值判断相等的问题了

老三样啊

上一篇
坚持原创技术分享,您的支持将鼓励我继续创作!

评论系统未开启,无法评论!