现在的位置: 首页 > 综合 > 正文

java字符串面试(一)

2018年02月05日 ⁄ 综合 ⁄ 共 2153字 ⁄ 字号 评论关闭

1. String对象是不可变的,String类中每一个看起来修改String值的方法,实际上都是创建了全新的String对象。

package com.lyj.string;

/*
 * String是不可变的
 */
public class StringDemo {

    public static void main(String[] args) {
       String s1 = "lyj";
       System.out.println(s1);
       
       String s2 = upcase(s1);
       System.out.println(s2);
       System.out.println(s1);
    }
    
    public static String upcase(String s) {
        return s.toUpperCase();
    }

输出结果是lyj, LYJ, lyj。s.toUpperCase(String s)会创建一个新的String对象,返回时返回指向这个对象的引用。 如果s1不指向新的对象,则它指向的值始终是lyj。


2. String对象是不可变的,可以给String对象加任意多的别名,因为String对象具有只读性,所以指向它的任何引用都不能改变它的值。

package com.lyj.test;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String s1 = "lyj";
        String s2 = "zky" + s1 + "age";
        System.out.println(s2);
    }

}

这个例子中,编译器会创建一个StringBuilder对象,用于构造最终的String,并且为每个字符串调用一次StringBuilder的append方法,总计4次。最后调用toString生成结果,并保存为s2.

StringBuilder是java SE5引入的,在这之前java用的StringBuffer.后者是线程安全的,因此开销会大一点,所以在引入StringBuilder操作字符串会更快一点。


3.

  public static void main(String[] args) {
        String hello = "hello";
        String hel = "hel";
        String lo = "lo";

        /*
         * 输出true 
         * 在"+"两边都是常量字符串,则将两个字符串合并并且在String Pool中查找"hello",然后返回他的内存地址
         */
        System.out.println(hello == "hel" + "lo");

        /*
         * 输出false 
         * "编译器为了对"hel" + lo语句进行优化,其实会创建一个StringBuilder对象,然后依次调用它的append方法,
         * 最后调用toString方法返回一个String对象的引用。
         */
        System.out.println(hello == "hel" + lo);
    }

4.

public static void main(String[] args) {
        /*
         *  虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。对于第一种,jvm会马上在heap中创建一个String对象,
         *  然后将该对象的引用返回给用户。对于第二种,jvm首先会在内部维护的strings pool中通过String的 equels 方法查找是对象池中是否存放有
         *  该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果对象池中没有该String对象,
         *  jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。
         *  注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法。
         */
        String s1 = new String("abc");
        String s2 = "abc";
        String s3 = new String("abc");

        System.out.println(s1 == s2);//false
        System.out.println(s1 == s3);//false
        System.out.println(s2 == s3);//false

        // 程序显式将s1放到strings pool中,intern运行过程是这样的:首先查看strings pool
        // 有没“abc”对象的引用,没有,则在堆中新建一个对象,然后将新对象的引用加入至
        // strings pool中。执行完该语句后,str1原来指向的String对象已经成为垃圾对象了,随时会
        // 被GC收集。s1.intern()是在String Pool中的“abc"的引用,s1是在heap中新建“abc”对象的引用。
        //分析这类题最好画图,这样比较好理解
        System.out.println(s1 == s1.intern());//false
        System.out.println(s2 == s1.intern());//true
        System.out.println(s2 == s2.intern());//true
        System.out.println(s1.intern() == s3.intern());//true
    }

分析图如下:

抱歉!评论已关闭.