A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© jiapengtao 中级黑马   /  2016-4-26 15:10  /  3573 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

10黑马币
1,String s1 = new String("abc");    //s1记录的是堆内存的地址值 ,但它在常量池中也创建了对象,为什么只记录一个堆内存地址?
2,String s1 = "ab"; String s3 = s1 + "c";    //答案已知,但是在内存中如何进行的一知半解,求详细解答,有条件附图说明
3,子类A重写了父类B的b方法,如果在子类A中调用这个方法有几种方式?分别是什么?
4,java中"\"是转义字符,常用的\d \t \n也都知道它们的意思,但深究为什么转义以及什么情况下转义却一头雾水,急盼解疑


回答不论是粘的还是自己写的,能图文或码文讲解,让我理清知识就好

最佳答案

查看完整内容

1.s1记录的是堆内存的地址值,而在堆内存的内存空间里面,还有在常量池里面的"abc"常量的副本。 2.s1的"ab" 是常量池里面的,而String s3=s1+"c"; 这句代码的底层实现 是这样的: String s3 = (new StringBuilder()).append(s1).append("c").toString(); 它的返回值是个String类型,是new出来的,所以就在堆内存中,这么一来结果就显而易见了,s1是常量池,方法区里面的,而s3是堆内存的,两个不同地方的玩意,那就肯定是不一 ...

9 个回复

倒序浏览
1.s1记录的是堆内存的地址值,而在堆内存的内存空间里面,还有在常量池里面的"abc"常量的副本。
2.s1的"ab" 是常量池里面的,而String s3=s1+"c";   这句代码的底层实现 是这样的:
String s3 = (new StringBuilder()).append(s1).append("c").toString();   它的返回值是个String类型,是new出来的,所以就在堆内存中,这么一来结果就显而易见了,s1是常量池,方法区里面的,而s3是堆内存的,两个不同地方的玩意,那就肯定是不一样的。也就是s1!=s3
3.假设你说的是,A类调用B类的b方法,那么就只有super.b()   如果你是要调用A类中自己的b方法,如果在类里面,就两种方式,直接类里面b()或者this.b()这样调用。如果在类外,就是创建对象调用的方式的话,那就是new A().b();这样调用。如果想在对象外面调用父类的话,那就new B().b();
4.转义字符的用处,就一般是什么\d \t \n \r等等的,暂时来说,你只需要知道,转义字符用在输出这些比如双引号(\"),反斜杠(\\)等的时候用的,还有前面那些具有固定功能的\d \t。还有正则表达式里面的,例如匹配一个字符是不是数字,那就用\d等等。到正则表达式学到了,就都懂啦。

纯手打,虽然没有代码,但是我觉得我说的挺清楚了。不明白可以给我留言,我会每天看的。好啦,快把那10个黑马币交出来吧,我是一边流口水一边敲的~
回复 使用道具 举报
1.String s="abc"
String类在内存中管理着一个文字池(pool of literal strings,也称为字符串常量池,是常量池的一部分),池中所有相同的字符串常量被合并,只占用一个空间。
这里创建“abc”时,先看文字池中有没有abc,没有就创建了一个abc字符串对象。
2.String s1 = new String("abc")
这里先在文字池中创建一个abc对象,同上。然后new String()时,将abc对象复制一份到堆heap中,new一次就复制一个,s1就指向堆中的abc。(参考下面的API文档)
可以用代码验证:
String s1=new String("abc");
String s2=new String("abc");
s1+="d";
System.out.println(s1==s2);//false,说明s1和s2指向的是堆内各自的abc(从文字池中abc复制过来的)
System.out.println(s1);//abcd,说明s1指向abc,不然无法和字符d相连接。
内存图:
String s1 = new String(abc) 问题终结 - libra - Libra Zeng

参考资料:
JAVA API文档中的解释
public String(String original)
Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.
初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。由于 String 是不可变的,所以无需使用此构造方法,除非需要 original 的显式副本。

http://blog.163.com/ichuanbo@126/blog/static/166706146201341801357935/  也可以自己进去看看
回复 使用道具 举报
3.第一个直接调用,第二创建A类对象调用,如果是静态的可以用A类名.调用是,第三可以用this调用
回复 使用道具 举报
1,string s1 = new String("abc")
newString("abc")首先会到常量池中看有没有abc,有的直接调用,没有在创建同样这个也是有地址值的,这是常量池的特点,然后在new一个对象到堆内存中,把常量池中abc的副本拷贝一份放进堆内存中.再把地址值赋给s1.今天讨论过这个问题 ,觉得没必要纠结是先创建堆的地址值还是常量池,但是肯定得到的是怼的地址值.
2,String s1 = "ab";
                String s2 = "abc";
                String s3 = s1 + "c";
首先你要看string的api,Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)这个叫字符串的缓冲区!!!类及其 append 方法实现的。字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。
首先main方法进栈,有一个string s1 然后常量池中创建ab赋给s1
回复 使用道具 举报
1,string s1 = new String("abc")
newString("abc")首先会到常量池中看有没有abc,有的直接调用,没有在创建同样这个也是有地址值的,这是常量池的特点,然后在new一个对象到堆内存中,把常量池中abc的副本拷贝一份放进堆内存中.再把地址值赋给s1.今天讨论过这个问题 ,觉得没必要纠结是先创建堆的地址值还是常量池,但是肯定得到的是怼的地址值.
2,              String s1 = "ab";
                String s2 = "abc";
                String s3 = s1 + "c";
