58同城的java字符串常量池
面试题代码
public class StringPools58Demo {
public static void main(String[] args) {
/*
(1).str1
str1 会有4个对象
一个StringBuilder、
一个58 ldc、
一个tongcheng ldc、
String
这个时候常量池中没有58tongcheng这个ldc在
str1.intern():在jdk7后,会看常量池中是否存在,如果没有,它不会创建一个对象,
如果堆中已经这个字符串,那么会将堆中的引用地址赋给它
所以这个时候str1.intern()是获取的堆中的
* */
String str1=new StringBuilder("58").append("tongcheng").toString();
System.out.println(str1);
System.out.println(str1.intern());
System.out.println(str1==str1.intern());//true
System.out.println();
/*
sum.misc.Version类会在JDK类库的初始化中被加载并初始化,而在初始化时它需要对静态常量字
段根据指定的常量值(ConstantValue)做默认初始化,此时sum.misc.Version.launcher静态常
量字段所引用的"java"字符串字面量就被intern到HotSpot VM的字符串常量池 - StringTable
里了
str2对象是堆中的
str.intern()是返回的是JDK出娘胎自带的,在加载sum.misc.version这个类的时候进入常量池
*/
String str2=new StringBuilder("ja").append("va").toString();
System.out.println(str2);
System.out.println(str2.intern());
System.out.println(str2==str2.intern());//false
}
}
讲解
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). 如果不是用双引号声明的String对象,可以使用String提供的intern方法: intern方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中
(2). 比如: String myInfo = new String(“I love u”).intern();
也就是说,如果在任意字符串上调用String. intern方法,那么其返回结果所指向的那个类实例,必须和直接以常量形式出现的字符串实例完全相同。因此,下 列表达式的值必定是true:
(“a” + “b” + “c”).intern()== “abc”;
(3). 通俗点讲,Interned String就是确保字符串在内存里只有一份拷贝,这样可以节约内存空间,加快字符串操作任务的执行速度。注意,这个值会被存放在字符串内部池(String Intern Pool)
why
按照代码结果,java字符串答案为false,必然是两个不同的java,那另外一个java在哪里?
有一个初始化的java,在加载sun.misc.Version类的时候,包括一个java字符串。
OpenJDK8底层源码
②. 原因解释一(字节码):
String str1=new StringBuilder(“58”).append(“tongcheng”).toString();
这句话中常量池中是没有58tongcheng的 无ldc
③.原因解释二(深入OpenJDK8底层源码分析):
(sum.misc.Version类会在JDK类库的初始化中被加载并初始化,而在初始化时它需要对静态常量字段根据指定的常量值(ConstantValue)做默认初始化,此时sum.misc.Version .launcher静态常量字段所引用的"java"字符串字面量就被intern到HotSpot VM的字符串常量池 - StringTable里了)
考查点
intern()方法,判读true/false ? 《深入理解java虚拟机》是否读过。
字节跳动两数求和
面试题
提供力扣网址:https://leetcode-cn.com/problems/two-sum/
解法
使用暴力法和哈希解法:
/*
题目:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,
并返回他们的数组下标你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使
用两遍。
* */
public class TwoSumDemo {
public static void main(String[] args) {
int[]nums ={2, 7, 11, 15};
int target = 9;
//int[]indexCollection=twoSum1(nums,target);
int[]indexCollection=twoSum2(nums,target);
if(indexCollection!=null){
for (int index : indexCollection) {
System.out.print(index+" ");
}
}
}
//1.暴力法:
//通过双重遍历数组中所有元素的两两组合,当出现符合的和时返回两个元素的下标
public static int[] twoSum1(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i+1; j <nums.length ; j++) {
if(target-nums[i]==nums[j]){
return new int[]{i,j};
}
}
}
return null;
}
//2.哈希(更优解法)
public static int[] twoSum2(int[] nums, int target){
Map<Integer,Integer> map=new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int param=target-nums[i];//2 7
if(map.containsKey(param)){
return new int[]{map.get(param),i};
}
map.put(nums[i],i);
}
return null;
}
}
考查点
力扣网站上的算法