- 动手实验
因为子类继承于父类,构造方法相当于对象初始化,只有父类先完成初始化,子类对象才能执行自己的初始化。子类在进行初始化的时候会默认调用父类的构造,所以不能反过来。
2 动手动脑
代码:
1 package Parent_son; 2 class Parent 3 { 4 public int value=100; 5 6 public void Introduce() 7 { 8 9 System.out.println("I‘m father"); 10 11 } 12 } 13 class Son extends Parent 14 { 15 16 public int value=101; 17 18 public void Introduce() 19 { 20 super.Introduce(); 21 System.out.println("I‘m Parent"+ super.value); 22 System.out.println("I‘m son"); 23 } 24 } 25 public class JiCheng1 { 26 27 public static void main(String[] args) { 28 Son p=new Son(); 29 p.Introduce(); 30 System.out.println(p.value); 31 32 } 33 }
结果截图:
3.子类与父类间的类型转换
d=m,d=c,c=(Cat)m不能运行
m=d,子类对象可以直接赋给基类变量,因为子类是对父类的一个改动,有父类里的所有的变量。
1.
如果父类对象与引用指向的实际是一个子类对象,那么调用这个方法时,可以使用子类对象作为实际参数。
2.
类型转换必须在继承层次类转换,即超类与子类间。d=m因为父类里面不一定包含全部子类所有的变量,基类对象要赋给子类对象变量,必须执行类型转换,如d=(Dog)m所示。
3.
d=c兄弟类间不存在继承,因此也不存在类型转换。
4.
对象的赋值是地址标识的传递,即两个对象名共同使用同一段内存地址。
5.
c=(Cat)m中不显示错误,会抛出异常,相当于“子=(子)父”如果父类变量引用的是正确的子类型(即父类对象要想类型转换后赋给子类对象,其本身引用的是子类型的内存空间),赋值将执行,如果父类变量引用的是不相关的子类型,将会生成class CastException异常。
4. 同名函数的处理
- 上面的程序运行结果是什么?
2. 你如何解释会得到这样的输出?
子类对象可以赋值给父类,子类可以覆盖父类,但是父类中的变量的值是不会变化的,访问父类中的变量中的变量时,可以用super关键词来访问。parent.printValue()的方法实际会调用child.printValue()方法(因为此时的parent引用child),即引用对象后,调用。parent.printValue()即引用对象将原来父类的方法在child子类中重写了,父类被覆盖时,如果子类被当做父类使用,则通过子类访问的字段是父类的!对父类中的变量进行操作时,parent.myValue++,父类中的变量改变,子类的属性不变,因为此时仍然使用的是子类的方法,所以输出子类的属性。
((Child)parent).myValue++;
将parent强制转换为Child类型,所以操作属性为子类的,所以输出结果为:201
3 计算机是不会出错的,之所以得到这样的运行结果也是有原因的,那么从这些运行结果中,你能总结出Java的哪些语法特性?
当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。如果子类与父类具有相同的字段,则,子类中的字段会代替会隐藏父类的字段,子类方法中访问的是子类的字段(而非父类中的字段)。如果子类方法确实相访问父类中被隐藏的同名字段,可以用super关键词来访问。
父类的引用可以调用父类中定义所有属性与方法,对于子类中定义而父类中没有的属性与方法,父类引用无法调用。子类重定义父类已有的属性,父类引用的还是本类的属性值。子类重定义父类已有方法时,父类引用调用的是子类重写过的方法。
而父类赋值给子类必须经过子类强制转换,此时的对象已是子类对象,对象操作的属性,方法是子类的。
5.接口
能否把“会游泳”、“能被吃”这种特性独立出来作为一种“可选项”,可以被“附加”到具体对象上?
在面向对象世界中,可以使用“接口(interface)”来抽象对象的行为特性。定义一个接口,采用关键字interface,实现一个接口,采用关键字implements接口的成员函数自动成为public的,数据成员自动成为 static和final的。如果接口不声明为public的,则自动变为package。
一个类可以同时实现多个接口。
可以通过继承接口来扩充已有接口,并形成一个新的接口。
interface OneInterface {
void f1();
}
interface TwoInterface extends OneInterface {
void f2();
}
实现子接口的类,必须实现“父”“子”接口所定义的所有方法,才能被实例化(即new出一个对象),接口也可定义常量,
public interface ArrayBound {
public static final int LOWBOUND=1;
public static final int UPBOUND=100;
}
只要一个类声明实现了这个接口,就可以直接使用这些常量名。
注意:定义在接口中的常量必须被初始化。
实例:
1 package 测试1; 2 interface Food 3 { 4 public void Cook(); 5 } 6 interface Swim 7 { 8 public void swim(); 9 } 10 class Bird 11 { 12 public void show() { 13 System.out.println("Duck is a bird"); 14 } 15 } 16 class Duck extends Bird implements Swim,Food 17 { 18 public void Cook() { 19 System.out.println("Duck can be cooked"); 20 } 21 public void swim() { 22 System.out.println("Duck can swim"); 23 24 } 25 } 26 public class Anaimal { 27 public static void main(String[] args) { 28 Food f = new Duck();//接口类型 接口类型的变量=new 实现了接口的具体类型() 29 Swim s=new Duck(); 30 s.swim(); 31 f.Cook(); 32 33 } 34 35 }
结果截图: