super
什么是super:
在父和子中有同名的属性,或者说有相同的方法。
如果此时想在子类中访问父中的数据,必须使用“super.”加以区分。
1 super是一个关键字,全部小写
2 super和this对比着学习
this:
this能出现在实例方法中和构造方法中。
this的语法是:“this.”、“this()”
this不能使用在静态方法中
this. 大部分情况下是可以省略的
this. 什么时候不能省略呢?在区分局部变量和实例变量的时候不能省略
public void doSome(String a){
this.a = a;
}
this() 只能出现在构造方法第一行,通过当前的构造方法去调用“本类”中其他的构造方法,目的是:代码复用。
super:
super能出现在实例方法中和构造方法中。
super的语法是:“super.”、“super()”
super不能使用在静态方法中
super. 大部分情况下是可以省略的
super. 什么时候不能省略呢?????
super() 只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中其他的构造方法,
目的是:创建子类对象的时候,先初始化父类型特征。
3 super()
表示通过子类的构造方法调用父类的构造方法。
模拟现实世界中的这种场景:要想有儿子,需要先有父亲。
4 重要的结论:
当一个构造方法第一行:
既没有this()有没有super()的话,默认会有一个super();
表示通过当前子类的构造方法调用父类无参数构造方法。
所以必须保证父类无参数构造方式是存在的。
5 注意:
this()和super()不能共存,他们都是只能出现在构造方法第一行。
6 无论是怎样折腾,父类的构造方法一定会执行的。(百分百)
super.属性名 【访问父类中的属性】
super.方法名(实参) 【访问父类中的方法】
super(实参) 【访问父类中的构造方法】
案例1:
/* 1 super是一个关键字,全部小写 2 super和this对比着学习 this: this能出现在实例方法中和构造方法中。 this的语法是:“this.”、“this()” this不能使用在静态方法中 this. 大部分情况下是可以省略的 this. 什么时候不能省略呢?在区分局部变量和实例变量的时候不能省略 public void doSome(String a){ this.a = a; } this() 只能出现在构造方法第一行,通过当前的构造方法去调用“本类”中其他的构造方法,目的是:代码复用。 super: super能出现在实例方法中和构造方法中。 super的语法是:“super.”、“super()” super不能使用在静态方法中 super. 大部分情况下是可以省略的 super. 什么时候不能省略呢????? super() 只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中其他的构造方法, 目的是:创建子类对象的时候,先初始化父类型特征。 3 super() 表示通过子类的构造方法调用父类的构造方法。 模拟现实世界中的这种场景:要想有儿子,需要先有父亲。 4 重要的结论: 当一个构造方法第一行: 既没有this()有没有super()的话,默认会有一个super(); 表示通过当前子类的构造方法调用父类无参数构造方法。 所以必须保证父类无参数构造方式是存在的。 5 注意: this()和super()不能共存,他们都是只能出现在构造方法第一行。 6 无论是怎样折腾,父类的构造方法一定会执行的。(百分百) */ public class SuperTest01{ public static void main(String[] args){ // 创建子类对象 /* A类的无参构造方法! B类的无参数构造方法! */ new B(); } } class A /*extends Object*/{ // 建议手动的将一个类的无参构造方法写出来。 public A(){ super();//调用Object中的无参构造方法 System.out.println("A类的无参构造方法!"); } // 一个类如果没有手动提供任何构造方法,系统会默认提供一个无参数构造方法 // 一个类如果手动提供了一个构造方法,那么无参数构造系统将不再提供。 // 错误: 无法将类 A中的构造器 A应用到给定类型 public A(int a){ System.out.println("A类的有参数构造方法(int)"); } } class B extends A{ /* public B(){ //super(100); super(); System.out.println("B类的无参数构造方法!"); } */ public B(){ // 调用父类中有参数的构造方法 //this("张三"); //错误: 对super的调用必须是构造器中的第一个语句 //super(123);//错误: 对this的调用必须是构造器中的第一个语句 this("zhangsan"); System.out.println("B类的无参数构造方法!"); } public B(String name){ super();// 调用的是父类中的无参构造方法 System.out.println("B类的有参数构造方法(String)"); } }
案例2:
案例2: public class SuperTest02{ public static void main(String[] args){ new C(); // 先不要看答案哦,要通过自己的努力把答案写出来,那才是真的牛。 /* A的无参数构造方法执行 B类的有参数构造执行(String) C的有参构造方法执行(String,int) C的有参构造方法执行(String) C的无参数构造方法执行 在java语言中不管是new什么对象,最后老祖宗的Object类的无参构造方法一定会执行。 (Object类中的无参数构造方法是处于“栈顶部”) 栈顶的特点: 最后调用,但是最先执行结束。 后进先出原则。 大家要注意: 以后写代码的时候,一个类的无参数构造方法还是建议大家手动的写出来。 如果无参数构造方法丢失的话,可能会影响到“子类对象的构建”。 */ } } class A{ public A(){ System.out.println("A的无参数构造方法执行"); } } class B extends A{ public B(){ System.out.println("B的无参数构造方法执行"); } public B(String name){ System.out.println("B类的有参数构造执行(String)"); } } class C extends B{ public C(){//这个是最先调用的,但是是最后结束的 this("zhangsan"); System.out.println("C的无参数构造方法执行"); } public C(String name){ this(name,20); System.out.println("C的有参构造方法执行(String)"); } public C(String name,int age){ super(name); System.out.println("C的有参构造方法执行(String,int)"); } }
案例3:
/* 举个例子:在恰当的时间使用:super(实际参数列表); 注意:在构造方法执行过程中一连串调用了父类的构造方法,父类的构造方法又继续向下调用他的父类方法,但是实际上对象只创建了一个。 思考:super(实参)到底是干啥的。 super(实参)的作用是:初始化当前对象的父类特征。 并不是创建了新的对象,实际上对象只创建了一个。 super关键字代表的是什么? super关键字代表的就是“当前对象”那部分父类型特征。 我继承了我父亲的一部分特征 例如:“眼睛,皮肤等” super代表的就是“眼睛,皮肤等”。 眼睛,皮肤等 虽然是继承了父亲的,但是这部分是在我身上的。 */ //测试程序 public class SuperTest03{ public static void main(String[] args){ CreditAccount a = new CreditAccount(); System.out.println("账号:" + a.getActno() + "余额" + a.getBalance() + "信誉度" + a.getCredit()); CreditAccount b = new CreditAccount("1111",100000,0.99); System.out.println("账号:" + b.getActno() + "余额" + b.getBalance() + "信誉度" + b.getCredit()); } } // 银行账户类 // 银行的属性: 账号、余额 class Account{ // 父类 // 属性 private String actno; private double balance; // 构造方法 // 无参 public Account(){ } // 有参 public Account(String actno,double balance){ this.actno = actno; this.balance = balance; } // getter and setter 方法 实例方法哦 public void setActno(String actno){ this.actno = actno; } public String getActno(){ return actno; } public void setBalance(double balance){ this.balance = balance; } public double getBalance(){ return balance; } } // 其他类型的账户:信用卡账户 // 账号、余额、信誉度 class CreditAccount extends Account{ // 子类 // 属性:信誉度(诚信值) // 子类特有的一个特征,父类没有。 private double credit; // 构造方法 public CreditAccount(){ } // 构造方法 // 分析一下程序是否存在编译错误????? public CreditAccount(String actno,double balance,double credit){ // 私有的属性,只能在本类中访问 /* this.actno = actno; this.balance = balance; */ // super(); // 默认 // 以上两行代码在恰当的位置,正好可以使用:super(actno,balance); // 通过子类的构造方法调用父类的构造方法。 super(actno,balance); this.credit = credit; } // getter and setter 方法 实例方法哦 public void setCredit(double credit){ this.credit = credit; } public double getCredit(){ return credit; } }
案例3内存图:
案例4:
public class SuperTest04{ public static void main(String[] args){ Vip v = new Vip("zhangsan"); v.shopping(); } } class Customer{ String name; public Customer(){} public Customer(String name){ this.name = name; } } class Vip extends Customer{ public Vip(){} public Vip(String name){ super(name); } // super 和 this都不能出现在静态方法中 public void shopping(){ // this表示当前对象 System.out.println(this.name + "正在购物"); // super表示的是当前对象的父类特征。(super是this指向的那个对象中的一块空间。) System.out.println(super.name + "正在购物"); // name其实就是this.name System.out.println(name + "正在购物"); } }
案例4内存图:
案例5:
/* this. 和 super. 大部分情况下都是可以省略的。 this. 什么时候不能省略 public void setName(String name){ this.name = name; } super.什么时候不能省略 如果父类和子类有同名属性,当你想访问父类中的那个属性的时候,那么就必须用到super. */ public class SuperTest05{ public static void main(String[] args){ Vip v = new Vip("zhangsan"); v.shopping(); } } class Customer{ String name; public Customer(){} public Customer(String name){ this.name = name; } } class Vip extends Customer{ // 假设子类也有一个同名属性 // java中允许在子类中出现和父类一样的同名变量/同名属性。 String name; public Vip(){} public Vip(String name){ super(name); // this name = null; } // super 和 this都不能出现在静态方法中 public void shopping(){ // this表示当前对象 System.out.println(this.name + "正在购物"); // super表示的是当前对象的父类特征。(super是this指向的那个对象中的一块空间。) System.out.println(super.name + "正在购物"); // name其实就是this.name System.out.println(name + "正在购物"); } }
案例5内存图:
案例6:
/* 通过这个测试得出的结论: super 不是引用。super也不保存内存地址,super也不指向任何对象。 super 只是代表当前对象内部的那一块父类型的特征。 */ public class SuperTest06{ //实例方法 public void doSome(){ // 输出“引用”的时候,会自动调用引用的toString()方法 // System.out.println(this); // 错误: 需要'.' // System.out.println(super); } // 静态方法 public static void main(String[] args){ SuperTest06 s = new SuperTest06(); // SuperTest06@2ff4acd0 s.doSome(); // main方法一样的 因为他也是静态的。 // System.out.println(this); } // 错误: 无法从静态上下文中引用非静态 变量 this // 错误: 无法从静态上下文中引用非静态 变量 super // 错误: 找不到符号 /* public static void doOther(){ System.out.println(this); System.out.println(super.xxx); } */ }
案例7:
/* 在父和子中有同名的属性,或者说有相同的方法。 如果此时想在子类中访问父中的数据,必须使用“super.”加以区分。 super.属性名 【访问父类中的属性】 super.方法名(实参) 【访问父类中的方法】 super(实参) 【访问父类中的构造方法】 记住一点:私有的只能在本类中访问。 */ public class SuperTest07{ public static void main(String[] args){ Cat c = new Cat(); /* Cat move! Cat move! Animal move! */ c.yiDong(); } } class Animal{ public void move(){ System.out.println("Animal move!"); } } class Cat extends Animal{ // 对move进行重写 public void move(){ System.out.println("Cat move!"); } // 单独编写一个子类特有的方法 public void yiDong(){ this.move(); move(); // super. 不仅可以访问属性,还可以访问方法。 super.move(); } }