1.第一种用法主要用来在子类中调用父类的同名成员变量或者方法
测试如下:
//
class A{
public String name="孙悟空";
public void testSuper(){
System.out.println("父类");
}
}
public class B extends A{
public String name="猪八戒";
public int age;
public void testSuper() {
System.out.println("子类");
}
public void test(){
System.out.println(name);//调用子类的成员变量
System.out.println(super.name);//调用父类的成员变量
testSuper();//调用子类的方法
super.testSuper();//调用父类的方法
}
public static void main(String[] args) {
B b=new B();
b.test();
}
}
内存分析:
分析任何程序都是从main方法的第一句开始分析的,所以首先分析main方法里面的第一句话:
//
B b=new B();
程序执行到这里时,首先在栈空间里面会产生一个对象地址,通过这个值我们可以找到new出来的b对象。由于子类B是从父类A继承下来的,所以当我们new一个子类对象的时候,这个子类对象里面会包含有一个父类对象,而这个父类对象拥有他自身的属性name。这个name成员变量在A类里面声明的时候初始化为孙悟空。
子类在继承父类name属性的同时,自己也单独定义了一个name属性,所以当我们new出一个子类对象的时候,这个对象会有两个name属性,一个是从父类继承下来的name,另一个是自己的name。在子类里定义的成员变量value在声明时初始化为猪八戒。因此,执行完第一句话以后,系统内存的布局如下图所示:
2.第二种主要用在子类的构造器中显示地调用父类的构造器,要注意的是,如果是用在子类构造器中,则必须是子类构造器的第一个语句。
//
class A{
public String name="孙悟空";
public A(){
}
public A(String name) {
this.name = name;
}
}
public class B extends A{
public String name="猪八戒";
public int age;
public B() {
}
public B(String name, int age) {
super(name); //在构造函数里面使用super调用父类构造器进行初始化,必须是构造函数的第一行代码
this.age = age;
}
public static void main(String[] args) {
B b = new B();
}
}
当new一个对象出来的时候,这个对象会产生一个this的引用,这个this引用指向对象自身。如果new出来的对象是一个子类对象的话,那么这个子类对象里面还会有一个super引用,这个super指向当前对象里面的父对象。所以相当于程序里面有一个this,this指向对象自己,还有一个super,super指向当前对象里面的父对象。
3.super不能在静态方法里面使用,因为静态方法属于类,但是super是属于对象的。super 可以调用的是父类的成员函数(即非静态的)和成员变量(即非静态的),需要调用父类的类函数和类变量则需要用父类名调用.
测试:
//
class A{
public static String name="孙悟空";
public static void testSuper1(){
System.out.println("父类1");
}
public void testSuper3() {
System.out.println("父类2");
}
}
public class B extends A{
public String name="猪八戒";
public int age;
public void testSuper2() {
System.out.println("子类");
super.name; //Not a statement
}
public static void main(String[] args) {
B b=new B();
super.testSuper2();//super' cannot be referenced from a static context
}
}