super关键字

主要是由Hadoop中的函数想到的,以前对super不太明白,写了几段代码搞懂了。
@Override
protected void setup(Context context) throws IOException,
    InterruptedException {
    super.setup(context);
}

(1)子类的构造函数如果要引用super的话,必须把super放在函数的首位.
class Base {
    Base() {
       System.out.println("Base");
    }
}
 
public class Child extends Base {
     Child() {
       super();//调用父类的构造方法,一定要放在方法的首个语句
       System.out.println("Child");
    }
 
    public static void main(String argv[]) {
        Child c = new  Child();
    }
}

如果想用super继承父类构造的方法,但是没有放在第一行的话,那么在super之前的语句,肯定是为了满足自己想要完成某些行为的语句,但是又用了super继承父类的构造方法。那么以前所做的修改就都回到以前了,就是说又成了父类的构造方法了。
在Eclipse中,如果不放在首位,报错:Constructor call must be the first statement in a constructor。
不用显示调用,也可以。我估计是,如果构造函数有多个的时候,可以显示指明哪一个。

(2)在Java中,有时还会遇到子类中的成员变量或方法与超类(有时也称父类)中的成员变量或方法同名。因为子类中的成员变量或方法名优先级高,所以子类中的同名成员变量或方法就隐藏了超类的成员变量或方法,但是我们如果想要使用超类中的这个成员变量或方法,就需要用到super.
class Country {
    String name="China";
//    private String name="China";//不能定义为私有成员变量,否则在子类中就不能玩耍了
 
    String value(String name) {
     this.name = name;
     return this.name;
    }
}
 
class City extends Country {
    String name = "Shijiazhuang";
    String value(String name) {
     System.out.println(super.name);
     super.value("Fail");
     System.out.println(name);
     System.out.println(super.name);
     return name;
   }
 
    public static void main(String[] args) {
       City c=new City();
       c.value("Sucess");
    }
}

super关键和this作用类似,是被屏蔽的成员变量或者成员方法或变为可见,或者说用来引用被屏蔽的成员变量和成员成员方法。
不过super是用在子类中,目的是访问直接父类中被屏蔽的成员,注意是直接父类(就是类之上最近的超类)。下面是一个综合运用super的例子,有两个类:一个Father类,一个Father类的子类Son,通过这两个类完全演示了super的用法,一下是代码:

 
package org.leizhimin;
public class Father {
 public String v="Father";
 public String x="输出了Father类的public成员变量x!!!";
 
 public Father() {
  System.out.println("Father构造方法被调用!");
 }
 
 public Father(String v){
  this.v="Father类的带参数构造方法!运行了.";
 }
 public void outinfo(){
  System.out.println("Father的outinfo方法被调用");
 } 
 public static void main(String[] args) {
  // TODO 自动生成方法存根
 }
}
 
package org.leizhimin;
public class Son extends Father{
 public String v="Son";
 
 public Son() {
  super();      //调用超类的构造方法,只能放到第一行.
  System.out.println("Son无参数构造方法被调用!");
  //super();      //错误的,必须放到构造方法体的最前面.
 } 
 
 public Son(String str){
  super(str);
  System.out.println("Son带参数构造方法被调用!");
 }
 //覆盖了超类成员方法outinfo()
 public void outinfo(){ 
  System.out.println("Son的outinfo()方法被调用");
 } 
 
 public void test(){
  
  String v="哈哈哈哈!";   //局部变量v覆盖了成员变量v和超类变量v
  
  System.out.println("------1-----");
  System.out.println(v);   //输出局部变量v
  System.out.println(this.v);  //输出(子类)成员变量v
  System.out.println(super.v); //输出超类成员变量v 
  
  System.out.println("------2-----");
  System.out.println(x);   //输出超类成员变量v,子类继承而来
  System.out.println(super.x); //输出超类成员变量v
  
  System.out.println("------3-----");
  outinfo();   //调用子类的outinfo()方法
  this.outinfo();  //调用子类的outinfo()方法
  super.outinfo(); //调用父类的outinfo()方法
 } 
 
