黑马程序员技术交流社区

标题: super的解释 [打印本页]

作者: yanghu    时间: 2014-4-18 19:02
标题: super的解释

我知道super是指向父类,我想问super这个引用是怎么来的?父类没有初始化,怎么会有super这个地址引用?

作者: sanguodouble1    时间: 2014-4-18 19:11
本帖最后由 sanguodouble1 于 2014-4-18 19:14 编辑

你好,如果你实例化了一个子类的话,父类是被默认初始化的,
也就是说,子类内部是包含所有父类资料的

补充一下,这个原理是这样的:
子类构造方法的一个句就是调用父类构造方法,如果子类没有主动调用,
那么编译器就自动调用父类无参的构造方法,如果子类没有调用,父类又没有无参构造方法,那么肯定报错。
不信你试试

作者: yanzhendong    时间: 2014-4-18 19:11
子类的构造函数第一句默认是super(),也就是说子类在初始化自己的时候先初始化父类,等父类初始化完毕后再初始化自己
作者: 月光海    时间: 2014-4-18 19:23
java中的super和this有类似的理解,但是不同的,就是继承时需要初始化父类,层层迭代,由祖宗开始初始化。
package com.cbh.this_test;
class Super_father
{
int i;
String father=”我是第一个爸爸”;
Super_father(int x)
{
i=x;
System.out.println(“我是i=”+i);
}
Super_father()
{
System.out.println(father+”,”+”而且是无参构造”);
}
}
class father1 extends Super_father
{
int i;
String father=”我是第二个爸爸”;
father1(int x)
{
i=x;
System.out.println(“我是J=”+i);
}
father1()
{
System.out.println(father+”,”+”而且是无参构造”);
}
}
public class Super_test extends father1
{
int s=10;
String son=”I’m a son”;
Super_test()
{
super(10);//调用父类的有参构造方法
//  super(); //
super(s);//不能使用两次,和this一样
System.out.println(super.father);
}
Super_test(int k)
{
super(k);
}
public static void main(String[] args)
{
new Super_test();
new Super_test(5);
}
}
//继承时,需要初始化父类,父类需要再继承爷爷类,那么也需要初始化爷爷类,如此下去。如果没有调用特定的构造方法,就默认调用无参构造。反正就是需要初始化。
//从字面上理解,super指的是超类,所谓超类可以简单点理解为,超出本类,所以需要一个前提,就是必须有类给它超,所以它需要一个直接父类,当然,父类可以有爷爷类,用的时候,知道要初始化就行了。
希望能帮到你
作者: 孙旌棋    时间: 2014-4-20 16:52
本帖最后由 孙旌棋 于 2014-4-20 16:53 编辑

首先, 子类实例化的过程中其实第一句就是你super(), 如果你不写, 则由虚拟机为你加载
如果父类的构造函数中有参数, 那么自类实例化的时候, 需要指定的哦, 详细的请看代码中的注释
  1. class Father {
  2.         int num;
  3.         private String name;
  4.         private int age;

  5.         Father() {
  6.                 num = 1;
  7.                 System.out.println("孙旌棋");
  8.         }

  9.         Father(int x) {
  10.                 System.out.println(x);
  11.         }

  12.         Father(String name, int age) {
  13.                 this.name = name;
  14.                 this.age = age;
  15.                 System.out.println(name + "        " + age);
  16.         }
  17. }

  18. class Son extends Father {

  19.         Son() {
  20.                 // super(); 第一行有默认的隐式语句super(),由虚拟机加载
  21.                 System.out.println("孙旌棋,863523704");
  22.         }

  23.         Son(int x) {
  24.                 // this(); 当子类中有一个构造函数访问父类的构造函数时,可以用this(); super(2);//
  25.                 // 有参数时需要手动定义super(),语句来指定
  26.                 System.out.println(x);
  27.         }

  28.         Son(String name, int age) {
  29.                 super(name, age);// 父类已实现,子类可以直接拿来用
  30.         }
  31. }
复制代码



作者: 左拉    时间: 2014-4-20 19:32
本帖最后由 左拉 于 2014-4-20 19:42 编辑

