Java中super的运行原理(super如何在内存中运行的)以及super和this的对比

一、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()只能出现在构造方法第一行,通过当前的构造方法区调用"本类"中其它的构造方法,目的是:代码复用。

目的是:创建子类对象的时候,先初始化父类型特征(创建子类对象的时候,先创建父类对象)

 

猜你喜欢

转载自blog.csdn.net/MyxZxd/article/details/105891967