初始Java——认识String

String a = "abf";

 

String a = new String("abvc");

 

char[] array = {'a','b','c','d','e'};

String a = new String(array);

 

String str = new String(array,2,2);//offset,count

 

 

sout(str);

 

sout(str == str2);//错误,存的是地址,不是值

 

 

image.png

image.png

 

课堂代码举例str == str2
String str1 = "hello";

String str2 = new String("hello");//false,new了新的内存块

String str3  = "he"+new String("llo");//false,在+拼接过程中,也会创建一块新的内存块,str3直接指向这块新的内存块,并不分别存两块的地址,拿回栈拼接

String str4 = "he" + "llo";//常量在编译前就已经拼接好了(19:39可以反编译看一下),在常量池先进行拼接,再传值,也就是说常量池里已经有hello的话,拼完直接就是那个现成的hello,所以地址相同,==true

String str5 = "he";
String str6 = str5+"llo";//false,因为在str6的位置认为str5是个变量,所以重新创建了,而不能把str5当作一个常量

String str7 = new String("he");
String str8 = new String("llo");
String str9 = str7 + str8;//false,  7和8分别有自己的,但是str9朝阳重新创建了一个内存区域,上边分别7和8的地址(19:43)

遇到str == str2的问题:

new出来的一定重新开辟内存空间,意味着一个新的地址

例子2:

byte a = 10;

byte b = 20;

byte c = a+b;//报错,运算自动转换成int运算,byte的C不能接收int型

 

final byte a= 10;

final byte b= 20;

byte c = a+b;//可以通过,因为常量加完再给回来

 

例子3:

String str1 = "hello";

String str2 = str1;//可以看出来,2并不是指向1,而是指向1的对象hello

str1 = "world";

sout(str2);

 

//执行结果

hello

 

public class testString {
    public static void change(String str,char[] array){
            //传值过来,在栈中又创建了一个Str,存着真正的str的地址
        str = "haha";//给覆盖了新地址,但是没传回去
        //只改变了形式参数,并不会影响到实参
        array[0]= 'g';//数组操作是直接在数组上覆盖【0】位置直接给他盖了
    }

    public static void main(String[] args) {
        String str = "hello";
        char[] array = {'a','b','c'};
        change(str,array);
        System.out.println(str);
        System.out.println(Arrays.toString(array));
    }

}

//执行结果
hello
gbc

 

 

常量池

常量池

同样的字符串,只能存一个

如果有,那么返回现在的地址给引用

如果没有,则存放进去,并且返回地址给引用

 

所有的池的作用:都是用于节省资源的(共享)

用equals比较内容

主动与被动关系

String str = null;

sout(str.equals("abc"));//报错空指针

sout("abc".equlas(str));//正常运行

 

intern()方法(选择题)

入池方法,给对象丢进常量池

String str1 = "hello";

String str2 = new String("hello").intern();//调用了intern会直接把常量池的hello给str2,如果是原来没有的也会在常量池创建一个hello

sout(str1 == str2);//true

 

 

str1 = str1+"";

1.每次拼接会产生一个新的对象,不会在原有的基础上进行修改

2.value 的指向不能发生改变

 

 

 

想越过权限,直接修改常量池的值:

反射

PSVM
String str = "abc";

//反射
Class cl = String.class;
Field valueField = cl.getDeclaredField("value");//必须与属性字段一样,不能改变
valueField.setAccessible(true);
char[] value = (char[]) calueField.get(str);
value[0] = 'h';
sout(str);

 

 

 

StringBuffer 和 StringBuilder20:50

image.pngimage.png

StringBuiler sb = new StringBuilder("hello");

StringBuilder sb2 = new StringBuilder(sb);//向上转型

 

String与StringBuilder与StringBuffer的区别

String str = "hello";

String str2 = "abc";

//String的拼接被优化为StringBuilder

String str3 = str + str2;

 

 

StringBuilder sb = new StringBuilder();

sb.append("ab");

sb.append("cd");

 

  1. String的拼接会产生新的对象,但是StringBuilder 和 StringBufer的append方法来进行拼接,返回的是当前对象
  2. String的拼接会被优化为StringBuilder
  3. StringBuffer多用于多线程StringBuilder多用于单线程,String多用于单线程(Buffer会有一个synchronized是用来保证线程安全的,相当于锁)
  4. 两个B的方法相较于String会更多

 

 

String与StringBuilder与StringBuffer类型转化

String转别的不能直接转

String str1 = "abc";

StringBuilder a = new StringBuilder(str1);

或者

StringBuilder a = new StringBuilder();

sb.append(str1);

 

两个B转String用ToString

 

 

字符、字节与字符串21:20

str.length()//length函数

array.length//length属性

ASCⅡ表

@Deprete——>当前方法已经过时了

posted @ 2021-08-09 17:01    阅读(90)  评论(0)    收藏  举报