浅谈java中==,equal(),String.intern()的原理

在学习String类型时,看到使用引用型变量作为方法的输入参数举例,于是查阅有关资料,大概对其做了了解。

一.首先要了解什么是字符串常量池(String Constant Pool)

        字符串在java程序中被大量使用,为了避免每次都创建相同的字符串对象及内存分配,JVM内部对字符串对象的创建做了一定的优化,在Permanent Generation中专门有一块区域用来存储字符串常量池(一组指针指向Heap中的String对象的内存地址)。

        程序运行时,可以通过String类的intern()方法动态地扩充字符串常量池。当调用 intern 方法时,如果池已经包含一个等于此String对象的字符串(用 equals(object)方法确定),则返回池中的字符串。否则,将此String 对象添加到池中,并返回此String对象的引用。所有字面值字符串和字符串赋值常量表达式都使用 intern 方法进行操作。

创建字符串对象的几种形式:

(1)通过new方式如String s = new String("aa")及string.intern()方法

(2)通过字面量的形式如String s = "aa"

(3)字面量+字面量如String s = "b" + "c"

(4)字面量+变量如String s1 = "d"; String s = "e"+s1

对于通过new方式创建的String对象,每次都会在Heap(堆)上创建一个新的实例,但是对于字符串字面量的形式,只有当字符串常量池中不存在相同对象时才会创建。

//关于堆Heap的解释

swift-algorithm-club/Heap at master · raywenderlich/swift-algorithm-club · GitHub

第二种方式不用说,相当于第一种方式中的字面量部分。

第三种和第四种方式会怎样创建字符串对象呢?

关于字符串常量池的问题可以看以下文章:

JDK1.8字符串常量池里存的是String对象还是引用?

img

翻译:String类的intern()方法:一个初始为空的字符串池,它由类String独自维护。当调用 intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(oject)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象(注意是常量池中的对象,不是堆中的对象)的引用。 对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s.intern() == t.intern()才为true。所有字面值字符串和字符串赋值常量表达式都使用 intern方法进行操作。

自己用代码举了几个例子:

package com.company;

import com.sun.org.apache.xml.internal.utils.StringToStringTable;

public class Main {
    public static void main(String[] args) {
        String s1="hello";//创建String型引用变量s1,指向字符串常量池中的"hello"字符串。
        String s2=new String("hello");//栈中创建s2引用变量,堆内存中创建"hello"字符串对象,并被s2指向。
        System.out.println(s1 == s2);//false
        String s3="h"+"ello";//"h"和"ello"合成为字符串常量"hello",先在字符串常量池中查找是否已有"hello"字符串对象,已有,不再重新创建对象
        System.out.println(s1 == s3);//true
        String s4="h"+new String("ello");//在堆中创建了"ello"对象,与"h"相加,返回新的字符串对象赋给s4,s4还指向堆中的字符串对象。
        System.out.println(s1==s4);//false
        System.out.println(s2==s4);//false
    }
}
package com.company;

import com.sun.org.apache.xml.internal.utils.StringToStringTable;

public class Main {
    public static void main(String[] args) {
        String string1 = "hello";
        String string2 = new String("hello");
        String string3 = new String("hello");
        System.out.println(string1 == string2.intern());//true
        System.out.println(string2 == string3.intern());//false
    }
}

 记录自己学习java的历程

参考文章:

JDK1.8字符串常量池里存的是String对象还是引用? - 程序员曾奈斯 - 博客园

java 字符串,字符串缓冲区_chen_yuyunfox的专栏-CSDN博客_java 字符串缓存 

String literal pool – iByteCode Technologies 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值