Java代码优化(1)—String字符串

    技术2022-06-24  52

        Java编程中,字符串的使用频率是非常高的。因此,对字符串进行性能优化,将会在一定程度上减小JVM的负担,提升程序的运行效率。或许,我们在平时的编程中并没有感觉到这种细微的变化所带来的差异,但是,当我们需要处理海量的数据时,这种性能上的影响就会十分的明显了,也容不得我们忽略。

        Java编译器在对字符串操作这部分做了大量的优化工作,基本上已经达到了极致。下面我将分条进行说明。

        String存储:JVM中有一个字符串常量池,当我们定义了一些字符常量时,JVM内部首先会从常量池中查找,如果找到,则将引用直接指向该对象;否则,创建一个对象,并放入到常量池中,然后将引用指向该对象。注意:这里定义字符的方式跟定义基本类型的方式一致,如String a = "test",或者使用String对象提供的静态方法valueOf(),如String a = String.valueOf("test"),我们尽量不要使用new来创建一个对象,这样不仅失去了上述的特性,而且在创建和销毁对象时都会消耗一部分JVM的处理时间。

        String+运算: Java中的String同时也实现了+的运算符重载操作,可以直接使用+实现字符串连接,当我们将两个字符串常量(可以是非字符串类型的,如一个整数)相加时,编译器会在编译时进行计算优化,如String ab = "a" + "b"; 和 String ab = "ab"; 在编译器执行编译后得到的字节码是完全相同的,当然,这里也可以使用final类型的变量来替代字符常量。总之,我们可以把字符串的这种运算看作是基本类型数据的优化操作(基本数据类型在执行编译时,会进行一部分数据计算和优化)。

        String连接:通常,我们需要将多个字符串进行拼接来生成一个新的字符串,如构造SQL语句,重写toString方法等等。一般情况有四种方式可供我们选择。第一,直接使用+运算符;第二,使用String的concat方法;第三,使用StringBuilder;第四,使用StringBuffer。对于第一种方法,需要为运算符两侧的操作数构造对象,当完成连接操作后,需要再次构造一个新的字符串对象,这样就可能会导致很多无用的对象被构造出来,不仅消耗了大量的CPU时间,还需要进行后期的垃圾回收,所以这种方法不推荐使用;第二种方法是第一种方式的一个实现,所以就不再重叙了,该不该用大家自己决定吧;第三种方式是构造一个缓冲区,然后将字符串通过append的方式进行追加,最后通过调用toString方法获取连接后的字符串,这种方式可以减少对象的创建次数,推荐使用,不过StringBuilder是非线程安全的,只能在单线程环境下使用,这也使它的运行速度稍稍的快些,如果希望在多线程环境下执行连接操作,可以使用StringBuffer,它是StringBuilder的一个安全实现,支持多线程运行,但这也或多或少的影响了它的性能。

        个人几条建议:第一,尽量不要自己创建对象,而使用Java内部提供的函数来创建。你要相信,就算你很牛掰,你做了很大的优化,也不如别人底层做的优化好;第二,创建缓冲区时,尽量能够指定它的大小,这样可以避免重新分配缓冲区长度时消耗的资源和时间。当然,大部分时间我们是无法指定的,所以我说的是尽量;第三,尽量避免生成那些生命周期短的对象或变量,如果有很多对象和变量需要管理,我们可以定义一个对象缓冲池来进行管理,这样会比频繁的生成和销毁对象开销小很多;第四,对于一些不随对象而改变的内容,可以使用静态变量,从而使所有的实例都共享这个变量;第五,对于一些常量,可以使用final进行修饰;第六,如果有些程序对效率和空间要求比较高,可以考虑对对象进行延缓加载,即在需要时才去创建对象。

        先就这么多,如果有什么好的思想或建议,希望大家一起来分享。


    最新回复(0)