String的两种实例化方式 学习笔记

hkwljs 2017-7-27 16829


字符串操作是计算机程序设计中最常见的行为。以下是String的源码:

public final class String     implements java.io.Serializable, Comparable<String>, CharSequence { }

我们可以看出String是final类型,不能被继承。它继承了3个接口,Serializable(可序列化的)、Comparable(可比较的)、CharSequence(字符序列)。

  • 继承Serializable接口,可以被JVM序列化成文件
  • 继承Comparable接口,主要实现它的compareTo(T o)方法,此方法用来比较两个字符串的长度,返回一个int值。
  • 继承CharSequence接口,实现的方法常用的有length()、toString()等。

顺便提醒,Java是单继承、多实现语言。

隐式实例化:直接赋值

public class Demo {     public static void main(String[] args) {         String s = "hello";         String s2 = "hello";         System.out.println(s == s2);     } }

以上直接赋值,是我们常用的实例化方式。通过输出结果为true可知,对于s2引用来说,没有重新新建一个匿名对象,而是将s2引用指向”hello”对象。“==”判断两个对象引用是否指向同一个对象。

从JVM角度来看。JVM将在堆中给”hello”分配一块内存,在虚拟机栈(局部变量表)中给s、s2分配一块内存,均指向”hello”。如下图,其中内存地址0x1001只是一个假设,知道代表一个内存地址就行。

String的两种实例化方式

image

那如果隐式实例化如下,引用与匿名对象是什么关系?

String s = "hello"; s = "world";

因为String是final类型,即一个String对象创建后就不能被修改。所以”world”是一个新匿名对象。s引用指向”world”,”hello”对象会被回收。如下图所示:

String的两种实例化方式

image

显式实例化:使用构造函数

public class Demo {     public static void main(String[] args) {         String s = "hello";         String s2 = new String("hello");         String s3 = new String("hello");         System.out.println(s==s2);         System.out.println(s==s3);         System.out.println(s2==s3);     } }

从输出三个false可以看出,三个对象均不相同,从JVM分析,有如下图示:

String的两种实例化方式

image

显式实例化常用于将字符数组转换为字符串,使用方式如下:

String string = "hello"; char[] array = string.toCharArray(); return new String(array);

总结

直接赋值是一种共享设计,所有匿名对象放在方法区(逻辑上的堆)的字符串常量池中,新实例化的对象如果已经在字符串常量池存在,就不再新建对象,而是直接使用。所以推荐使用直接赋值方式。


最新回复 (0)
全部楼主
返回
发新帖