一道经典的面试题、寻求高手解答

时间:2021-08-14 21:59:36
package com.wxhx.java.other;

public class Test5 extends BB
{
public static void main(String[] args)
{
Test5 a = new Test5(5);
}

private int radius = 1;

public void draw()
{
System.out.println("A.draw(),radius =" + radius);
}

public Test5(int radius)
{
this.radius = radius;
System.out.println("A constructor");
}
}

class BB
{
private int radius = 10;

public void draw()
{
System.out.println("B.draw(),radius =" + radius);
}

public BB()
{
System.out.println("B constructor");
draw();
}

public BB(int x)
{
 System.out.println("B constructor  param");
     draw();
}
}

/*
 * (a) B constructor。
A.draw(),radius =0
A constructor        //

(b) B constructor。
B.draw(),radius =0
A constructor

(c) B constructor。
A.draw(),radius =10
A constructor

(d) B constructor。
A.draw(),radius =1
A constructor
 */

输出的内容以及为甚么?????????

15 个解决方案

#1


选(a)
生成一个类的对象的时候首先调用父类的构造函数,输出B constructor
接着执行draw()方法,但由于此方法被子类所覆盖,所以执行的是子类的draw()方法,输出A.draw(),radius =0 (注意这里并没执行到private int radius = 1; 或者private int radius = 10;所以radius被jvm初始化为0)
最后执行子类的构造函数,输出A constructor 

#2


引用 1 楼 gesanri 的回复:
选(a) 
生成一个类的对象的时候首先调用父类的构造函数,输出B constructor 
接着执行draw()方法,但由于此方法被子类所覆盖,所以执行的是子类的draw()方法,输出A.draw(),radius =0 (注意这里并没执行到private int radius = 1; 或者private int radius = 10;所以radius被jvm初始化为0) 
最后执行子类的构造函数,输出A constructor 


有没有讲解这方面的书籍和资料呀、求教。

#3


不明白radius为什么等于0

#4


在调用draw()的时候,其实 radius = 1这还没有执行,那可能有人会说,既然没有初始化赋值为1,那怎么等于0呢?这个其实是java的安全所在,当你定义一个变量的时候,java马上会给了你一个初始值。int的初始值是0,所以 radius = 0了。

#5


我选择(a)

#6


public class Test5 extends BB{

    private int radius=1;

    public void draw(){
        System.out.println("A.draw(),radius ="+radius);
    }

    public Test5(int radius){
        this.radius=radius;
        System.out.println("A constructor");
    }

    public static void main(String[] args){
        Test5 a=new Test5(5);
    }
}
class BB{

    private int radius=10;

    public BB(){
        System.out.println("B constructor");
        draw();
    }

    public BB(int x){
        System.out.println("B constructor  param");
        draw();
    }

    public void draw(){
        System.out.println("B.draw(),radius ="+radius);
    }
}


帖代码要好看些。

#7


引用 4 楼 haozhenmail 的回复:
在调用draw()的时候,其实 radius = 1这还没有执行,那可能有人会说,既然没有初始化赋值为1,那怎么等于0呢?这个其实是java的安全所在,当你定义一个变量的时候,java马上会给了你一个初始值。int的初始值是0,所以 radius = 0了。

java里的类,都是先执行成员变量的声明的呀,

public class Test
{
private int i=2;
public Test()
{
draw();
}
public void draw()
{
System.out.println(i);
}
public static void main(String[] args)
{
new Test();
}
}
这个为什么就知道输出2,而不输出0呢?

#8


这个在你用new产生对象的时候,i=2被执行了,实例变量初始化在构造器之前执行。

#9


引用 7 楼 xiongwenhua365 的回复:
引用 4 楼 haozhenmail 的回复:

在调用draw()的时候,其实 radius = 1这还没有执行,那可能有人会说,既然没有初始化赋值为1,那怎么等于0呢?这个其实是java的安全所在,当你定义一个变量的时候,java马上会给了你一个初始值。int的初始值是0,所以 radius = 0了。 

java里的类,都是先执行成员变量的声明的呀, 
Java code

