Java面试题(基础)字符串

  • String是基本的数据类型吗?String能被继承吗?

不是。Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(reference type),Java 5以后引入的枚举类型也算是一种比较特殊的引用类型。
扩展:String是java.lang包下的一个final类,由Java默认导入,所以不需要写import导入,类似的还有System,Math,基本数据类型包装类。

扩展:String不可变以及不可继承的好处

(1)有当字符串是不可变的,字符串常量池才能实现,字符串池的实现可以在运行时节约很多堆空间,因为不同的字符串变量都指向池中的同一个字符串;

(2)可以避免一些安全漏洞,比如在 Socket 编程中,主机名和端口都是以字符串的形式传入,因为字符串是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变字符串指向的对象的值,造成安全漏洞;

(3)多线程安全,因为字符串是不可变的,所以同一个字符串实例可以被多个线程共享,保证了多线程的安全性;

(4)适合做缓存的 key,因为字符串是不可变的,所以在它创建的时候哈希值就被缓存了,不需要重新计算速度更快,所以字符串很适合作缓存的中的 key。

  • 为什么要把String设计为不变量?

(1)节省空间:字符串常量存储在JVM的字符串池中可以被用户共享。
(2)提高效率:String会被不同线程共享,是线程安全的。在涉及多线程操作中不需要同步操作。
(3)安全:String常被用于用户名、密码、文件名等使用,由于其不可变,可避免黑客行为对其恶意修改。

  • String和StringBuffer有什么区别?

String用于字符串操作,属于不可变类。String对象一旦被创建,其值将不能被改变。而StringBuffer是可变类,当对象创建后,仍然可以对其值进行修改。

  • 简述String/StringBuffer与StringBuilder

String类采用利用final修饰的字符数组进行字符串保存,因此不可变。如果对String类型对象修改,需要
新建对象,将老字符和新增加的字符一并存进去。

StringBuilder,采用无final修饰的字符数组进行保存,因此可变。但线程不安全,但效率比StringBuffer高。

StringBuffer,采用无final修饰的字符数组进行保存,可理解为实现线程安全的StringBuilder,效率比StringBuilder稍差。

  • String s = new String(“xyz”);创建了几个字符串对象?

一个或者两个。如果在常量池中没有“xyz”的话,就会在常量池中创建一个"xyz"对象,另外面一个是用new创建在堆上的对象;如果在常量池中有“xyz”的话,则在堆上创建一个对象s,指向常量池中的“xyz”。
扩展:(字符串常量池)字符串常量池是存储在 Java 堆内存中的字符串池,是为防止每次新建字符串带的时间和空间消耗的一种解决方案。在创建字符串时 JVM 会首先检查字符串常量池,如果字符串已经存在池中,就返回池中的实例引用,如果字符串不在池中,就会实例化一个字符串放到池中并把当前引用指向该字符串。

  • (String)如下程序的输出结果是?
public class StringTest {
    
    
    public static void main(String[] args) {
    
    
        String s1 = "Hello," + "word!";
        String s2 = "Hello,word!";
        String s3 = new String(s1);
        String s4 = "Hello,";
        s4+="word!";
        System.out.println(s1 == s2);  // true
        System.out.println(s1 == s3);  // false
        System.out.println(s1 == s4);  // false
        System.out.println(s2 == s3);  // false
        System.out.println(s2 == s4);  // false
        System.out.println(s3 == s4);  // false
    }
}

String s1 = “Hello,”+”word!”;会被JVM优化为String s1 = “Hello,word!”,存贮在字符串常量池中,而s2的内容与s1相同,所以s1与s2都指向常量池中的”Hello,word!”;而s3是通过new关键字创建出来的,s3的地址在堆上,s3的字符串内容在常量池已经有,指向常量池中的“Hello,word!”。s4+=“word!”的过程相当于将原有的s4变量指向的对象内容取出与“word!”作字符串相加操作在存进另一个新的String对象中,在让s4变量指向新生成的对象。
扩展:String s=“abc”;形式赋值在java中叫直接量,它是在常量池中而不是像使用new关键字一样放在压缩堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abc"的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指向了同一对象,如果没有,则在常量池中新创建一个"abc",下一次如果有String s1 = “abc”;又会将s1指向"abc"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象.而String s = new String(“abc”);和其它任何对象一样.每调用一次就重新分配内存空间产生一个对象。简单的来说: String str = “abc”; 先在内存中找是不是有"hello"这个对象,如果有,就让str指向那个"abc".如果内存里没有"abc",就创建一个新的对象保存"abc"。
hello"这个对象,如果有,就让str指向那个"abc".如果内存里没有"abc",就创建一个新的对象保存"abc"。

猜你喜欢

转载自blog.csdn.net/chen15369337607/article/details/126046454