关于构造方法的理解不是很清楚,请大家指点。

findjober 2007-07-14 10:11:46
public class Test
{
public static void main(String args[])
{
Person p1 = new Person("A");
Person p2 = new Person("B", "Shanghai");
Student s1 = new Student("C", "S1");
Student s2 = new Student("D", "Shanghai", "S2");
System.out.println(p1.info());
System.out.println(p2.info());
System.out.println(s1.info());
System.out.println(s2.info());
}
}

class Person
{
private String name;
private String location;

Person(String name)
{
this.name = name;
location = "Beijing";
}

Person(String name, String location)
{
this.name = name;
this.location = location;
}

public String info()
{
return "name: " + name + " location: " + location;
}
}

class Student extends Person
{
private String school;
Student(String name, String school)
{
this(name, "Beijing", school);
}
Student(String n, String l, String school)
{
super(n, l);
this.school = school;
}
public String info()
{
return super.info() + " school: " + school;
}
}

程序很简单,但是有一点我不明白,就是在初始化子类的时候不是要先调用父类的构造方法吗?如果没有显式调用,那么系统自动调用默认的不带参数的构造方法。可是Student s1 = new Student("C", "S1");这句执行的时候它的构造方法中没有显式的调用父类的构造方法,且父类中也没有不带参数的构造方法,那么为什么不会出现错误?不解。
...全文
272 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2008-06-04
  • 打赏
  • 举报
回复
调试下。就知道了,同一类型的问题。

package testOrder;

class Person {
int age = 0;

public Person() { //*******************************注释 + -
System.out.println("2、然后执行了super");
}

Person(int age){
System.out.println("******");
}

public void fun() {
System.out.println("super.age=" + age);
}
}

public class Test4 extends Person {
static {
System.out.println("1、先执行了static区域");
}

int age = 10;

public Test4() {
super(3);
super.fun();
System.out.println("3、然后执行了this() age=" + age);
}

public Test4(int age) {
super(2);
// this();
System.out.println("4、然后执行了this(int age) 年龄是:" + age);
}

public static void main(String[] args) {
Test4 test = new Test4(20);
// Person p=new Person(23);
}
}
中鱼文林 2007-07-14
  • 打赏
  • 举报
回复
调试跟踪一下
weiqiyiji 2007-07-14
  • 打赏
  • 举报
回复
我仔细看了下thinking in java,应该这样解释合理些。首先是书上说的:
编译器可以轻松调用基类构造器是因为不用考虑传递什么样的参数。但是如果类没有缺省的参数,或者想调用一个带参数的构造器,就必须super调用基类构造器,并配以适当的参数。这是一个例子class Game {
Game(int i) {
System.out.println("Game constructor");
}
}

class BoardGame extends Game {
BoardGame(int i) {
super(i);//如果这没调用,就会报错。
System.out.println("BoardGame constructor");
}
}

public class Chess extends BoardGame {
private static Test monitor = new Test();
Chess() {
super(11);
System.out.println("Chess constructor");
}
public static void main(String[] args) {
Chess x = new Chess();
/*输出
"Game constructor",
"BoardGame constructor",
"Chess constructor"
*/
}
}
在楼主的例子当中
Student(String n, String l, String school) {
//super(n, l);
//将super注释掉后eclipse的提示为“未定义隐式超构造函数 Person()。必须显式调用另一个//构造函数”。那么一般情况下调用的的确是缺省构造器
this.school = school;
}
Student(String name, String school)
{
this(name, "Beijing", school);
}//在这之中的确是调用的super(name,"Beijing"),由this调用的。所以在this前加其他语句会报//错

所以把我的话做下修改,当父类没有缺省构造器时,子类调用相同参数的父类构造器。父类有缺省构造器时,就调用缺省的
awusoft 2007-07-14
  • 打赏
  • 举报
回复
像上面的,那么在调用Student(String name, String school)
{
System.out.println("AAA");
this(name, "Beijing", school);
}
这时候不是应该调用
Person(String name, String location)
{
this.name = name;
this.location = location;
}
事实上没有哦
awusoft 2007-07-14
  • 打赏
  • 举报
回复
编译器会调用与子类参数相同的基类构造器
======对于这句话有点怀疑哦,我想应该是调用无参的构造函数.
weiqiyiji 2007-07-14
  • 打赏
  • 举报
回复
编译器会调用与子类参数相同的基类构造器
Student(String n, String l, String school)
{
super(n, l);
this.school = school;
}
在这之中,由于基类没有这样的构造器,所以你必须显式的调用一个父类构造器,不信你把super去掉。
Student(String name, String school)
{
System.out.println("AAA");
this(name, "Beijing", school);
}但在这之中,它执行的时候实际上是这样的
Student(String name, String school)
{
super(name,school);
System.out.println("AAA");
this(name, "Beijing", school);
}
所以为什么你说会调用无参构造器,是因为你的构造器无参,如果你的构造器有参,那也会调用有参构造器
awusoft 2007-07-14
  • 打赏
  • 举报
回复
public class Test
{
public static void main(String args[])
{
Person p1 = new Person("A");
Person p2 = new Person("B", "Shanghai");
Student s1 = new Student("C", "S1");
Student s2 = new Student("D", "Shanghai", "S2");
System.out.println(p1.info());
System.out.println(p2.info());
System.out.println(s1.info());
System.out.println(s2.info());
}
}

class Person
{
private String name;
private String location;

Person(String name)
{
this.name = name;
location = "Beijing";
}

Person(String name, String location)
{
this.name = name;
this.location = location;
}

public String info()
{
return "name: " + name + " location: " + location;
}
}

class Student extends Person
{
private String school;
Student(String name, String school)
{
System.out.println("AAA");
this(name, "Beijing", school);
}
Student(String n, String l, String school)
{
super(n, l);
this.school = school;
}
public String info()
{
return super.info() + " school: " + school;
}
}
这样报错了.
awusoft 2007-07-14
  • 打赏
  • 举报
回复
Student(String name, String school)问题是它里边马上去调用别的构造函数了
awusoft 2007-07-14
  • 打赏
  • 举报
回复
或者你把super(n,1)去了你就会发现报错了,所以这里的结论应该是,第一个构造函数应该没有调用父类的构造函数,因为它转到别的构造函数去构造了
findjober 2007-07-14
  • 打赏
  • 举报
回复
书上不是这么说的啊,说要先调用父类构造方法在子类内部构造出父类后才能继续执行,否则不成了无本之木?所以我很不理解。
虽然Student(String n, String l, String school)
{
super(n, l);
this.school = school;
}
这个构造方法调用了父类的构造方法,但是Student s1 = new Student("C", "S1");明显调用的是Student(String name, String school)啊,所以应该先调用父类的无参数构造方法,然后再执行this(name, "Beijing", school);,郁闷啊。
awusoft 2007-07-14
  • 打赏
  • 举报
回复
它调用了其它的构造函数,所以应该是在其它的地方调用父类的构造函数了,你改来试一下啊,
不要这一句试试看this(name, "Beijing", school);
awusoft 2007-07-14
  • 打赏
  • 举报
回复
会不会先执行this(name, "Beijing", school);这里,然后才会去想父类的构造呢?
lalakid 2007-07-14
  • 打赏
  • 举报
回复
留名

62,623

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