通过用static来定义方法或成员,为我们编程提供了某种便利,从某种程度上可以说它类似于C语言中的全局函数和全局变量。但是,并不是说有了这种便利,你便可以随处使用,如果那样的话,你便需要认真考虑一下自己是否在用面向对象的思想编程,自己的程序是否是面向对象的。
好了,现在开始讨论this&super这两个关键字的意义和用法。
在Java中,this通常指当前对象,super则指父类的。当你想要引用当前对象的某种东西,比如当前对象的某个方法,或当前对象的某个成员,你便可以利用this来实现这个目的,当然,this的另一个用途是调用当前对象的另一个构造函数,这些马上就要讨论。如果你想引用父类的某种东西,则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某种关系,所以我们在这一块儿来讨论,希望能帮助你区分和掌握它们两个。
在一般方法中
最普遍的情况就是,在你的方法中的某个形参名与当前对象的某个成员有相同的名字,这时为了不至于混淆,你便需要明确使用this关键字来指明你要使用某个成员,使用方法是“this.成员名”,而不带this的那个便是形参。另外,还可以用“this.方法名”来引用当前对象的某个方法,但这时this就不是必须的了,你可以直接用方法名来访问那个方法,编译器会知道你要调用的是那一个。
  1. public class DemoThis{
  2. private String name;
  3. private int age;
  4. DemoThis(String name,int age){
  5. setName(name);
  6. //你可以加上this来调用方法,像这样:this.setName(name);但这并不是必须的
  7. setAge(age);
  8. this.print(); }
  9. public void setName(String name){
  10. this.name=name;//此处必须指明你要引用成员变量
  11. }
  12. public void etAge(int age){
  13. this.age=age;
  14. }
  15. public void print(){
  16. System.out.println("Name="+name+" ge="+age);
  17. //在此行中并不需要用this,因为没有会导致混淆的东西
  18. }
  19. public static void main(String[] args){
  20. DemoThis dt=new DemoThis("Kevin","22");
  21. 这段代码很简单,不用解释你也应该能看明白。在构造函数中你看到用this.print(),你完全可以用print()来代替它,两者效果一样。下面我们修改这个程序,来演示super的用法。
  22. class Person{
  23. public int c;
  24. private String name;
  25. private int age;
  26. protected void setName(String name){
  27. this.name=name;
  28. }
  29. protected void setAge(int age){
  30. this.age=age;
  31. }
  32. protected void print(){
  33. System.out.println("Name="+name+" Age="+age);
  34. }
  35. }
  36. public class DemoSuper extends Person{
  37. public void print(){
  38. System.out.println("DemoSuper:");
  39. super.print();
  40. }
  41. public static void main(String[] args){
  42. DemoSuper ds=new DemoSuper();
  43. ds.setName("kevin");
  44. ds.setAge(22);
  45. ds.print();
  46. }
  47. }
复制代码

在DemoSuper中,重新定义的print方法覆写了父类的print方法,它首先做一些自己的事情,然后调用父类的那个被覆写了的方法。输出结果说明了这一点:
DemoSuper:
Name=kevin Age=22

这样的使用方法是比较常用的。另外如果父类的成员可以被子类访问,那你可以像使用this一样使用它,用“super.父类中的成员名”的方式,但常常你并不是这样来访问父类中的成员名的。
在构造函数中构造函数是一种特殊的方法,在对象初始化的时候自动调用。在构造函数中,this和super也有上面说的种种使用方式,并且它还有特殊的地方,请看下面的例子:
  1. class Person{
  2. public static void prt(String s) {
  3. System.out.println(s);
  4. }
  5. public Person(){
  6. prt("A Person.");
  7. }
  8. public Person(String name){
  9. prt(name);
  10. }
  11. }

  12. public class Chinese extends Person {
  13. Chinese() {
  14. super(); // 调用父类构造函数(1)
  15. prt("A chinese.");// (4)
  16. }
  17. Chinese(String name) {
  18. super(name);// 调用父类具有相同形参的构造函数(2)
  19. prt("his name is:" + name);
  20. }
  21. Chinese(String name, int age) {
  22. this(name);// 调用当前具有相同形参的构造函数(3)
  23. prt("his age is:" + age);
  24. }
  25. public static void main(String[] args) {
  26. Chinese cn = new Chinese();
  27. cn = new Chinese("kevin");
  28. cn = new Chinese("kevin", 22);
  29. }
复制代码


在这段程序中,this和super不再是像以前那样用“.”连接一个方法或成员,而是直接在其后跟
上适当的参数,因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同形式的
构造函数,如1和2处。this后加参数则调用的是当前具有相同参数的构造函数,如3处。当然,在
Chinese的各个重载构造函数中,this和super在一般方法中的各种用法也仍可使用,比如4处,你
可以将它替换为“this.prt”(因为它继承了父类中的那个方法)或者是“super.prt”(因为它
是父类中的方法且可被子类访问),它照样可以正确运行。但这样似乎就有点画蛇添足的味道
了。


作者: 菠萝包丶    时间: 2014-4-20 19:33
本帖最后由 菠萝包丶 于 2014-4-20 19:37 编辑

当对子类的对象进行初始化时,父类的构造函数也会运行!
那是因为子类的构造函数默认第一行有一条隐式的语句super()
super():会访问父类中空参数的的构造函数,而且子类中所有的构造函数默认第一行都是super()

  1. zi()
  2. {
  3.        //super();
  4. }
复制代码

由于父类中的数据子类可以直接获取,所以子类对象建立时,需要先查看父类是如何对这些数据进行初始化的
所以子类在对象初始化时,要先访问一下父类中的构造函数。







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2