01_java字符串常量池

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&trade; 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;
    }
}

考查点

力扣网站上的算法

猜你喜欢

转载自blog.csdn.net/kongfanyu/article/details/112726390
今日推荐