前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java中String类常见问题汇总

Java中String类常见问题汇总

作者头像
joshua317
发布2021-12-01 15:08:11
3670
发布2021-12-01 15:08:11
举报
文章被收录于专栏:技术博文技术博文

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

代码语言:javascript
复制
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字符串内存结构剖析

代码语言:javascript
复制
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

代码语言:javascript
复制
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.字符串常量比较,字符串对象比较

代码语言:javascript
复制
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中字符串数据的比较

代码语言:javascript
复制
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类型

代码语言:javascript
复制
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类型是基本数据类型吗?

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

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

9.String类是否可以被继承

代码语言:javascript
复制
不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。

10.String类为什么是final的

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

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

代码语言:javascript
复制
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 的区别

代码语言:javascript
复制
我们知道Java平台提供了两种类型的字符串:String和StringBuffer / StringBuilder

相同点:
它们都可以储存和操作字符串,同时三者都使用final修饰,都属于终结类不能派生子类,操作的相关方法也类似例如获取字符串长度等;

不同点:
其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的,而StringBuffer和StringBuilder类表示的字符串对象可以直接进行修改,在修改的同时地址值不会发生改变。StringBuilder是JDK 1.5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer略高。在此重点说明一下,String、StringBuffer、StringBuilder三者类型不一样,无法使用equals()方法比较其字符串内容是否一样!

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

代码语言:javascript
复制
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

代码语言:javascript
复制
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"));
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-11-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.字符串常量和字符串对象比较
  • 2.Java字符串内存结构剖析
  • 3.Java中所有引用类型的默认值都是null
  • 4.字符串常量比较,字符串对象比较
  • 5.Java中字符串数据的比较
  • 6.字符串如何转换为int类型
  • 7.String类型是基本数据类型吗?
  • 8.Java语言中,String类中的indexOf()方法返回值的类型是int
  • 9.String类是否可以被继承
  • 10.String类为什么是final的
  • 11.同一个字符串变量被修改,是否是对初始化变量指向空间内容的修改
  • 12.String 和StringBuilder、StringBuffer 的区别
  • 13.实现字符串的反转,如:输入joshua317,输出713auhsoj
  • 14.String类中replaceAll() 方法,使用给定的参数 replacement 替换字符串所有匹配给定的正则表达式的子字符串
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档