首先你要看string的api,Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)这个叫字符串的缓冲区!!!类及其 append 方法实现的。字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。
首先main方法进栈,有一个string s1 然后常量池中创建ab赋给s1,然后s2创建常量值abc s2就能拿到abc的地址值,(因为是两个对象s1,s2所以创建两个).s3=s1+c,这是+号字符串串联,因为是串联所以底层先创建一个stringbuffer对象或stringBulider对象放进堆内存,然后通过append方法把abc加到一起,这个stringbuffer对象也有地址值但会先调用他的tostring方法转换成string字符串(他也是有地址值的).然后在把地最后这个string字符串的地址值赋给s3
码字挺累的我建议你自己找找笔记看看父子类,这样容易记得牢
4就没必要这么深究了,知道是转义字符,知道什么意思就够了
希望能帮到你
回复 使用道具 举报
1,String s1 = new String("abc");    //s1记录的是堆内存的地址值 ,但它在常量池中也创建了对象,为什么只记录一个堆内存地址?
2,String s1 = "ab"; String s3 = s1 + "c";    //答案已知,但是在内存中如何进行的一知半解,求详细解答,有条件附图说明
前两个问题是有关的,话说内存之类的我也有点不懂 楼上的说的好像挺有道理。
我就知道String s =new String("ab");是创建了2个对象,而String s = “ab”;是创建了1个对象。因为String本身就是引用类型,它的底层是字符数组
对于String s = new String("ab");来说,首先new的时候调用String类的构造方法创建了一个对象指向了变量s,而这个构造方法在获得"ab"的时候又是通过一个对象获得的,在创建"ab"的时候,jvm实际上进行了判断,也就是看字符串池中有没有对象,没有,就创建了"ab"然后把它放入池中,所以s的地址实际上就是new出来的堆内存地址,跟在常量池中的"ab"无关。
至于第二题,有点没看懂想问的是什么,总之就记住,String变量指向的是堆内存地址,而通过这个对象又与字符串池里的字符串相连。
3,子类A重写了父类B的b方法,如果在子类A中调用这个方法有几种方式?分别是什么?
Fu fu = new Fu(); fu.方法    这是最普通的,父类方法不能是抽象的
super.父类方法(super代表父类对象,没什么好说的)
Zi zi = new Fu();  zi.父类方法(这里类型是Zi, 但实际运行的对象是Fu,所以方法也是父类的方法)
4,java中"\"是转义字符,常用的\d \t \n也都知道它们的意思,但深究为什么转义以及什么情况下转义却一头雾水,急盼解疑
转义为什么要用,最主要的还是因为编程语言中的一些符号本身是语法的一部分,所以必须配合转义字符把它表示出来。
例如java中的引号”“本身就是修饰一些值的符号,所以必须用转义字符加上符号本身来表示这种符号
另外一种情况,就是一些键盘上的键在ASCII码中并没有值,所以用转义字符加上一些字母表示,比如\n、\r等等
回复 使用道具 举报
the_way 发表于 2016-4-26 23:33
1,String s1 = new String("abc");    //s1记录的是堆内存的地址值 ,但它在常量池中也创建了对象,为什么只 ...

另外一种情况,就是一些键盘上的键在ASCII码中并没有值,所以用转义字符加上一些字母表示,比如\n、\r等等

这句话是你自己理解的还是有出处呢? 字符被占用,通过转义来表达特殊含义我懂了,但是你的这种情况我不懂
回复 使用道具 举报
the_way 发表于 2016-4-26 23:33
1,String s1 = new String("abc");    //s1记录的是堆内存的地址值 ,但它在常量池中也创建了对象,为什么只 ...

另外一种情况,就是一些键盘上的键在ASCII码中并没有值,所以用转义字符加上一些字母表示,比如\n、\r等等

这句话是你自己理解的还是有出处呢? 字符被占用,通过转义来表达特殊含义我懂了,但是你的这种情况我不懂
回复 使用道具 举报
Unknown_Explore 发表于 2016-4-26 15:10
1.s1记录的是堆内存的地址值,而在堆内存的内存空间里面,还有在常量池里面的"abc"常量的副本。
2.s1的"ab" ...

现在,我对第一题有更深入的理解了,然后再来给你说说。
String s1=new String("abc");  
首先,在栈中声明一个String类型的引用s1,然后到new String("abc")这一步,首先去常量池中看看有没有"abc"这个玩意,常量池说到底就是个数组,String类型的底层也是个char[] 字符数组,而字符串常量池中的实际也一样是个char[] 字符数组,所以实际上就是去这个数组里面看看有没有char[]{'a','b','c'} 这么一个数组,如果没有,那就创建一个,然后毕竟你是创建对象的,是new的。所以就肯定要到堆内存中创建一个String对象,而我们刚刚也提到了,String的底层,就是个char[] 字符数组,字符数组也是个引用类型数据,所以最后的结果是,堆内存中新创建的String类型对象的引用赋值给了栈内存中的s1,而堆内存中的这个对应的String对象里面的char[] 字符数组的引用就指向了常量池中char[]{'a','b','c'}它的引用。我之前说的副本差不多就是这个意思。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马