1、What will be printed when you execute the following code?
class C {
C() {
System.out.print("C");
}
}
class A {
C c = new C();
A() {
this("A");
System.out.print("A");
}
A(String s) {
System.out.print(s);
}
}
class Test extends A {
Test() {
super("B");
System.out.print("B");
}
public static void main(String[] args) {
new Test();
}
}
初始化过程是这样的:
1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
3.其次,初始化父类的普通成员变量和代码块,在执行父类的构造方法;
4.最后,初始化子类的普通成员变量和代码块,在执行子类的构造方法;
(1)初始化父类的普通成员变量和代码块,执行 C c = new C(); 输出C
(2)super(“B”); 表示调用父类的构造方法,不调用父类的无参构造函数,输出B
(3) System.out.print(“B”);
所以输出CBB
为什么没有执行父类方法的构造函数呢?
因为已经显式调用父类带参构造函数super(“B”)了,所以子类调用的父类构造器是A(String s),而不是无参构造器,除非在子类构造器里没有显式调用父类构造器,编译器才在子类构造器为其默认添加super();
是先执行父类的构造函数再执行子类的构造函数,这个执行顺序是没有错的。但是还有一个逻辑顺序,为什么平白无故的执行父类的构造函数呢?因为子类调用了(或默认调用了)父类的构造函数,在逻辑上是子类先执行。
2、给出以下代码,请给出结果.
class Two{
Byte x;
}
class PassO{
public static void main(String[] args){
PassO p=new PassO();
p.start();
}
void start(){
Two t=new Two();
System.out.print(t.x+””);
Two t2=fix(t);
System.out.print(t.x+” ” +t2.x);
}
Two fix(Two tt){
tt.x=42;
return tt;
}
}
解析: Byte默认值是null t2和t指向同一对象,因此是null 42 42
3、以下程序的输出结果为
class Base{
public Base(String s){
System.out.print("B");
}
}
public class Derived extends Base{
public Derived (String s) {
System.out.print("D");
}
public static void main(String[] args){
new Derived("C");
}
}
正确答案: 编译错误
在调用子类构造器之前,会先调用父类构造器,当子类构造器中没有使用"super(参数或无参数)"指定调用父类构造器时,是默认调用父类的无参构造器,如果父类中包含有参构造器,却没有无参构造器,则在子类构造器中一定要使用“super(参数)”指定调用父类的有参构造器
,不然就会报错。
4、运行输出结果
public class StringDemo{
private static final String MESSAGE="taobao";
public static void main(String [] args) {
String a ="tao"+"bao";
String b="tao";
String c="bao";
System.out.println(a==MESSAGE);
System.out.println((b+c)==MESSAGE);
}
}
正确答案:true false
这题是在考编译器的优化,hotspot中 编译时"tao"+“bao"将直接变成"taobao”,b+c则不会优化,因为不知道在之前的步骤中bc会不会发生改变,而针对b+c则是用语法糖,新建一个StringBuilder来处理