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;
评论