java习题和解答:关于构造方法、成员变量、继承、变量的赋值

java习题和解答:关于构造方法、成员变量、继承、变量的赋值

发信人: ludongxing (ludongxing), 信区: Java
标  题: 大家猜猜这个java的运行结果是什么?
发信站: 水木社区 (Sat Feb  8 22:46:21 2020), 站内  [累计积分奖励: 100/0]
  
文件名是 Test.java
  
class A {
  
int x=5;
  
public A(){
pk();
}
  
     public void pk() {
     System.out.println(x);
     }
    
}
  
  
class B extends A{
int x=6;
  
     public void pk() {
     System.out.println(x);
     }
  
}
  
  
  
public class Test {
  
public static void main(String args[]) {
    B mb = new B();
}
  
}
  
  
/////////////////////////////////////////////////////
运行结果为啥不是 6 ?
A的pk()不是被B的pk()覆盖了吗?结果不应该是 6 吗?
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 110.255.89.*]

发信人: elizabethxxy (此处留白), 信区: Java
标  题: Re: 大家猜猜这个java的运行结果是什么?
发信站: 水木社区 (Sun Feb  9 12:51:02 2020), 站内  [累计积分奖励: 100/0]
  
1. 关于类的构造方法、类继承中构造方法的访问:
如果类没有给出构造方法,系统将给出一个默认的无参构造方法供这个类使用。
子类构造方法执行前,都会先执行父类的无参构造方法。因为子类会继承父类的成员方法,父类必须先初始化好了,子类才能继承。在子类的构造方法中,默认第一行有一条语句super(),即必须在构造方法的第一行。如果子类没有写super(),系统会默认加上一条。如果我们写了构造方法,系统就不会给我们提供构造方法了。
在楼主的代码中,类B没有明确写自己的构造方法,那么它的构造方法就是默认构造方法。因为类B是类A的子类,所以在执行类B的构造方法之前,会先执行父类A的无参构造方法。
  
2. 关于类继承中成员方法的覆盖:
java继承中成员方法的访问特点是就近原则。子类中方法和父类中方法的声明相同时(这叫方法的覆盖override),调用的是子类中的方法。
在楼主的代码中,类A有成员方法pk(),类B也有成员方法pk(),由于类B继承了类A,所以类B是类A的子类。调用类B的构造方法时,会先调用父类A的构造方法。在父类A的构造方法中调用成员方法pk()时,由于成员方法pk()被子类B的成员方法pk()覆盖,这时调用的就是子类B中的成员方法pk()。
  
3. 关于变量的默认值、初始化和赋值:
类的成员变量有默认值,可以不用初始化就可以使用。给类的成员变量赋值的方法通常有两种:A.setXxx()  B.构造方法。还有一种是直接赋值的方法,如int x = 5;但是这种方法不建议采用。局部变量没有默认值,必须先定义(即初始化)、赋值,最后使用。
在楼主的代码中,类A的成员变量x和类B的成员变量x都没有采用常用的赋值的方法来赋值,所以一开始采用的都是默认值。int数据类型的默认值是0,所以x的值都是0。后期待代码调用到第三种直接赋值的方法时,才给x赋值。
  
4. 关于成员变量和局部变量:
成员变量的位置在类中方法外。局部变量在方法内或者方法声明上(形式参数)。如果局部变量名和成员变量名称一致,在方法中使用的时候采用的是就近原则,所以用this来区分成员变量和局部变量。方法被哪个对象调用,this就代表谁。
成员变量名称相同时,在子类方法中访问变量,(1)在方法的局部范围找,如果有就使用。(2)在子类的成员范围找,如果有就使用。(3)在父类的成员范围找,如果有就使用。(4)如果还找不到,就报错。
在楼主代码中的x都是类的成员变量,pk都是类的成员方法。类A的成员方法pk内调用变量x,先在成员方法pk内找局部变量x,由于方法pk内没有局部变量x,按照就近原则,就在成员方法pk所属的类A的成员变量中找有没有名字为x的成员变量,找到了,就采用成员变量x。B的pk方法也是类似的思路,采用B的成员变量x。
  