 public static void main(String[] args) {
  new Son().test();
  
 }
}
 
子类Son运行结果:
 
Father构造方法被调用!
Son无参数构造方法被调用!
------1-----
哈哈哈哈!
Son
Father
------2-----
输出了Father类的public成员变量x!!!
输出了Father类的public成员变量x!!!
------3-----
Son的outinfo()方法被调用
Son的outinfo()方法被调用
Father的outinfo方法被调用
 
        说明:次例子仅仅为了说明super的用法,实际在设计类的时候一般都尽可能私有(private)化。
 
        通过上面的例子,下面总结一下super的用法:
        第一、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,参数不是必须的。同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。
        第二、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,用“super.成员变量名”来引用父类成员变量。当然,如果父类的成员变量没有被覆盖,也可以用“super.成员变量名”来引用父类成员变量,不过这是不必要的。
        第三、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有完全相同的方法定义(但方法体可以不同),此时,用“super.方法名(参数列表)”的方式访问父类的方法。




构造方法中的super关键字

在Java子类的构造方法中可以通过super关键字来调用父类的构造方法。其用法为:
1) super(); 访问父类中的无参构造函数
2) super (paras…); 访问父类中的成员函数yyy
super()来调用父类无参的构造方法,但即使不使用super(),默认也会调用父类无参的构造方法。父类无参的构造方法可以是自定义的无参构造方法,也可以是编译器自动生成的默认构造方法。但如果父类中定义了有参的构造方法,但没有定义无参的构造方法,这时编译器不会生成默认构造函数,也就不能通过super()来调用构造方法。此外,如果父类中定义了private的无参构造方法,也不同通过super()来调用。
super(paras…);用来调用父类中某个有参的构造方法。
super调用父类的构造方法,必须放在子类构造方法的第一行中执行。如果调用的有参的父类构造方法,在super的参数中不能用子类中的非static成员变量(可以使用static成员变量,因为static成员变量在构造方法执行前就已经初始化),也不能使用this或super的相关调用。例如super(super.getClass().getName());
在构造方法中也可以使用super关键字来访问父类中的成员变量和成员函数。其用法和非构造方法中的super关键字用法相同。

非构造方法中的super关键字

在Java子类中可以通过通过super关键字来调用父类中的成员变量和方法。其用法是。
1) super.xxx; 访问父类中的成员变量xxx
2) super.yyy(paras…); 访问父类中的成员函数yyy
super关键字访问父类的成员变量和成员函数时不能越过访问权限的控制,不能访问父类中private的成员变量和方法。例如:

class a {
    private int mNum = 0;
}
class b extends a {
    public void setNum(int i) {
        super.mNum = i;     //错误,不能访问父类的private成员
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在有多层的继承关系时,super调用只能自身父类的成员变量和方法,不能越过父类直接调用父类的父类中的成员变量或方法。当然如果父类的父类中的成员变量或方法被父类继承,那么是可以通过super来调用该成员变量和方法的,但这时实际调用的是父类中的成员变量和方法。例如:

class a {
    protected int mNum = 0;
    public void setNum(int i) {
        mNum = i;
    }
}
class b extends a {
    public void setNum(int i) {
        mNum = i * i;
    }
}
class c extends b {
    public void setNum(int i) {
        super.setNum(i);        //调用的是b中的setNum()方法
        super.super.setNum(i);  //错误,不支持的用法
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
class a {
    protected int mNum = 0;
    public void setNum(int i) {
        mNum = i;
    }
}
class b extends a {
}
class c extends b {
    public void setNum(int i) {
        super.setNum(i);    //正确,虽然b中没有实现setNum(),但b中继承了a的setNum()函数,
                            //c中调用super.setNum()调用的是b的setNum()函数,可以执行。
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值