java字符串之面试题

1、判断s1和s2是否相等

	String s1 = "123";
	String s2 = "123";
	System.out.println(s1 == s2);       // true
	System.out.println(s1.equals(s2));  // true

首先需要知道的是第一种方式是常量池中的对象的地址的比较

第二种是利用了String类的equals方法比较,看下源码:

public boolean equals(Object anObject) {
    	// 判断当前的string对象是否和传入进来的对象的地址值相同
        if (this == anObject) {
            return true;
        }
    	// 传入进来的对象是否是字符串类型的
        if (anObject instanceof String) {
            // 向下转型,利用多态性质
            String anotherString = (String)anObject;
            // 判断两个字符串的长度是否是相等的
            int n = value.length;
            if (n == anotherString.value.length) {
                // 拿到当前对象的数组和比较进来的数组
                // 居然还有这种操作,对于同种数据类型的来说,可以直接来进行操作
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                // 遍历每一个字符数组中的每一个元素
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
    	// 如果对象既不是和当前string对象地址相同;也不是同一个类型的;长度也不相等
        return false;
    }

可以看到返回true的只有两个地方:一、是同一个对象;第二个、字符串中的每个字符都是相同的。

但是对于字符串来说,无论是哪一种都是可以的,只不过第一种的话更加实用而已。

2、以下代码创建了几个对象

	String s = new String("abc");

首先第一步:确定常量池中是否有"abc"这个对象,如果没有,那么先在常量池中创建"abc"对象;如果有,那么就不需要在创建;

然后再从堆中的其他空间来创建一个对象,"abc"

所以可能创建了一个对象,也可能是创建了两个对象。这取决于常量池中是否有"abc"

3、判断new String是否相等

		String s1 = new String("abc");
		String s2 = "abc";
        System.out.println(s1 == s2);            // false
        System.out.println(s1.equals(s2));       // true

第一行代码先去常量池中查找是否"abc"对象,然后再去堆中创建一个对象,返回s1指向堆中的内存;

第二行中直接返回常量池中的地址;

第三行中==比较的是两个字符串的地址不同,所以返回为false;

第四行中利用的equals方法比较的是两个字符串,上面已经分析过了。

这里需要注意的是:堆内存中的和常量池中的都是用数组来进行存储的,比较的是数组中的字符

4、string被final修饰,值是不可变的,解释?

String类上就是用final来进行修饰的,所以这个类是无法继承的;

String类中用来存放成员的字符串使用char数组,只不过使用final来修饰的变量,如果一旦确定了值,那么对应的地址将无法来进行修改。但是我们可以修改其中的数组中的值,但是String类并没有来给我们提供。

int i = 0;
while(true){
    if(i>obj.length) break;
    obj[i] = i;
    i++;
}

可以赋值,也可以来修改值。但是数组的引用是固定的。

String类但是我们去做修改,并没有提供对应的方法来进行操作。

看看下面这段代码:

	 String s = "Java";
	 s = "HTML";

值是不可变的,说的是存储的字符串的地址是没有办法改变的,但是引用可以随便指向。

对于状态来说,已经是固定的,无法来对其进行修改。

5、拼接字符串是否相等

		String s1 = "a"+"b"+"c";
        String s2 = "abc";
        System.out.println(s1 == s2);    // true

思考问题:对于"a"、"b"、"c","abc"常量池中是否存在。

如果来进行验证,通过intern()方法来进行验证:

        String a = new String("a");
        String intern = a.intern();
        System.out.println(a==intern);  // false

这说明了常量池中已经有了这个"a",其实一开始就是不需要验证的。

6、变量拼接字符串相等吗?

		String s1 = "ab";
        String s2 = "abc";
        String s3 = s1 + "c";
        System.out.println(s3 == s2);        // false
        System.out.println(s3.equals(s2));   // true

需要注意的:第三行中的使用方式

因为s1是变量,所以在编译的时候无法确定,只有在运行的时候才会确定下来值。

底层实现是会先创建一个StringBuilder/StringBuffer的对象来进行append()方法来进行追加,然后将追加后的字符串数据利用toString的方式创建出来一个新的String对象。所以s3中其实返回的是堆中的地址

与下面的类似:

String s3 = new String("abc");

s3和s2相比不是同一块内存地址,所以不可能相等

这里我再衍生一下:

        String s1 = "ab";
        String s2 = "abc";
        String s3 = "ab" + "c";
        System.out.println(s3 == s2);        // true
        System.out.println(s3.equals(s2));   // true

这里为什么又是不相等的了?因为这里是在编译阶段做的事情,相当于执行完了第三行代码,已经返回了常量池中的"abc"的地址了。

posted @ 2021-09-10 00:27  写的代码很烂  阅读(180)  评论(0编辑  收藏  举报