JAVA基础学习之路(八)[1]String类的基本特点

String类的两种定义方式:

  1. 直接赋值

  2. 通过构造方法赋值 

//直接赋值
public class test2 {
    public static void main(String args[]) {
        String str = "hello"; 
        System.out.println(str);
    }    
}


//通过构造方法
public class test2 {
    public static void main(String args[]) {
        String str = new String("hello");
        System.out.println(str);
    }    
}

但是,两种方法却有着极大的区别

主要体现在内存

一个简单的例子:

public class test1 {
    public static void main(String args[]) {
        int a = 10;
        int b = 10;
        String str_1 = "hello";
        String str_2 = "hello";
        String str_3 = new String("hello");
        System.out.println(a==b);
        System.out.println(str_1==str_2);
        System.out.println(str_1==str_3);
        System.out.println(str_2==str_3);    
    }
}   //输出为true true  false false

按道理来说,应该是四个true,因为他们的值都是相等的啊.......但是.....

上图解释了两个通过直接赋相同值产生的字符串使用“”==“”为什么返回true。

为什么会全部指向一块堆内存而不是分别指向自己的堆内存呢???

共享设计模式:

在JVM底层有一个对象池,里面有包括String在内的许多对象,当代码之中使用了直接赋值的方式定义了一个String类对象时,会将此字符串使用的匿名对象加入对象池。之后若有采用直接赋值的方式定义字符串,并且赋了相同的值,那么不会开辟新的堆内存空间,而是使用已有的对象(堆内存)进行继续使用。

上图解释了为什么直接赋值和构造方法赋相同的值,然而返回值却为false。因为使用构造方法定义字符串,使用了new关键字,意味着产生一块新的堆内存。那么两种方法各自开辟了一块堆内存,“==”符号对于字符串来说,比较的是地址值。两块堆内存的地址不同,所以返回值为false。

若要比较字符串的内容,而不是地址,应该使用str_a.equals(str_b)

字符串常量就是String类的匿名对象,所谓的直接赋值实际上就是为匿名对象加了一个名字。但是String类的匿名对象是由系统自动生成的,不用用户自己创建

public class test1 {
    public static void main(String args[]) {
        String str = "hello";
        System.out.println("hello".equals(str));    
    }
}
//返回值为true

tips:

防止空指向异常(使用了未实例化的对象):将字符串写在输入的前面

public class test1 {
    public static void main(String args[]) {
        String input = null;
        System.out.println(input.equals("hello"));    
    }
}
//Exception in thread "main" java.lang.NullPointerException
    at test.test1.main(test1.java:6)  空指向异常


public class test1 {
    public static void main(String args[]) {
        String input = null;
        System.out.println("hello".equals(input));    
    }
}
//false

两种定义方法的优劣:

直接赋值节约空间

然而构造方法却会产生大量垃圾,如下图:

代码从右向左看,产生的第一块堆内存会成为垃圾

构造方法实例化的方法除了浪费内存外,其定义的对象不会保存在对象池之中,若要保存,需要手动入池(使用inner()方法)

public class test1 {
    public static void main(String args[]) {
        String str_1 = new String("hello").intern();
        String str_2 = "hello";
        System.out.println(str_1==str_2);    
    }
}
//true

返回值为true,证明入池成功。

原文地址:https://www.cnblogs.com/xhnxhnu/p/9129101.html