Java中String类(里面4个练习是重点!!!)

本文详细解析了JavaString类的工作原理,包括字符串常量池、对象创建方式、不可变性特征、连接操作以及方法调用时的内存影响,通过实例演示展示了这些概念的实际应用。
摘要由CSDN通过智能技术生成

String类

String类的理解

  1. String 对象用于保存字符串,也就是一组支付串序列

在这里插入图片描述
注:如果一个类可以串行化,说明该对象可以在网络传输。

  1. 字符串常量对象是用双引号括起来的字符串序列,例如"你好"、“12.97”、"boy"等
  1. 字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
  1. String类有很多构造器(其它看Java图标)。构造器的重载
    eg:
    String s1 = new String();
    String s2 = new String(String original);
    String s3 = new String(char[] a);
    String s4 = new String(char[] a,int startindex,int count)
  1. String 是final类,不能被其它的类继承
  1. String 类中有属性 private final char value[]; 用于存放字符串内容,一定要注意:value是一个final类型的,不可修改。(不可修改的是里面的地址:即value不能指向新的地址,但是单个字符内容是可以变化的)

String类的创建对象

方式一:直接赋值 String s = “hello”;

先从常量池查看是否有"hello"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址

方式二:调用构造器 String s2 = new String(“hello”);

先在堆中创建空间,里面维护了value属性,指向常量池的helli空间。如果常量池没有"hello",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。

在这里插入图片描述

练习1

String a = "joker";//a 指向常量池的 "joker"
String b = new String("joker");//b 指向堆中的对象
System.out.println(a.equals(b));//输出true
System.out.println(a==b);//输出false
System.out.println(a==b.intern);//输出true
System.out.println(b==b.intern);//输出false
当调用intern方法时,如果池已经包含一个等于次String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。
b.intern()方法最终返回的是常量池的地址

练习2 !!!

Person p1 = new Person();
p1.name = "joker";
Person p2 = new Person();
p2.name = "joker";
System.out.println(p1.name.equals(p2.name));//输出true
System.out.println(p1.name == p2.name);//输出true,此处p1和p2都在堆中创建了一个对象,对象地址不一样,但是对象中的name都指向常量池中的"joker"的地址,总的来说都指向同一个池中的同一个地址,因此输出true。
System.out.println(p1.name == "joker");//输出 true,因为"joker"是字符串常量是放在常量池中的,会返回一个常量池中的地址
String s1 = new String("bcde");
String s2 = new String("bcde");
System.out.println(s1 == s2);//输出false

字符串的特性

  1. String 是一个final类,代表不可变的字符序列
  1. 字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的
    eg:练习1
String s1 = "joker";
s1 = "hello";
//创建了两个对象,首先s1在常量池中没有找到"joker",创建了"joker",之后s1被赋值"hello"后只会再次重新创建一个"hello",然后把s1指向"hello"的地址。

eg:练习2

String a = "hello" + "abc";
//问:创建了几个对象
//系统会优化这句代码,优化后等价 String a = "helloabc",所以只有一个对象

eg:练习3

String a = "hello";
String b = "abc";
String c = a + b;
//问:创建了几个对象(关键就是要分析String c = a + b; 到底如何执行的)
1.在底层先创建一个StringBuilder sb = StringBuilder()
2.执行 sb.append("hello");
3.执行 sb.append("abc");
4.调用 sb.toString(),把两个字符串连接输出返回,String c = sb.toString;
5.最后其实是 c 指向堆中的对象(String类型) value[]-> 常量池中的"helloabc";
6.a指向的是常量池中的"hello" b指向的是常量池中的"abc" c先指向堆中的对象,对象里面的value指向常量池中的"helloabc"。c 并不是直接指向常量池中的"helloabc",而是通过底层new,toString输出的,最终c是指向堆的。
解:3个对象

重要规则

String c1 = “ab” + “cd”;(常量相加,看的是常量池)
String c1 = a + b;(变量相加,是在堆中)

String c = a + b;
String d = "helloabc";
System.out.println(c == d);//真还是假? 是false
String e = "hello" + "abc";//直接看池, e指向常量池
System.out.println(d == e);//真还是假? 是true

eg:练习4

class Test1 {
    String str = new String("joker");
    final char[] ch = {'j', 'a', 'v', 'a'};

    public void change(String str, char ch[]) {
        str = "java";//会在常量池中新开一个,这时str是调用change方法时是栈里面开辟的新方法空间里面的str,不是堆里面的str,这时堆里面的str是指向joker,而方法栈里面str是指向java,两个不一样
        ch[0] = 'h';//数组存储放在堆中
    }

    public static void main(String[] args) {
        Test1 ex = new Test1();
        ex.change(ex.str, ex.ch);
        System.out.print(ex.str + " and ");//这时是调用主栈里面的str因此是joker
        System.out.println(ex.ch);
    }
}
输出的是:jokerandjava

分析
调用方法时ex.change(ex.str, ex.ch)传入的str会在方法栈里面,然后在常量池中新开一个"java"指向,而不是ex对象里面的str,对象里面的str还是指向"joker",因此调用主栈里面的ex.str是原来"joker",并不是"java"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值