黑马程序员技术交流社区

标题: 一个构造函数里面this()与super()为什么不能并存? [打印本页]

作者: 苏格拉底的弟子    时间: 2012-1-30 14:53
标题: 一个构造函数里面this()与super()为什么不能并存?
本帖最后由 苏格拉底的弟子 于 2012-1-31 18:58 编辑

一个构造函数里面this()与super()为什么不能并存?
作者: 彭嘉聪    时间: 2012-1-30 15:33
翻了两本书,都没有详细说,但是可以用一个现象来推测一下,
第一,super(),要先对父类构造对象,再对子类构造,所以,现有父类,才有子类,这不难理解构造函数中的第一个语句必须是super()先运行
第二,this()调用其他的构造函数,是必须先构造了那个再对自己进行属性赋值,所以this也必须是第一个语句先运行。
但是,假设你的结果成立,里面有super()和this()语句,this是调用其他构造函数,这个时候你想想,this.调用的构造函数里面没有super()吗?因为是继承,所以必须有,那这样不是冲突了吗?有两个super()运行
  1. tt(){//构造函数1
  2. //这里也必须有super();
  3. }

  4. tt(int a ){构造函数2
  5. super();
  6. this();
  7. this.a=a;
  8. }
复制代码
所以这个现象可能就引起了java程序的识别出错。
而且java规定两者要必须位于第一个位置,如果有一个是第二位的,就违反了java规则了。我觉得这样想就可以了
作者: 刘基军    时间: 2012-1-30 15:54
使用this()或是super()都必须放在第一行位置
作者: 张冬冬    时间: 2012-1-30 18:22
也不是说第一行位置,我觉得严谨一点应该是:必须是第一条执行的语句,两个都要第一条执行所以没办法冲突了
作者: 张伟~    时间: 2012-1-30 18:50
1.一个子类构造方法的第一条语句,都是隐含地调用super()
2.this和super为什么不能同时出现在一个构造函数里面:因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

作者: 张建银    时间: 2012-1-30 19:24
假如super()和this()同时存在,super()是直接构造该类的父类对象,因为本类一般是由Object继承来的,所以this()会先构造父类再构造自己(C++里的子父类的构造是这么做的),如果同时存在,则好比构造了2个父类对象,貌似不允许
作者: 胡威    时间: 2012-1-30 22:32
因为java中新建对象初始化时只能在类中的一个构造函数中进行一次初始化,如果在同一个构造函数中两次初始化就浪费资源,java规定这样无法通过编译。假设子类构造函数中既含有super() 又含有this(参数)  那么因为super到父类构造函数中进行了一次初始化,再执行this(参数) ,又会到子类的另一个构造函数中初始化,而这另一个子类构造函数中如果含有默认的super(),又回到父类构造函数中初始化,这样就造成虚拟机资源浪费。 所以二者只能含其一,并且必须是子类构造函数的第一条执行语句,因为父类初始化要优先进行。无论执行this还是super最终目的都是能够到父类的一个构造函数中初始化。
作者: 戴振良    时间: 2012-1-31 01:13
如果还不明白,可以看张孝祥java基础4-1视频,里面有说的,看了不明白就后退,反复看个5、6遍的应该差不多明白了
作者: 荣凯旋    时间: 2012-1-31 19:04
要知道这个你必须要知道他们而这的用法
一、this用途:
一是引用隐式参数,二是调用该类其他的构造器。

二、super用途:
一是调用超类的方法,二是调用超类的构造器

三、用法举例

[java] view plaincopyprint?package com.test.xqh;  
  
public class Manage extends Employee {  
  
    private String sex;  
  
    public Manage(String name, int age, String sex) {  
        super(name, age); // super用途2,调用超类的构造器   
        this.setSex(sex);  
    }  
  
    public String getName() {  
        return super.getName() + "HHHH"; // super用途1, 调用超类的方法   
    }  
  
    public void setSex(String sex) {  
        this.sex = sex;  
    }  
  
    public String getSex() {  
        return sex;  
    }  
  
    public void say() {  
        System.out.println("***");  
    }  
  
    public static void main(String[] args) {  
        Employee[] e = new Employee[2];  
        e[0] = new Employee("张三", 22);  
        e[1] = new Manage("李四", 22, "男");  
        System.out.println(e[0].getName());  
        System.out.println(e[1].getName());  
    }  
  
}  
  
class Employee {  
    private String name;  
    private int age;  
  
    public Employee(String name, int age) {  
        this(); // this用途2,调用该类的构造器(此例为默认的构造器)   
        this.name = name; // this用途1,引用隐式参数   
        this.age = age; // this用途1,引用隐式参数   
    }  
  
    public Employee() {  
  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
  
}  
package com.test.xqh;

public class Manage extends Employee {

        private String sex;

        public Manage(String name, int age, String sex) {
                super(name, age); // super用途2,调用超类的构造器
                this.setSex(sex);
        }

        public String getName() {
                return super.getName() + "HHHH"; // super用途1, 调用超类的方法
        }

        public void setSex(String sex) {
                this.sex = sex;
        }

        public String getSex() {
                return sex;
        }

        public void say() {
                System.out.println("***");
        }

        public static void main(String[] args) {
                Employee[] e = new Employee[2];
                e[0] = new Employee("张三", 22);
                e[1] = new Manage("李四", 22, "男");
                System.out.println(e[0].getName());
                System.out.println(e[1].getName());
        }

}

class Employee {
        private String name;
        private int age;

        public Employee(String name, int age) {
                this(); // this用途2,调用该类的构造器(此例为默认的构造器)
                this.name = name; // this用途1,引用隐式参数
                this.age = age; // this用途1,引用隐式参数
        }

        public Employee() {

        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public int getAge() {
                return age;
        }

        public void setAge(int age) {
                this.age = age;
        }

}
因为在构造的时候只需要调用父类的super()作为初始化父类一次,如果super(...)和this(...)同时出现的话,那么就会出现初始化父类两次的不安全操作,因为当super(...)和this(...)同时出现的时候,在调用完了super(..)之后还会执行this(..),而this(...)中又会自动调用super(),这就造成了调用两次super()的结果(这是假设super(...)和this(...)同时出现时候,super(...)在this(...)前面,反过来出现也一样)





作者: 荣凯旋    时间: 2012-1-31 19:15
最简洁的理解
构造函数必须出现在第一行上。

所以,注定了你只能调用一个构造函数。

默认的,父类的或者本类的其它构造,你自己选一个。
作者: 女神从来不加班    时间: 2015-3-25 01:09
荣凯旋 发表于 2012-1-31 19:15
最简洁的理解
构造函数必须出现在第一行上。

嗯这么一说明白了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2