傻傻分不清楚?: 一文看懂Java中String的New操作和直接赋值字符串的区别 |
您所在的位置:网站首页 › java中字符串是什么意思 › 傻傻分不清楚?: 一文看懂Java中String的New操作和直接赋值字符串的区别 |
简介
String str=new String("a")和String str = "a"有什么区别?
String s = new String("xyz");创建了几个StringObject?
这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";
`String s1 = "a";String s2 = s1 + "b";` s2 == “ab” 吗?
是不是被上面的题目逼疯了,哈哈,微观Java对考查Java变量初始化原理十分普遍,不过不用着急,本篇文章赋予你杀虫利器!!! 方法/步骤 1,区别字符串New和直接赋值百度的面试官问: 这两个值,A,B 是否相等,如果都往HashSet里面放,能放下吗? String A="ABC"; String B=new String("ABC");答:(a)A==B 的判断为false; (b)A.equals(B)为true ;因为值相等,所以都往HashSet里面放不下,只能放一个问题:==与equals()的区别: ==:比较引用类型比较的是地址值是否相同equals:比较引用类型默认也是比较地址值是否相同,注意:String类重写了equals()方法,比较的是内容是否相同。 String A = "ABC";内存会去查找永久代(常量池) 如果没有的话,在永久代中中开辟一块儿内存空间, 把地址付给栈指针,如果已经有了"ABC"的内存,直接把地址赋给栈指针;因此 String str1="aa"; Srting str2="aa"; String Str3="aa"; .... 这样下去,str1== Str2 == str3;会一直相等下去,(a) == 的判断,(b)equals()的判断;都相等,因为他们的地址都相等,因此只在常量池中有一份内存空间,地址全部相同; 而String str = newString("a");是根据"a"这个String对象再次构造一个String对象;在堆中从新new一块儿内存,把指针赋给栈,将新构造出来的String对象的引用赋给str。 因此 只要是new String(),则,栈中的地址都是指向最新的new出来的堆中的地址, (a)“”==“” 是判断地址的,当然不相同; (b)至于equals,String类型重写了 equals()方法,判断值是否相等,明显相等,因此 equals 是相等的; Demo1: public class StringDemo1 { public static void main(String[] args) { String s1 = new String("hello"); String s2 = "hello"; System.out.println(s1 == s2);// false System.out.println(s1.equals(s2));// true } } ** 运行结果:** > false > trueDemo1 代码详解 首先,通过main()方法进栈。 然后再栈中定义一个对象s1,去堆中开辟一个内存空间,将内存空间的引用赋值给s1,“hello”是常量,然后去字符串常量池 查看是否有hello字符串对象,没有的话分配一个空间存放hello,并且将其空间地址存入堆中new出来的空间中。 在栈中定义一个对象s2,然后去字符串常量池中查看是否有”hello”字符串对象,有,直接把”hello”的地址赋值给s2. 即s1中存的是堆中分配的空间,堆中分配的空间中存的是字符串常量池中分配空间存放”hello”的空间的地址值。而s2中之间存的是字符串常量池中分配空间存放”hello”的空间的地址值。 由于s1与s2中存放的地址不同,所以输出false。因为,类String重写了equals()方法,它比较的是引用类型的的值是否相等,所以输出true。即结果为false、true。Demo2: public class StringDemo2 { public static void main(String[] args) { String s1 = "hello"; String s2 = "world"; String s3 = "helloworld"; System.out.println(s3 == s1 + s2); //false System.out.println(s3.equals((s1 + s2)));//true System.out.println(s3 == "hello" + "world");//true System.out.println(s3.equals("hello" + "world"));//true } }运行结果: 注:当字符串常量池中有对象hello时括号内成立! 字符串如果是变量相加,先开空间,在拼接。 字符串如果是常量相加,是先加,然后在常量池找,如果有就直接返回,否则,就创建。那有读者会问了,那么不是常量相加呢?类似这种: String s1 = "a"; String s2 = s1 + "b";s2 == "ab"吗?下面就来解答!!! 2,引用赋值与直接赋值的区别 先看Demo String s1 = "Java"; String s2 = "Hello"; String s5 = s1; s5 = "change"; String s3 = new String("Hello"); String s4 = new String("Java"); 字符串常量在虚拟机内存空间的情况如图所示: 重点看 : String s1 = "Java"; String s5 = s1; s5 = "change"; 当执行String s5 = s1时,s5会直接去使用s1在常量池中的内容,而后面当执行s5 = "change"的时候,也就是说需要对Java这个字符串进行修改,可是这个字符串除了s5自己使用外,s1也在使用,所以就不能直接修改他,而是要在空间中重新开辟一个空间,用于存储change。这就是字符串不可以直接修改的底层实现! 字符串设置为不可变的原因: ①出于安全考虑,程序在运行之前虚拟机会把字符常量,静态变量等预加载到常量池(方法区) 中存储起来,在程序运行的时候直接调用,但是常量池里面的信息不会有重复的,每一个都是 唯一的(这样是为了减少内存的开销,提升性能),这些信息是线程共享的,同一个字符串可 能会被多个线程使用,如果字符串可变,当某个线程修对他做了修改,其他正在使用该字符串 的线程可能就会出现严重的错误,从而变得不安全。 ②保证hash值不会经常变动,具有唯一性,使得类似HashMap的容器能实现key—value的功能 String 字符串的拼接 static String s1 = "Hello"; static String s2 = "Java"; static String s3 = "Hello"+"Java"; static String s4 = "HelloJava"; static String s5 = s1 + "Java"; static String s6 = "Hello" + s2; static String s7 = s1 + s2; static String s8 = (s1 + s2).intern();内存分配如图 ** 1.常量和常量的拼接,结果也在常量池中,且不存在两个相同的常量。 2.只要参与拼接的项里面有变量,结果就在堆中。 3.使用(String).inter()方法处理拼接后,被处理的字符串会进入常量池中。** 回归之前的题目 String str=new String("a")和String str = "a"有什么区别? 解答: 一个是在常量池里面,new的对象是在heap里面,两个当然是不==的String s = new String("xyz");创建了几个StringObject?如果之前在常量池里面有了"xyz",就创建了一个,如果没有就创建两个(一个放在常量池里面,一个在heap里面) 这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d"; 解答: 题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,上面的代码应该只创建了一个String对象。 `String s1 = "a"; String s2 = s1 + "b";` s2 == “ab” 吗?不相等!!! s2指向heap里面,s1是指向的是常量池!!! 参考资料 & 致谢java String 两种不同的赋值 比较java String 内容的比较 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |