• Java中String类常见问题汇总


    1.字符串常量和字符串对象比较

    String str1 = "joshua317";
    String str2 = new String("joshua317");
    System.out.println(str1 == str2);//false
    System.out.println(str1.equals(str2));//true
    /**
    str1没有使用new关键字,在堆中没有开辟空间,其值"joshua317"在常量池中,str2使用new关键字创建了一个对象,在堆中开辟了空间,"=="比较的是对象的引用,即内存地址,所以str1与str2两个对象的内存地址是不相同的;
    而equals() 方法用于将字符串与指定的对象比较。String 类中重写了 equals() 方法,用于比较两个字符串的内容是否相等。
    **/
    

    2.Java字符串内存结构剖析

    package com.joshua317;
    
    public class Main {
        String str = new String("joshua317");
        char[] ch = {'j','a','v','a'};
        public static void main(String[] args) {
            Main main = new Main();
            main.change(main.str, main.ch);
            System.out.print(main.str + "and");
            System.out.print(main.ch);
            //输出结果为joshua317andgava
        }
    
        public void change(String  str,char ch[]){
            str = "str change";
            ch[0]='g';
        }
    }
    /**
    在方法调用时,在change方法中对str的值进行修改,是将str指向了常量池中的"str change",而主方法中的ex.str仍然指向的是常量池中的"joshua317"。字符型数组在方法调用时,将主方法中ex.ch的引用传递给change方法中的ch,指向是堆中的同一堆空间,所以修改ch[0]的时候,ex.ch可以看到相同的修改后的结果。
    **/
    

    3.Java中所有引用类型的默认值都是null

    package com.joshua317;
    
    public class Main {
        public static void main(String[] args) {
            String[] strings = new String[2];
            System.out.println(strings[0]);//null
            System.out.println(strings[1]);//null
    
            Integer[] integers = new Integer[2];
            System.out.println(integers[0]);//null
            System.out.println(integers[1]);//null
    
            int[] ints = new int[2];
            System.out.println(ints[0]);//0
            System.out.println(ints[1]);//0
        }
    }
    /**
    对象、数组都是引用数据类型。
    所有引用类型的默认值都是null。
    基本数据类型,根据类型不同,默认值不同,比如int默认值为0,float默认值是 0.0f
    **/
    

    4.字符串常量比较,字符串对象比较

    package com.joshua317;
    
    public class Main {
        public static void main(String[] args) {
            String s1 = new String("joshua317");
            String s2 = new String("joshua317");
            System.out.print(s1 == s2);//false
            String s3 = "joshua317";
            String s4 = "joshua317";
            System.out.print(s3 == s4);//true
            s1 = s3;
            s2 = s4;
            System.out.print(s1 == s2);//true
        }
    }
    /**
    字符串常量在常量池中;
    对象在堆中开辟空间
    **/
    

    5.Java中字符串数据的比较

    package com.joshua317;
    
    public class Main {
        public static void main(String[] args) {
            String a = "joshua317";
            String b = new String("joshua317");
            String c = "joshua" + "317";
            String str1 = "joshua";
            String str2 = "317";
            String d = str1 + str2;
            System.out.println(a == b);//false
            System.out.println(a == c);//true
            System.out.println(a.equals(b));//true
            System.out.println(a.equals(c));//true
            System.out.println(a.intern() == b.intern());//true
            System.out.println(a == b.intern());//true
    
            System.out.println(c == d);//false
            System.out.println(c.equals(d));//true
            System.out.println(b.intern() == d.intern());//true
            System.out.println(c.intern() == d.intern());//true
            System.out.println(b == d.intern());//false
        }
    }
    
    /**
    字符串比较分为两种形式
    一种使用比较运算符"=="比较,他们比较的是各自的字符串在内存当中的地址值是否相同;
    一种是使用equals()方法进行比较,比较的是两个字符串的内容是否相同!
    String类的intern()方法,含义如下:返回字符串对象的规范化表示形式。它遵循以下规则:
    对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。
    
    尽管在输出中调用intern方法并没有什么效果,但是实际上后台这个方法会做一系列的动作和操作。在调用b.intern()方法的时候会返回"joshua317",但是这个方法会首先检查字符串池中是否有"joshua317"这个字符串,如果存在则返回这个字符串的引用,否则就将这个字符串添加到字符串池中,然会返回这个字符串的引用。
    
    字符串常量相加时,先相加,然后在字符串常量池找,如果有就直接返回,否则就创建。
    字符串常量相加,jvm 会进行优化,不会创建 StringBuilder 对象
    
    字符串变量相加时,先开辟空间再相加;
    字符串变量加上常量,会创建 StringBuilder 对象,然后调用 append 方法
    **/
    

    6.字符串如何转换为int类型

    package com.joshua317;
    
    public class Main {
        public static void main(String[] args) {
            String str = "123";
            int num1 = Integer.parseInt(str);
            int num2 = Integer.valueOf(str);
            int num3 = new Integer(str);
    
            System.out.println(num1);//123
            System.out.println(num2);//123
            System.out.println(num3);//123
        }
    }
    

    7.String类型是基本数据类型吗?

    (1)java.lang.String类是引用数据类型,并且是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类
    (2)基本数据类型包括byte、short、int、long、char、float、double、boolean
    

    8.Java语言中,String类中的indexOf()方法返回值的类型是int

     

    9.String类是否可以被继承

    不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。
    
     

     

    10.String类为什么是final的

    (1) 为了效率。若允许被继承,则其高度的被使用率可能会降低程序的性能。
    (2) 为了安全。JDK中提供的好多核心类比如String,这类的类的内部好多方法的实现都不是java编程语言本身编写的,好多方法都是调用的操作系统本地的API,这就是著名的“本地方法调用”,也只有这样才能做事,这种类是非常底层的,和操作系统交流频繁的,那么如果这种类可以被继承的话,如果我们再把它的方法重写了,往操作系统内部写入一段具有恶意攻击性质的代码什么的,这不就成了核心病毒了么?不希望别人改,这个类就像一个工具一样,类的提供者给我们提供了, 就希望我们直接用就完了,不想让我们随便能改,其实说白了还是安全性,如果随便能改了,那么java编写的程序肯定就很不稳定,你可以保证自己不乱改, 但是将来一个项目好多人来做,管不了别人,再说有时候万一疏忽了呢?他也不是估计的, 所以这个安全性是很重要的,java和C++相比,优点之一就包括这一点。
    

    11.同一个字符串变量被修改,是否是对初始化变量指向空间内容的修改

    package com.joshua317;
    
    public class Main {
        public static void main(String[] args) {
            String str = "hello";
            str += "world";
            System.out.println(str);//helloworld
        }
    }
    /**
    首先不是对初始化变量str指向空间内容的直接修改。
    
    因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是 "Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
    
    通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为 String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。
    
    对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
    
    至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即 StringBuffer。
    **/
    

    12.String 和StringBuilder、StringBuffer 的区别

    我们知道Java平台提供了两种类型的字符串:String和StringBuffer / StringBuilder
    
    相同点:
    它们都可以储存和操作字符串,同时三者都使用final修饰,都属于终结类不能派生子类,操作的相关方法也类似例如获取字符串长度等;
    
    不同点:
    其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的,而StringBuffer和StringBuilder类表示的字符串对象可以直接进行修改,在修改的同时地址值不会发生改变。StringBuilder是JDK 1.5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer略高。在此重点说明一下,String、StringBuffer、StringBuilder三者类型不一样,无法使用equals()方法比较其字符串内容是否一样!
    

    13.实现字符串的反转,如:输入joshua317,输出713auhsoj

    package com.joshua317;
    
    public class Main {
        public static void main(String[] args){
            String str1 = "joshua317";
            String str2 = reverse(str1);
            System.out.println(str1);
            System.out.println(str2);
        }
        public static String reverse(String str) {
            StringBuilder stringBuilder = new StringBuilder("");
            char[] chArra = str.toCharArray();
            for(int i = chArra.length-1; i >= 0; i--){
                char ch=chArra[i];
                stringBuilder.append(ch);
            }
            return stringBuilder.toString();
        }
    }
    

    14.String类中replaceAll() 方法,使用给定的参数 replacement 替换字符串所有匹配给定的正则表达式的子字符串

    将字符串中的数字全部转为6

    package com.joshua317;
    
    public class Main {
        public static void main(String[] args){
            String str1 = "joshua317";
            System.out.println(str1);
            System.out.println(str1.replaceAll("\\d", "6"));
        }
    }
    

     

  • 相关阅读:
    系统综合实践_5
    系统综合实践_4
    系统综合实践_3
    系统综合实践_2
    系统综合实践_1
    软件工程17—第09组 Beta版本演示
    软件工程16—第09组 Beta冲刺(4/4)
    软工实践个人总结
    第06组 Beta版本演示
    第06组 Beta冲刺(5/5)
  • 原文地址:https://www.cnblogs.com/joshua317/p/15625527.html
Copyright © 2020-2023  润新知