1 String与StringBuffer的区别?解析:String是不可变的对象,StringBuffer是可以再编辑的
字符串是常量,StringBuffer是变量;-----
详细解析:String, StringBuffer,StringBuilder的区别
1.可变与不可变
String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。
private final char value[];
String 为不可变对象,一旦被创建,就不能修改它的值,对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.
StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的
char[] value;
StringBuffer:是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象 , 它只能通过构造函数来建立, 如: StringBuffer sb = new StringBuffer();
不能通过赋值符号对他进行赋值. ,
如 sb = “welcome to here!”;//error
对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer中赋值的时候可以通过它的append方法 sb.append(“hello”);
2.是否多线程安全
String中的对象是不可变的,也就可以理解为常量, 显然线程安全 。
AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是 线程安全的 。看如下源码:
1 public synchronized StringBuffer reverse() {
super .reverse();
return this ;
4 }
StringBuilder并没有对方法进行加同步锁,所以是 非线程安全的 。
3.StringBuilder与StringBuffer共同点
1 StringBuilder与StringBuffer有公共父类AbstractStringBuilder( 抽象类 )。
2 抽象类与接口的其中一个区别是:抽象类中可以定义一些子类的公共方法,子类只需要增加新的功能,不需要重复写已经存在的方法;
而接口中只是对方法的申明和常量的定义。
StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(…)。只是StringBuffer会在方法上加synchronized关键字,进行同步。
最后,如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。
效率比较String < StringBuffer < StringBuilder,
但是在String S1 =“This is only a”+“simple”+“test”时,String效率最高。,常量优化!!!
2 public class Test
{
public static void changeStr(String str)
{
str = “welcome”;
}
public static void main(String[] args)
{
String str = “1234”;
changeStr(str);
System.out.println(str);
}
}
解析:考察Java方法参数传递特性
Java方法调用中,只存在值传递调用。**
此处,实参str是引用变量,由于java方法调用是值传递,所以形参str得到的是实参str的一个拷贝。此时形参str和实参str均指向字符串"1234"。
然后,在changeStr方法中,形参str指向了一个新的字符串"welcom",而后方法结束,形参str被销毁。而实参str仍然指向字符串"1234";第二:1234和welcome都被编译到了常量池中,在调用changeStr(str)的过程中,首先将,str的引用传递给了changeStr(保存在在栈里),然后在这里面更改str的值,相当于在栈中将传递给changeStr的引用的值变化了,但是当changeStr结束之后,
栈就清空了,因此原来的引用并没有发生变化。
3 三种string的区别?java中的字符串存储在字符串常量区,不会改变,发生改变是会新创建一个对象
B,StringBuffer是线程安全的StringBuilder
C,StringBuilder跟StringBuffer功能相同,区别是StringBuilder不是线程安全的
D,StringBuilder和StringBuffer底层都是以字符数组存放的,可以修改内容
4 三种string的区别?效率:StringString(大姐,出生于JDK1.0时代) 不可变字符序列 <StringBuffer(二姐,出生于JDK1.0时代) 线程安全的可变字符序列 <StringBuilder(小妹,出生于JDK1.5时代) 非线程安全的可变字符序列 。Java中的String是一个类,而并非基本数据类型。string是值传入,不是引用传入。 StringBuffer和StringBuilder可以算是双胞胎了,这两者的方法没有很大区别。但在线程安全性方面,StringBuffer允许多线程进行字符操作。 这是因为在源代码中StringBuffer的很多方法都被关键字 synchronized 修饰了,而StringBuilder没有。 StringBuilder的效率比StringBuffer稍高,如果不考虑线程安全,StringBuilder应该是首选。另外,JVM运行程序主要的时间耗费是在创建对象和回收对象上。
5 包装类是针对 基本数据类型 的。—string不是的!!!
6 **String对String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,而不是StringBuffer;StringBuffer每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。 **
7 **StringBuffer类的对象调用toString()方法将转换为String类型,String类没有append方法
可以直接将字符串“test”复制给声明的Stirng类和StringBuffer类的变量 引用类型只有String可以直接复制,其他的都要new出来
两个类的实例的值都能够被改变 StringBuffer类可以直接改变它的内容,不用重新分配地址; String 对象/ 实例 是不可以被改变的。
StringBuffer:
是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象
它只能通过构造函数来建立,
StringBuffer sb = new StringBuffer();
!!!:不能通过赋值符号对他进行付值.
sb = “welcome to here!”;//error
对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer
中赋值的时候可以通过它的append方法.
sb.append(“hello”);
字符串连接操作中StringBuffer的效率要比String高:
String str = new String("welcome to ");
str += “here”;
的处理步骤实际上是通过建立一个StringBuffer,然后调用append(),最后
再将StringBuffer toSting()(toString方法:StringBuffer类型转化成String类型);**
8 string:swap交换string,但是结束之后,栈会被清空,所以原来的引用没有变化,注意了
引用作为形参传递会改变实参的值,但是string是特殊的引用是 final的,并不会改变实参的值,他是一个列外!!!所有试图对string的修改都会生成一个新的string对象
10 string:成员变量的引用在堆区,“hello”是未经new的常量在常量区,局部变量的引用在栈,在方法里面未经new的:“hello”在常量区,—堆区只是存放类对象,线程共享!!!局部变量在站里面!!!
11 string属于类,底层是字符数组实现的,不是基本的数据类型
12 String 是不可变类型,是存储在常量字符区的
13 String x=“fmn”; “fmn”是在常量池里的不可变对象。
x.toUpperCase();在堆中new一个"FMN"对象,但无任何引用指向它。
String y=x.replace(‘f’,‘F’); 在堆中 new一个"Fmn"对象,y指向它。
y=y+“wxy”; 在堆中 重新new一个"Fmnwxy"对象, 修改y指向,现在y指向它。
14 String类是final类型的,不能继承和修改这个类。str=“tesk ok”,其实是隐含的让Java生成一个新的String对象,那么就与原来的“Hello”没有任何关系,当函数结束,str作用结束,所以输出的还是“Hello”。 char ch[] 是传递引用,修改了原内容
15 String str=new String(“hello”);
这句话new了一个新的String对象,所以地址与"hello"字符串常量的地址不同,答案为false,如果判断字符串是否相等应给用str.equals(“hello”)方法
16 问:String s1=“abc”; s2=“abc”; s3= new String(“abc”);为啥s1和s2的地址值一样而s1和s3的就不一样呢?也就是,为什么 s1s2但s1!=s3呢?
答:先是在内存里创建了一个abc字符串,然后s1指向abc,s2要指向abc,内存中已经有abc,所以s1和s2地址相同,s3指向的是新字符串abc的地址,所以s1与s3不同,s1s2但s1!=s3,因为s1,s2,s3是引用,比较的是地址而不是内容,所以有这个结果,比较值是否相同应该用。equal函数而不能直接用==
17 **Java中String类型变量是immutable(不可变的),尽管 change()方法中的str与sv.str都是新的对象实例成员变量值"6"的引用, 由于String类型的 不可变 性,change()方法中的str="10"语句实际上是将传入的str副本引用指向了一个值为“10”的新的内存地址,但 原数据引用 sv.str的引用值(也就是“6”的内存地址) 并没有发生改变,因此sv.str指向的值仍旧为6.
昨天刚看的这个。java中的方法传递都是值传递,java中的数据类型有基本类型和引用类型,他们都是值传递方式。基本类型传递的是它的值,因此方法中的改变参数的值,不会影响方法外。引用类型传递的是一个地址,因为引用类型在生成对象实例时,里面的值是一个地址,指向了对象实例。在传值的时候实际上传的是一个地址,他们指向了同一块地址,所以在方法内的改变会影响方法外的参数。 这里比较乱人心的是包装类型,因为包装类型也是引用类型,这里应该就是和包装类型的实现有关了,在包装类型中,比如Integer a=1,有一个自动装箱的操作。其实a=1,如果现在令a=2,不会令2覆盖1(即1本身是不会变的),真正改变的是a被赋给了一个新地址,这个地址指向了2。因此方法内的改变包装类型的值就相当于改变了形参里面的地址,相当于重新new了一遍。而方法外面的实参仍旧指向含1的那个地址,一次方法内的改变不会影响方法外的实参。**
18 ==是比较两个内存地址是否相同,相同为true,不相同为false;
在字符串缓冲池中,若已有字符串,则直接赋值时不再新创建一个字符串,如果是new 关键字,则新创建一个不同的字符串。
String类的equals被重新复写,只要字符串相等,则返回true
19 String类不可变,指的是String对象内容不可变,因为’String对象存在常量池中,而String的引用是可以可变,可以为String引用赋予新的对象字符串。
20 在源码中 toLowerCase 是重新 new String()所以为 == 是比较对象是否是同一个对象,所以为 false 。
21 string:基本数据类型是值传递,数组和接口是引用传递,由于String对象本身的特殊性,导致他值传递的特性!!!变量代表的是值的副本!!!
22 字符串的比较一定要用equals(),==是判断地址,stringtoLowercase是new了一个新的对象
23 包装类里面没有String
24 stringbuilder:构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。–特点:是一个容器。
3:是可变长度的。
4:缓冲区中可以存储任意类型的数据。
5:最终需要变成字符串。–1,添加。
StringBuffer append(data):在缓冲区中追加数据。追加到尾部。
StringBuffer insert(index,data):在指定位置插入数据。
25 ** String
在String 中认为都是对象,String str = “…”;
所以str 是对象,""也是对象
String 是一个常量,其本质就是private final 修饰的字符数组
String的构造方法:
new String(byte [] bytes, int offset,int length);
offset: 数据解锁起始位置
length:需要解锁的位数
substring(int start ,int end ); 包含头,不包含尾。 截取一段字符
substring(int start); 从某一位到尾
startsWith(String str) 判断以什么开头
endsWith(String str) 判断以什么结尾
contains(String str) 判断是否包含
indexOf(String str)
charAt(int index)
equals() 注意:要区分大小写
equalsIgnoreCase 不区分大小写
getBytes()
toCharArray()**
26 ****# Java中String、StringBuffer、StringBuilder的区别
笔记仓库:https://github.com/nnngu/LearningNotes
1.从是否可变的角度
String类中使用字符数组保存字符串,因为有“final”修饰符,所以String对象是不可变的。
/** The value is used for character storage. */
private final char value[];
StringBuffer和StringBuilder都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,但没有“final”修饰符,所以两种对象都是可变的。
/**
* The value is used for character storage.
*/
char[] value;
2.是否多线程安全
String中的对象是不可变的,也就可以理解为常量,所以是线程安全的。
AbstractStringBuilder是StringBuffer和StringBuilder的公共父类,定义了一些字符串的基本操作,如append、insert、indexOf等公共方法。
StringBuffer对方法加了同步锁(synchronized) ,所以是线程安全的。看如下源码:
1 public synchronized StringBuffer append(String str) {
2 toStringCache = null;
3 super.append(str);
4 return this;
5 }
StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。如下源码:
1 public StringBuilder append(String str) {
2 super.append(str);
3 return this;
4 }
3.StringBuffer和StringBuilder的共同点
StringBuffer和StringBuilder有公共父类AbstractStringBuilder(抽象类)。
StringBuffer、StringBuilder的方法都会调用AbstractStringBuilder中的公共方法,如上面的两段源码中都调用了super.append(str); 只是StringBuffer会在方法上加synchronized关键字,进行同步。
最后,如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。