「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」 1.废话少说:我们直接上面试题?
当前字符串中intern(),结果如何,细说一下原因?
package com.test.testdelete.controller;
import java.sql.SQLOutput;
/**
* @author 卢卡多多
* @create 2021-7-23 22:10
* @description 对于字符串,intern()输出对比?
*/
public class StringByte58 {
public static void main(String[] args) {
String lucas = new StringBuilder("58").append("tongcheng").toString();
System.out.println(lucas);
System.out.println(lucas.intern());
System.out.println(lucas == lucas.intern()); //TURE
System.out.println("-------------------------------");
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2);
System.out.println(str2.intern());
System.out.println(str2 == str2.intern()); //FALSE
}
}
只有java是错误的,其实都是都是正确的表示
解析Intern的方法,
源码:
/**
* Returns a canonical representation for the string object.
* <p>
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
* <p>
* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
* <p>
* It follows that for any two strings {@code s} and {@code t},
* {@code s.intern() == t.intern()} is {@code true}
* if and only if {@code s.equals(t)} is {@code true}.
* <p>
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section 3.10.5 of the
* <cite>The Java™ Language Specification</cite>.
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
*/
public native String intern();
1.为什么说只有Java是错误的?
java, java.intern
为什么其他的对象可以直接在常量池中返回,但是就是java这个字符串不行呢;
也就是说,我们自己建立的string的java字符不是不想同,如果相同就会直接是true;
因为"java "这个是Java自己JDK自带的,在加载sun.misc.Version这个类的时候进入常量池
demo:
package com.atguowang.thirdinterview.javabase;
/**
* @author 卢卡多多
* @description 字符串常量池的面试
**/
public class TestString58 {
public static void main(String[] args) {
// String str1=new StringBuffer("2020/10/20").append("22:45").toString();
// //打印
// System.out.println(str1);
// System.out.println(str1.intern());
// //打印
// System.out.println(str1 == str1.intern());
String str2=new StringBuffer("ja").append("va").toString();
//打印
System.out.println(str2);
System.out.println(str2.intern());
System.out.println("java".intern());
System.out.println(str2 == str2.intern());
System.out.println("java" == "java".intern());
System.out.println(str2 == "java");//引用地址不同
//
// String str3=new StringBuffer("hell").append("alibaba").toString();
// //打印
// System.out.println(str3);
// System.out.println(str3.intern());
// //打印
// System.out.println(str3 == str3.intern());
}
}
2.面试题:"java"=="java".intern()的答案是什么?,如何理解?
也就是说,当我们使用的过程中,jdk,底层已经有个"java"的字符串字面量了,所以我们自己创建一个java对象的String的对象,然后我们可以将数据对比的时候,(假设str=="java")
str == str.intern();
其实str.intern();(native的是运行计算机底层的本地的,如果说存在这个对象,直接存常量池中取出来,然后去返回,)要是不存在吗,就创建一个然后直接返回,并将创建好的数据转化为具体的----》常量池中;
现在来揭晓答案:
第一个为false,是因为str1虽然是“Java”,但是对于Str.intern()的时候,我们JDK底层,jdk/jre/lib/rt.jar/sun.misc/version类中有具体一个表示,已经明确的实例化出“java”的数据,将这个数据放到了常量池中,所以展示的两个“java”,一个来源于自己创建的,一个是底层已经定义好的,引用地址不一样,所以false;
第二个为ture: 因为他是直接的字面量,不是通过new得来的String对象,我们底层JDK已经实现了常量池,所以他们会复用返回,--->TUREl;
至于第三个:false,因为String是一个引用类型的数据,==表示对比的事引用对象的地址;
一个是自己创建的时候,从内存中开辟空间得出的,一个是JDK自己已经有存放在常量池中的数据;
3.JDK 8的深层次的源码解析:
System--》initializeSystemClass-->sun.misc.version=java;