关于创建String对象的抉择

关于创建String对象的抉择

标签(空格分隔): 与String有关的那些事儿
转自博客:java String 两种不同的赋值 比较



我的旧记忆


之前我的大脑还是有概念的,只是比较模糊,我知道创建一个String对象有几种形式。

  • String string=new String()
  • String string=”jfirehj”

但是我是真不知道这两种形式有没有区别,因此在比较String 对象的时候,理解到不了位。

public class EmptyTest {
    public static void main(String[] args) {
        String s1 = "iiii";
        String s2 = "iiii";
        if(s1==s2){
            System.out.println("you are right");
        }
        if (s1.equals(s2)) {
            System.out.println("you are right again");

        }
    }
}

输出是

you are right
you are right again

再来一次

public class EmptyTest {
    public static void main(String[] args) {
        String s1 = new String("iiii");
        String s2 = new String("iiii");
        if (s1 == s2) {
            System.out.println("you are right");
        }
        if (s1.equals(s2)) {
            System.out.println("you are right again");

        }
    }
}

输出:

you are right again

使用new是在堆上创建了两个不同的对象。但是这个字符串创建的怎么来进行解释呢?


新的认识


找到的两篇写得比较好的博文:
第一篇
第二篇

原来就还有一个常量池的概念。

类似普通对象,通过new 创建字符串对象


String str = new String(“Hello”); 内存图如下图所示,系统会先创建一个匿名对象”Hello”存入堆内存(我们暂且叫它A),然后new关键字会在堆内存中又开辟一块新的空间,然后把”Hello”存进去,并且把地址返回给栈内存中的str, 此时A对象成为了一个垃圾对象,因为它没有被任何栈中的变量指向,会被GC自动回收
此处输入图片的描述

直接赋值

如String str = “Hello”; 首先会去缓冲池中找有没有一个”Hello”对象,如果没有,则新建一个,并且入池,所以此种赋值有一个好处,下次如果还有String对象也用直接赋值方式定义为“Hello”, 则不需要开辟新的堆空间,而仍然指向这个池中的”Hello”,原来如此
此处输入图片的描述

这段代码证明结论:
此处输入图片的描述

手动入池

即使使用new关键字,第一种方式赋值,也可以使用一个java中的手动入池指令,让所创建的对象入池,以后依然可以背重复使用,利用下面两段代码可以测试, 如下图,结果显然是false,因为二者的地址不同。

此处输入图片的描述

国际惯例:总结

通过常量池的形式可以很好的提高效率,因此提倡直接赋值

后话:为什么String 可以直接赋值

打开了String.class,有这么一段介绍:

/** 
* The <code>String</code> class represents character strings. All 
 * string literals in Java programs, such as <code>"abc"</code>, are 
 * implemented as instances of this class. 
 * <p> 
 * Strings are constant; their values cannot be changed after they 
 * are created. String buffers support mutable strings. 
 * Because String objects are immutable they can be shared. For example: 
 * <p><blockquote><pre> 
 *     String str = "abc"; 
 * </pre></blockquote><p> 
 * is equivalent to: 
 * <p><blockquote><pre> 
 *     char data[] = {'a', 'b', 'c'}; 
 *     String str = new String(data); 
 * </pre></blockquote><p> 
 * Here are some more examples of how strings can be used: 
 * <p><blockquote><pre> 
 *     System.out.println("abc"); 
 *     String cde = "cde"; 
 *     System.out.println("abc" + cde); 
 *     String c = "abc".substring(2,3); 
 *     String d = cde.substring(1, 2); 
 * </pre></blockquote> 
 * <p> 
 */  

通过上面的介绍,我们可以清楚,直接赋值的话,是通过编译器在起作用,当你对”abc”没有通过new创建时,他会自动默认给你调用构造函数new String(char value[]). 不显式调用String的构造函数(通过new叫显式调用),其实JDK编译器会自动给你加上。

编译器主动调用构造方法的情况出现很多次了也

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值