一、super关键字的了解,以及和this的比较
(1)super()什么时候使用
//银行账户类
//账户的属性:账号、余额
//父类
class Account{
//属性
private String actno;
private double balance;
//构造方法
public Account(){
}
public Account(String actno, double balance){
this.actno = actno;
this.balance =balance;
}
//setter and getter
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(){
}
//setter and getter方法
public void setCredit(double credit){
this.credit = credit;
}
public double getCredit(){
return credit;
}
}
如果我把上面改成下面:
public CreditAccount(String actno,double balance , double credit){
this.actno = actno;
this.balance = balance;
//以上两个都是父类的私有属性
this.credit = credit;
}
这个时候就会产生报错,因为私有属性是不能在类外进行访问的。
如果我们想要访问了怎么办呢?这个时候就用到了super。
public CreditAccount(String actno,double balance , double credit){
super(actno,balance);
this.credit = credit;
}
(2)super在对象创建的时候起到了什么作用
public class SuperTest
{
public static void main(String [] args){
new B();
};
}
class A
{
public A(){
System.out.println("A类的无参数构造方法");
}
}
class B extends A
{
public B(){
System.out.println("B类的无参数构造方法");
}
}
这时候控制台会输出
所以说,在创建子类的时候都会走一下父类 ,有儿子必须有父亲。其实public B(){}这里面第一行有一个默认的super();
当我们改一下程序
public class SuperTest
{
public static void main(String [] args){
new B();
};
}
class A
{
//public A(){
//System.out.println("A类的无参数构造方法");
//}
public A(int i){
}
}
class B extends A
{
public B(){
System.out.println("B类的无参数构造方法");
}
}
其实这时候
pulic B(){
super();
}
super()它会去调用A无参数的构造方法,但是A中没有无参数的构造方法,只有public A(int i){};所以就会报错了,建议将一个类中无参数构造方法要写出来。
所以结论:(a)即没有this()也没有super(),默认会有一个super(),表示当前通过子类的构造方法调用父类的无参数构造方法,所以必须保证父类的无参数构造方法是存在的。(c)this()和super不能共存,他们都是只能出现在构造方法第一行。
(b)无论怎么折腾,父类中的构造方法一定会执行。
public class SuperTest
{
public static void main(String [] args){
new B();
};
}
class A
{
public A(){
System.out.println("A类的无参数构造方法");
}
public A(int i){
}
}
class B extends A
{
public B(){
this("zhangsan");
//调用父类中有参数的构造方法
System.out.println("B类中无参数构造方法!");
}
public B(String name){
super();
System.out.println("B类中有参数构造方法(String)");
}
}
(3)子类构造方法执行时必然调用父类的构造方法
在java语言中不管是new什么对象,最后object类的无参数构造方法一定会执行(Object类的无参数构造方法是处于"栈顶部")。
二、super的执行原理(super在内存中的体现)
super代表的是当前对象的父类型特征
//银行账户类
//账户的属性:账号、余额
//父类
class Account{
//属性
private String actno;
private double balance;
//构造方法
public Account(){
}
public Account(String actno, double balance){
this.actno = actno;
this.balance =balance;
}
//setter and getter
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(){
}
//setter and getter方法
public void setCredit(double credit){
this.credit = credit;
}
public double getCredit(){
return credit;
}
}
//使用继承机制来解决代码复用问题
public class ExtendTest01{
public static void main(String [] args){
//创建普通账户
Account act = new Account();
act.setActno("11111");
act.setBalance(10000);
System.out.println(act.getActno() + "余额" +act.getBalance());
//创建信用账户
CreditAccount ca = new CreditAccount();
act.setActno("222222");
act.setBalance(-10000);
System.out.println(act.getActno() + "余额" +act.getBalance());
}
}
new CreditAccount它是Account的子类,Account又是Object的子类,所以会调用object,初始化了objtct之后,再初始化Account,然后再初始化CreditAccount,这时候Account的super代表着object的特征,CreditAccount代表这Account的特征,
问题:(1)这个图中一共创建了几个对象?
1个对象。虽然调用构造方法,在调用方法执行过程中一连串调用了父类的构造方法,父类的构造方法又继续向下调用它的父类的构造方法,但是实际上对象只调用了一个。
(2)super(实参)到底是做什么的?
super(实参)的作用是:初始化当前对象的父类型特征
(3)super关键字代表什么?
super关键字代表的就是“当前对象”的那部分父类型特征。
public class SuperTest02
{
public static void (String [] args){
Vip v = new Vip("张三");
v.shopping();
}
}
class Customer
{
String name;
public Customer(){}
public Customer(String name){
this.name = name;
}
}
class Vip
{
public vip(){}
public vip(String name){
super(name);
}
//这个方法不能是静态的,super不能出现在静态方法中。
public void shopping(){
System.out.println(name +"正在购物");
System.out.println(this.name +"正在购物");
System.out.println(super.name +"正在购物");
}
}
我们再把代码改一下:
class Vip
{
//假设子类中也有一个同名的属性
String name;
public vip(){}
public vip(String name){
super(name);
//this.name = null;
}
//这个方法不能是静态的,super不能出现在静态方法中。
public void shopping(){
System.out.println(name +"正在购物");
System.out.println(this.name +"正在购物");
System.out.println(super.name +"正在购物");
}
}
从上图可以看出,java中允许在子类中出现和父类一样的同名变量/同名属性。
(a)super.什么时候不能省略?
如果父类和子类有同名属性,并且在子类中想要方法父类的属性。
(b)java是怎么区分子类和父类的同名属性的?
this.和super.
(c)super不保存内存地址,super也不指向任何对象,super知识代表当前对象的那一块父类型特征
public class SuperTest03
{
public static void main(String [] args){
Dog D1 = new Dog();
D1.test();
}
}
class Animal
{
public void move(){
System.out.println("动物在移动");
}
}
class Dog extends Animal
{
public void move(){
System.out.println("狗在跑");
}
public void test(){
this.move();
move();
super.move();
}
}
(三)总结:super和this的区别
this:
this能出现在实例方法和构造方法中。
this的语法是:"this."、"this()"
this不能使用在静态方法中。
This.大部分情况下是可以省略的。
This.什么时候不能省略呢?在区分局部变量和实例变量的时候不能省略。
Public void setName(String name){
This.name = name;
}
This()只能出现在构造方法第一行,通过当前的构造方法区调用"本类"中其它的构造方法,目的是:代码复用。
Super:
super能出现在实例方法和构造方法中。
super的语法是:"super."、"super()"
super不能使用在静态方法中。
super.大部分情况下是可以省略的。
super.什么时候不能省略呢?在区分父类和子类同名属性
super()只能出现在构造方法第一行,通过当前的构造方法区调用"本类"中其它的构造方法,目的是:代码复用。
目的是:创建子类对象的时候,先初始化父类型特征(创建子类对象的时候,先创建父类对象)