当前位置:首页 > java练习题(含答案)
结果说明:因为s2.intern()只是执行了,而没有把String Pool中的“abc”的地址赋给s2,所以s1还是指向String Pool中的“abc”,s2则指向Heap中的“abc”,对于s1 == s2,返回值为false;对于s1 == s2.intern(),其中s2.intern()的返回值为指向String Pool中“abc”的地址,故s2.intern()与s1指向同一个对象,因而返回true;因为s3 = s3.intern()把String Pool中的“abc”的地址赋给了s3,此时s1和s3指向的是同一对象,即String Pool中的“abc“,因而返回true。
例程8: Java代码 1. String s1 = \
2. String s2 = new String(\
3. String s3 = \+ new String(\ 4. System.out.println(s1 == s2); 5. System.out.println(s1 == s3); 6. System.out.println(s2 == s3);
运行结果如下: false false false
结果说明:
s1指向String Pool中的字符串对象“abc”,编译期确定; s2指向Heap中的字符串对象“abc”,运行期确定;
s3指向Heap中的另一个字符串对象“abc”,运行期确定。 注意:String s3 = \等价于
String s3 = new StringBuilder().append(\String(\
思考:String s = \产生了那几个对象? 解:等价于String s = new StringBuilder().append(\
String(\,会在String Pool中产生\、\、\三个对象,在Heap中产生\、\两个个对象。一共5个字符串对象。
例程9: Java代码 1. String s1 = \ 2. s1 = \
3. String s2 = \
4. String s3 = new String(\ 5. System.out.println(s1 == s2); 6. System.out.println(s2 == s3);
运行结果如下: false false
分析这段程序的执行过程:
首先在加载Java程序时,JVM会创建一片的内存空间(String Pool)专门存入string对象。
String s1 = \,现在栈中创建一个字符串引用s1,然后JVM会在String Pool中查找是否存在\,如果存在,则直接使用它,将其地址赋给s1,如果不存在(这时String Pool中显然不存在\),则在String Pool中创建\,并将其地址赋给s1。
s1 = \,JVM会在String Pool中查找是否存在\,如果存在,则直接使用它,将其地址赋给s1,如果不存在(这时String Pool中显然不存在\),则在String Pool中创建\,并将其地址赋给s1。而原来的字符串对象\仍然在String Pool中,没有消失,因为String对象的值是不能被修改的。这里只是改变了引用的值即引用指向的对象的地址,而没有改变它所引用的对象。
String s2 = \,JVM会在String Pool里查看有没有字符串\,若有,则返回它的地址给s2,否则,创建新的String对象\, 放到String Pool里。这里由于\对象已经创建,并存在于String Pool中,因而不需要重新创建String对象\。此时s1指向String Pool中的\,s2指向String Pool中的\,故s1 == s2的值为false。
String s3=String(\,JVM会在String Pool里查看有没有字符串\,若有,直接执行new操作,若没有,则先要在String Pool中创建\,然后执行new操作,由于遇到了new,还会在Heap上(不是String Pool里)创建string对象\,并将Heap上的\对象的地址赋给引用s3。所以s2 == s3将返回false,因为s2和s3不是引用同一个对象。
以上小结如理解有误,希望各位高手指教!
写代码验证静态代码块被自动执行,就算产生了类的多个实例对象,但其中的静态代码块只被执行了一次。
class Parent { }
class Child extends Parent { }
public class TextStatic {
public static void main(String[] args) { }
// TODO Auto-generated method stub new Child();// 语句(*) new Child(); public Child() { }
System.out.println(\); static String childName = \; { }
static { }
System.out.println(\); System.out.println(\); public Parent() { }
System.out.println(\); static String name = \; { }
static { }
System.out.println(\); System.out.println(\);
}
运行结果:
parent static block child static block parent block parent constructor child block child constructor parent block parent constructor child block child constructor
分析:当执行new Child()时,它首先去看父类里面有没有静态代码块,如果有,它先去执行父类里面静态代码块里面的内容,当父类的静态代码块里面的内容执行完毕之后,接着去执行子类(自己这个类)里面的静态代码块,当子类的静态代码块执行完毕之后,它接着又去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法,这个就是一个对象的初始化顺序。 总结:
对象的初始化顺序:首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法。总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。
注意:子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。
共分享92篇相关文档