new String()

new String()

String str1=new String("something");             //1

String str2="something";           //2

疑问:在1中new String("something")是调用了 String(String  xxx)这个构造方法,意思是"something”已经是String类的实例对象了?那么2中的String str2="something";  其实是表示让str2指向了已存在的"something"的地址?如果上面的观点是正确的,“something”这个实例化过程又是调用了哪些方法?


正在回答

登陆购买课程后可参与讨论,去登陆

5回答

1、

同学你好,能理解同学的问题,老师翻阅了很多资料,也咨询的很多的老师,但说法不一。但这个问题无法被验证,也没有明确的官方说明。

说法一:

如果是第一次new,会创建两个对象。一个放在常量池中,一个在堆中。第二次new相同的字符的时候就不会在常量池中创建一个了。直接在堆中创建一个。和同学的观点一致

说法二:

同学说的参数“***”在编译的时候,就会进入一个运行时常量池中,而不是到字符串常量池中。new的时候并不会先在字符串常量池中创建。而是直接在堆中创建一个。

但老师无法进行验证。不过同学不用纠结。因为,如果是在十几年前,可能会非常有用,因为设备跟不上,我们要研究底层,但现在不会了,随着机器设备的优化,如何写好程序才是最应该思考的。不用过多的研究底层。


如果我的回答解决了你的疑惑,请采纳!祝学习愉快!


  • 大大鱼pzy 提问者 #1
    谢谢老师的解答
    2019-07-13 21:11:04
好帮手慕小班 2019-07-13 12:00:50

        同学你好,这里老师根据同学的说法来验证一下,例如:

public class Test01 {
	public static void main(String[] args){ 
		String a = new String("abc");
		String b=a.intern();
		System.out.println(b==a);
		String c ="abc";
		String d=c.intern();
		System.out.println(d==c);
	}
}

运行结果如下:

http://img1.sycdn.imooc.com//climg/5d29558e0001fcf301930114.jpg

这里 intern方法返回字符串常量池中的唯一对象。所以这里老师来通过这个方法验证常量池中是否有这个字符串,根据运行结果可知,String类型的对象a在常量池中并没有这个字符串,所以运行结果为false!

 intern方法的返回值是一个字符串,内容与此字符串相同,但一定取自具有唯一字符串的池。所以这里同学不用纠结,记住就可以了哦,它的具体原理老师也无法深究,但是提供了这个intern方法,只能为同学验证一下!

        如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 提问者 大大鱼pzy #1
    老师,我没说a和b指向同一地址,我说的是String a = new String("abc")创建了两个实例对象,一个在常量池,一个在堆里;c指向了String a = new String("abc")在常量池创建的实例对象
    2019-07-13 15:37:53
好帮手慕小班 2019-07-12 19:50:16

        同学你好,String str1=new String("something");调用的是String的构造方法哦!例如:

http://img1.sycdn.imooc.com//climg/5d2873cd000195e205110181.jpg

        如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 提问者 大大鱼pzy #1
    老师您好,这个构造方法参数是String类型的,基本类型和String都该在常量池里。String str1=new String("something")的第一步不是该在常量池里查找有无“something”,没有的话再构建吗?
    2019-07-12 21:37:27
提问者 大大鱼pzy 2019-07-12 11:29:41

String str1=new String("something");             //语句1

(语句1的步骤:先在常量池里创建“something”,在栈里创建str1,把常量池里的“something”作为参数,在堆里创建new String("something"),将str1指向堆里的对象。)

http://img1.sycdn.imooc.com//climg/5d27fe8000010c6a16001192.jpg

String str2="something";               //语句2

(语句2的步骤:由于常量池里已经存在“something”,所以直接将栈里新创建的str2指向在语句1里创建的“something”)

http://img1.sycdn.imooc.com//climg/5d27fe9e0001db2515991151.jpg

  • 同学你好,这里同学有一个误区哦,1、String str1=new String("something"); 是通过new关键字在堆中创建一个对象,这里new Cat()和new String()是一样的哦,所以常量池与这个对象没有关系,不会在常量池中去创建这个对象哦!2、String str2="something"; 没有new关键字,是不会去堆中找对象的,而是去常量池中找有没有这个对象哦,如果没有就创建一个。 综上所述,不论哪种方式都创建了对象,只是创建的位置不同,数据存放的地址也就不同。 如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~
    2019-07-12 17:21:40
  • 提问者 大大鱼pzy 回复 好帮手慕小班 #2
    老师您好,String str1=new String("something");调用的是什么方法?
    2019-07-12 18:04:21
好帮手慕小班 2019-07-12 10:50:24

        同学你好,这里关于str2指向了已存在的str1的"something"的地址这里理解有错哦!

1、(1)、String str2="something"; 这也是创建了一个对象,可以理解为简化了创建对象的过程。

(2)、因为String类型比较特殊,它使用的时候可以像基本数据类型一样使用,但是它实际上是类,所以它是会创建对象的。

(3)、特殊的地方在于,String str2="something";这条语句中,字符串的内容是存储在常量池中的,

如果常量池中存在“something”的字符串,那么不创建新的对象,直接使用常量池中已存在的对象,然后将引用str2指向该对象。

如果常量池中不存在“something”的字符串,则先在常量池中创建一个新的字符串对象“something”,然后将引用str2指向阿三中创建的新对象。 

也就是字符串的引用str2指向常量池中的内容。

    2、但是使用new String()这种方式去创建,就会存储在堆中。String str1=new String("something");就是在堆中创建一个内容为"something"的对象,str1指向堆中的这个对象!

综上所述,不论哪种方式都创建了对象,只是数据存放的位置不同。

        如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

    

  • 提问者 大大鱼pzy #1
    感谢老师的讲解,我没表达清楚,我重新表述一下。
    2019-07-12 11:18:38
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师