public class Test
{
    private int i=2;
    public Test()
    {
        draw();
    }
    pu…



因为draw()这个方法是在本类中调用的,而这时本类成员已经被赋值了。
上一题是由父类的构造调用的,这时Test类的成员还没有被赋值。

#10


过程如下:
     在堆中存在两个对象,test5对象和BB对象,同时test5持有一个BB的引用,两个对象中各有一个radius实例
     1.main函数调用test5的带参构造函数,而构造函数第一行默认调用基类的同参数的构造函数,这时候test5中的radius初始化为0
     2.BB调用自己带参构造函数,初始化化自己的radius=10,输出B constructor,调用draw();但是由于draw()方法的重写,根据多态的动态绑定,
        它将调用test5中的draw(),所以输出A.draw(),radius=,因为此时test5中的构造函数还没执行,所以它的radius为默认值0,所以输出0
     3.返回执行test5 的构造函数,初始化radius=5,输出A constructor
         

#11


个人理解:
执行顺序为:
创建类时:先初始化父类的成员,在构造类
创建子类时:先创建父类,在创建子类
因此,
1:BB.radium=10
2: BB()
3: Test5.draw(但调用的没有赋值的Test5.radium,因此为0)
4:Test5.radium=1;
5: Test5()

#12


构造函数第一行默认调用基类的同参数的构造函数
对吗?

引用 10 楼 WN2007 的回复:
过程如下: 
    在堆中存在两个对象,test5对象和BB对象,同时test5持有一个BB的引用,两个对象中各有一个radius实例 
    1.main函数调用test5的带参构造函数,而构造函数第一行默认调用基类的同参数的构造函数,这时候test5中的radius初始化为0 
    2.BB调用自己带参构造函数,初始化化自己的radius=10,输出B constructor,调用draw();但是由于draw()方法的重写,根据多态的动态绑定, 
        它将调用test5中的dra…

#13


引用 8 楼 haozhenmail 的回复:
这个在你用new产生对象的时候,i=2被执行了,实例变量初始化在构造器之前执行。


你的意思是Test5 a=new Test5(5);在构造方法之前Test5类被载入java虚拟机、private int radius=1;应该被执行、
即打印出来的应该是:
B constructor
A.draw(),radius =1
A constructor

#14


引用 11 楼 msgsnd 的回复:
个人理解: 
执行顺序为: 
创建类时:先初始化父类的成员,在构造类 
创建子类时:先创建父类,在创建子类 
因此, 
1:BB.radium=10 
2: BB() 
3: Test5.draw(但调用的没有赋值的Test5.radium,因此为0) 
4:Test5.radium=1; 
5: Test5()

原代码中是: private int radius = 10;  即 变量 radius在声明的同时也就初始化了(同时完成),既然后面能够引用
radius,则说明radius被声明了,同时它也被初始化了,所以radius的值是10,(我是这样理解的)所以不存在什么没有赋值的确良Test5.radium.

#15


看了点资料可以这样理解。

初始化是按照下面的顺序完成的。
(1)设置成员的值为默认的初始值(0、false、null)。
(2)调用对象的构造方法(但是还没有执行构造方法体)。
(3)调用父类的构造方法。
(4)使用初始化程序和初始块初始化成员。
(5)执行构造方法体。

#1


选(a)
生成一个类的对象的时候首先调用父类的构造函数,输出B constructor
接着执行draw()方法,但由于此方法被子类所覆盖,所以执行的是子类的draw()方法,输出A.draw(),radius =0 (注意这里并没执行到private int radius = 1; 或者private int radius = 10;所以radius被jvm初始化为0)
最后执行子类的构造函数,输出A constructor 

#2


引用 1 楼 gesanri 的回复:
选(a) 
生成一个类的对象的时候首先调用父类的构造函数,输出B constructor 
接着执行draw()方法,但由于此方法被子类所覆盖,所以执行的是子类的draw()方法,输出A.draw(),radius =0 (注意这里并没执行到private int radius = 1; 或者private int radius = 10;所以radius被jvm初始化为0) 
最后执行子类的构造函数,输出A constructor 


有没有讲解这方面的书籍和资料呀、求教。

#3


不明白radius为什么等于0

#4


在调用draw()的时候,其实 radius = 1这还没有执行,那可能有人会说,既然没有初始化赋值为1,那怎么等于0呢?这个其实是java的安全所在,当你定义一个变量的时候,java马上会给了你一个初始值。int的初始值是0,所以 radius = 0了。

#5


我选择(a)

#6


public class Test5 extends BB{

    private int radius=1;

    public void draw(){
        System.out.println("A.draw(),radius ="+radius);
    }

    public Test5(int radius){
        this.radius=radius;
        System.out.println("A constructor");
    }

    public static void main(String[] args){
        Test5 a=new Test5(5);
    }
}
class BB{

    private int radius=10;

    public BB(){
        System.out.println("B constructor");
        draw();
    }

    public BB(int x){
        System.out.println("B constructor  param");
        draw();
    }

    public void draw(){
        System.out.println("B.draw(),radius ="+radius);
    }
}


帖代码要好看些。

#7


引用 4 楼 haozhenmail 的回复:
在调用draw()的时候,其实 radius = 1这还没有执行,那可能有人会说,既然没有初始化赋值为1,那怎么等于0呢?这个其实是java的安全所在,当你定义一个变量的时候,java马上会给了你一个初始值。int的初始值是0,所以 radius = 0了。

java里的类,都是先执行成员变量的声明的呀,

public class Test
{
private int i=2;
public Test()
{
draw();
}
public void draw()
{
System.out.println(i);
}
public static void main(String[] args)
{
new Test();
}
}
这个为什么就知道输出2,而不输出0呢?

#8


这个在你用new产生对象的时候,i=2被执行了,实例变量初始化在构造器之前执行。

#9


引用 7 楼 xiongwenhua365 的回复:
引用 4 楼 haozhenmail 的回复:

在调用draw()的时候,其实 radius = 1这还没有执行,那可能有人会说,既然没有初始化赋值为1,那怎么等于0呢?这个其实是java的安全所在,当你定义一个变量的时候,java马上会给了你一个初始值。int的初始值是0,所以 radius = 0了。 

java里的类,都是先执行成员变量的声明的呀, 
Java code

public class Test
{
    private int i=2;
    public Test()
    {
        draw();
    }
    pu…



因为draw()这个方法是在本类中调用的,而这时本类成员已经被赋值了。
上一题是由父类的构造调用的,这时Test类的成员还没有被赋值。

#10


过程如下:
     在堆中存在两个对象,test5对象和BB对象,同时test5持有一个BB的引用,两个对象中各有一个radius实例
     1.main函数调用test5的带参构造函数,而构造函数第一行默认调用基类的同参数的构造函数,这时候test5中的radius初始化为0
     2.BB调用自己带参构造函数,初始化化自己的radius=10,输出B constructor,调用draw();但是由于draw()方法的重写,根据多态的动态绑定,
        它将调用test5中的draw(),所以输出A.draw(),radius=,因为此时test5中的构造函数还没执行,所以它的radius为默认值0,所以输出0
     3.返回执行test5 的构造函数,初始化radius=5,输出A constructor
         

#11


个人理解:
执行顺序为:
创建类时:先初始化父类的成员,在构造类
创建子类时:先创建父类,在创建子类
因此,
1:BB.radium=10
2: BB()
3: Test5.draw(但调用的没有赋值的Test5.radium,因此为0)
4:Test5.radium=1;
5: Test5()

#12


构造函数第一行默认调用基类的同参数的构造函数
对吗?

引用 10 楼 WN2007 的回复:
过程如下: 
    在堆中存在两个对象,test5对象和BB对象,同时test5持有一个BB的引用,两个对象中各有一个radius实例 
    1.main函数调用test5的带参构造函数,而构造函数第一行默认调用基类的同参数的构造函数,这时候test5中的radius初始化为0 
    2.BB调用自己带参构造函数,初始化化自己的radius=10,输出B constructor,调用draw();但是由于draw()方法的重写,根据多态的动态绑定, 
        它将调用test5中的dra…

#13


引用 8 楼 haozhenmail 的回复:
这个在你用new产生对象的时候,i=2被执行了,实例变量初始化在构造器之前执行。


你的意思是Test5 a=new Test5(5);在构造方法之前Test5类被载入java虚拟机、private int radius=1;应该被执行、
即打印出来的应该是:
B constructor
A.draw(),radius =1
A constructor

#14


引用 11 楼 msgsnd 的回复:
个人理解: 
执行顺序为: 
创建类时:先初始化父类的成员,在构造类 
创建子类时:先创建父类,在创建子类 
因此, 
1:BB.radium=10 
2: BB() 
3: Test5.draw(但调用的没有赋值的Test5.radium,因此为0) 
4:Test5.radium=1; 
5: Test5()

原代码中是: private int radius = 10;  即 变量 radius在声明的同时也就初始化了(同时完成),既然后面能够引用
radius,则说明radius被声明了,同时它也被初始化了,所以radius的值是10,(我是这样理解的)所以不存在什么没有赋值的确良Test5.radium.

#15


看了点资料可以这样理解。

初始化是按照下面的顺序完成的。
(1)设置成员的值为默认的初始值(0、false、null)。
(2)调用对象的构造方法(但是还没有执行构造方法体)。
(3)调用父类的构造方法。
(4)使用初始化程序和初始块初始化成员。
(5)执行构造方法体。