综上所述,调用的大致路线是:类B的默认构造方法-->类A的构造方法(初始化A的成员变量x=0。在类A的代码之内方法之外,从上到下执行赋值语句,将A的成员变量x赋值为5。由于A的构造方法里调用了pk()方法,先用B的成员方法pk()把A的成员方法pk()覆盖,覆盖后的pk()代码按照就近原则寻找,因为现在的pk()是B的成员方法,所以它就近找到B的成员变量x。B的成员变量x还没有初始化,所以系统采用x的默认值为0。将B的成员变量x现在的值0打印出来。到此,A的构造方法执行完毕。)-->返回到B的构造方法里,先初始化B的成员变量x=0。在类
B的代码之内方法之外,从上到下执行赋值语句,将B的成员变量x赋值为6。再执行B的构造方法里下面的代码(无)。到此,B的构造方法执行完毕。
~~~~~~~~
  
以上是对楼主代码的分析,下面是一些建议:
1. 不要在父类的构造方法中调用可能被子类覆盖的方法。因为子类初始化会调用父类的构造方法,当父类构造方法调用被子类覆盖的方法时,往往由于子类初始化未完成导致异常。
2. 构造方法最好只用于给对象的数据进行初始化。
3. 构造方法至少写两个:空参构造方法、全参构造方法。
4. 给普通成员变量赋值时,最好采用这两种方法: A.setXxx()   B.构造方法,在这两个方法内给成员变量赋值,不要在类A的代码之内方法之外给成员变量赋值。
~~~~~~~~
  
全部代码见我的第二个re贴。
  
  
over
※ 修改:·elizabethxxy 于 Feb  9 14:32:41 2020 修改本文·[FROM: 42.122.25.*]
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 42.122.25.*]

发信人: elizabethxxy (此处留白), 信区: Java
标  题: Re: 大家猜猜这个java的运行结果是什么?
发信站: 水木社区 (Sun Feb  9 12:53:53 2020), 站内  [累计积分奖励: 100/0]
  
我的全部代码如下,同时以附件的形式上传了。
  
//file name: A.java
  
public class A {
     int x=5;
  
     public A(){
         System.out.println("调用pk()方法之前,A的成员变量x的值为:" + x);
         pk();
         System.out.println("调用pk()方法之后,A的成员变量x的值为:" + x);
     }
  
     public void pk(){
         System.out.println("从类A里调用pk()方法,开始");
         System.out.println(x);
         System.out.println("从类A里调用pk()方法,结束");
     }
}
  
  
//file name: B.java
  
public class B extends A {
     int x=6;
  
     public void pk() {
         System.out.println("从类B里调用pk()方法,开始");
         System.out.println(x);
         System.out.println("从类B里调用pk()方法,结束");
     }
  
}
  
  
//file name: Test.java
  
public class Test {
     public static void main(String args[]) {
         B mb = new B();
     }
}
  
  
  
输出结果:
调用pk()方法之前,A的成员变量x的值为:5
从类B里调用pk()方法,开始
0
从类B里调用pk()方法,结束
调用pk()方法之后,A的成员变量x的值为:5
  
  
  
  
over
  
  
  
【 在 ludongxing 的大作中提到: 】
: 文件名是 Test.java
: class A {
: int x=5;
: ...................

附件(481B) A.java
附件(271B) B.java
附件(128B) Test.java
--
  
[upload=1][/upload][upload=2][/upload][upload=3][/upload]
※ 修改:·elizabethxxy 于 Feb  9 14:22:45 2020 修改本文·[FROM: 42.122.25.*]
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 42.122.25.*]

发信人: elizabethxxy (此处留白), 信区: Java
标  题: Re: 大家猜猜这个java的运行结果是什么?
发信站: 水木社区 (Sun Feb  9 18:15:02 2020), 站内
  
狂汗
  
回答网友提出的问题的过程  也是  我自己学习提高的过程。采用以终为始的学习策略,以能够完整地把知识点讲出来的方式  来 检验 自己学习到的知识、查漏补缺,算是挤兑自己、强迫自己老老实实学习、不许偷懒的方式吧。
  
大家共同学习,共同提高!
  
【 在 galaxy123 的大作中提到: 】
:  
: 厉害! 条理清晰,完美回答了所有疑惑。  
:  
: 【 在 elizabethxxy 的大作中提到: 】  
: : 1. 关于类的构造方法、类继承中构造方法的访问:  
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 42.122.25.*]

发布了105 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/elizabethxxy/article/details/104282555