zoukankan      html  css  js  c++  java
  • Java第七周课堂示例总结

    一、super();调用基类构造方法

    代码:

     1 class Grandparent{
     2     public Grandparent(){
     3         System.out.println("GrandParent Created.");
     4     }
     5     public Grandparent(String string) {
     6         System.out.println("GrandParent Created.String:" + string);
     7      }
     8 }
     9 class Parent2 extends Grandparent
    10 {
    11     public Parent2() {
    12             //super("Hello.Grandparent.");
    13             System.out.println("Parent2 Created");
    14                // super("Hello.Grandparent.");
    15      }
    16 }
    17 class Child2 extends Parent2 {
    18     public Child2() {
    19         System.out.println("Child2 Created");
    20       }
    21 }
    22 public class TestInherits {
    23     public static void main(String args[]){
    24             Child2 c = new Child2();
    25     }
    26 }  

    第一次运行结果:

     第二次:(super语句放在第一句)

     

     第三次运行结果:(super语句放在第二位)报错:super必须放在第一位

    思索:为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来?

    构造函数的作用是完成类的初始化,子类继承了父类的成员方法和成员变量,如果不首先调用,则从父类继承来的成员得不到初始化。

    如果反过来调用,父类不知道子类的变量,并且子类中的部分从父类继承来的变量得不到正确的初始化,故顺序不能改变。

    二、JVM的一种默认实现

    请按照以下步骤进行技术探险:

    (1)使用javap –c命令反汇编ExplorationJDKSource.class;

    (2)阅读字节码指令,弄明白println()那条语句到底调用了什么?

    (3)依据第(2)得到的结论,使用Eclipse打开JDK源码,查看真正被执行的代码是什么

     原因:

    前面示例中,main方法实际上调用的是: public void println(Object x),这一方法内部调用了String类的valueOf方法。 valueOf方法内部又调用Object.toString方法: public String toString() { return getClass().getName() +"@" + Integer.toHexString(hashCode()); } hashCode方法是本地方法,由JVM设计者实现: public native int hashCode();

    三、

     1 public class Fruit{
     2     public String toString()
     3     {
     4         return "Fruit toString.";
     5     }
     6     public static void main(String args[])
     7     {
     8         Fruit f=new Fruit();
     9         System.out.println("f="+f);
    10         System.out.println("f="+f.toString());
    11     }
    12 }

    注意最后两句句,一个字串和一个对象“相加”,得到以下结果:

    原因分析:Fruit类覆盖了Object类的toString方法。在“+”运算中,当任何一个对象与一个String对象,连接时,会隐式地调用其toString()方法,默认情况下,此方法返回“类名 @ + hashCode”。为了返回有意义的信息,子类可以重写toString()方法。

    四、方法覆盖

    (1)覆盖方法的允许访问范围不能小于原方法。

    (2)覆盖方法所抛出的异常不能比原方法更多。

    (3)声明为final方法不允许覆盖。 例如,Object的getClass()方法不能覆盖。

    (4)不能覆盖静态方法。

    请自行编写代码测试以下特性:在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。

     

     运行结果:

     五、多态

    多态性的定义是:同一操作用于不同的类的实例,不同的类将进行不同的解释,最后产生不同的结果。即相同的一条语句,在不同的运行环境中可以产生不同的运行结果。

    多态的最本质特征就是父类(或接口)变量可以引用子类(或实现了接口的类)对象。换句话说:子类对象可以被当成基类对象使用!

    特别地,Java类库的最顶层类是Object。因此每个对象都可以赋值给Object变量。

    子类对象可以直接赋给基类变量。 基类对象要赋给子类对象变量,必须执行类型转换, 其语法是: 子类对象变量=(子类名)基类对象名;

    也不能乱转换。如果类型转换失败Java会抛出以下这种异常: ClassCastException

    例子:

     1 public class TestInstanceof
     2 {
     3     public static void main(String[] args) 
     4     {
     5         //可以使用instanceof运算符判断一个对象是否可以转换为指定的类型:
     6         //声明hello时使用Object类,则hello的编译类型是Object,Object是所有类的父类
     7         //但hello变量的实际类型是String
     8         Object hello = "Hello";
     9         //String是Object类的子类,所以返回true。
    10         System.out.println("字符串是否是Object类的实例:" + (hello instanceof Object));
    11         //返回true。
    12         System.out.println("字符串是否是String类的实例:" + (hello instanceof String));
    13         //返回false。
    14         System.out.println("字符串是否是Math类的实例:" + (hello instanceof Math));
    15         //String实现了Comparable接口,所以返回true。
    16         System.out.println("字符串是否是Comparable接口的实例:" + (hello instanceof Comparable));
    17         String a = "Hello";
    18         //String类既不是Math类,也不是Math类的父类,所以下面代码编译无法通过
    19         //System.out.println("字符串是否是Math类的实例:" + (a instanceof Math));
    20     }
    21 }

    运行结果:

     

     六、“类型转换”知识点考核

    下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么? 

     1 class Mammal{}
     2 class Dog extends Mammal {}
     3 class Cat extends Mammal{}
     4 public class TestCast
     5 {
     6     public static void main(String args[])
     7     {
     8         Mammal m;
     9         Dog d=new Dog();
    10         Cat c=new Cat();
    11         m=d;
    12         //d=m;
    13         d=(Dog)m;
    14         //d=c;
    15         //c=(Cat)m;
    16     }
    17 }

     解答:注释的三个语句皆会出现编译错误问题

    12、14行为同一父类的子类对象不能相互转换,15行则是因为m对象之前已经被强转,所以不能再次转换。

    七、子类和父类定义了一模一样的字段和方法

     1 public class ParentChildTest {
     2     public static void main(String[] args) {
     3         Parent parent=new Parent();
     4         parent.printValue();
     5         Child child=new Child();
     6         child.printValue();
     7         
     8         parent=child;
     9         parent.printValue();
    10         
    11         parent.myValue++;
    12         parent.printValue();
    13         
    14         ((Child)parent).myValue++;
    15         parent.printValue();
    16     }
    17 }
    18 class Parent{
    19     public int myValue=100;
    20     public void printValue() {
    21         System.out.println("Parent.printValue(),myValue="+myValue);
    22     }
    23 }
    24 class Child extends Parent{
    25     public int myValue=200;
    26     public void printValue() {
    27         System.out.println("Child.printValue(),myValue="+myValue);
    28     }
    29 }

    运行结果:

     回答问题:

    1. 左边的程序运行结果是什么? 2. 你如何解释会得到这样的输出? 3. 计算机是不会出错的,之所以得到这样的运行结果也是有原因的, 那么从这些运行结果中,你能总结出Java的哪些语法特性?

    总结:

    当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。 这个特性实际上就是面向对象“多态”特性的具体表现。

    如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。 如果子类被当作父类使用,则通过子类访问的字段是父类的! 牢记:在实际开发中,要避免在子类中定义与父类同名 的字段。不要自找麻烦!——但考试除外,考试 中出这种题还是可以的。

  • 相关阅读:
    42 最大子数组Ⅱ
    笔试之const问题
    笔试中sizeof求字节数的问题
    40 用栈实现队列
    38 搜索二维矩阵Ⅱ
    25.Remove Nth Node From End of List(删除链表的倒数第n个节点)
    29.最小的K个数
    28.数组中出现次数超过一半的数字
    27.字符串的排列
    26.二叉搜索树与双向链表
  • 原文地址:https://www.cnblogs.com/dongao/p/11730316.html
Copyright © 2011-2022 走看看