随笔-159  评论-114  文章-7  trackbacks-0

面向对象三大基石:封装,继承,多态。面试会问到。

Overriding  覆盖  只存在于父子类之间,一定。

什么时候才是覆盖呢?

class Father{
   public void run(){
   }
}

class Son extends Father{
   public void run(int a){
   }
}

注意:这是方法的重载,不是覆盖!只是这个重载发生在父子类之间。

覆盖是,子类参数列表与返回值都与父类相同,并且子类在覆盖父类方法时,不能给出更严格的访问控制,并且子类方法例外的类型是等于父子方法抛出的异常类型,或者是其子类型。

The exceptions thrown by an overriding method must be equal to or a subset of the exceptions thrown by the overridden method.

注意构造方法根本不能继承,所以不存在覆盖的问题。

访问控制

private 本类内部可见

default 同类同包

protected 同包+不同包子类

要构造一个对象,先构造父类对象,再构造子类对象

构造一个对象的执行过程。

1.递归的构造父类对象-----------〉也就是说父类本身也要走这样的步骤。
2.顺序调用成员属性赋初值语句
3.调用本类构造方法

后来课程领悟,类加载与构造对象是两回事,类加载过程,1.static静态成员加载,2运行static一次,静态代码块,3如果有静态内部类,赋值,对静态内部类的赋值是指编译产生的Employee$SomeInner.class文件的读取。

如果类有静态变量或者静态块,而且用到时(static初始化只有在必要的时候才会进行,那么就会在第一步之前执行一遍,先静态变量,然后静态块,以后再怎么new都不会执行,回到创建父类开始。

======〉引用Think In Java

在这里有必要总结一下对象的创建过程。请考虑一个名为Dog的类:
(1) 类型为Dog的一个对象首次创建时,或者Dog类的static方法/static字段首次访问时,Java解释器必须找到Dog.class(在事先设好的类路径里搜索)。
(2) 找到Dog.class后(它会创建一个Class对象,这将在后面学到),它的所有static初始化模块都会运行。因此,static初始化仅发生一次——在Class对象首次载入的时候。
(3) 创建一个new Dog()时,Dog对象的构建进程首先会在内存堆(Heap)里为一个Dog对象分配足够多的存储空间。
(4) 这种存储空间会清为零,将Dog中的所有基本类型设为它们的默认值(零用于数字,以及boolean和char的等价设定)。
(5) 进行字段定义时发生的所有初始化都会执行。
(6) 执行构建器。正如第6章将要讲到的那样,这实际可能要求进行相当多的操作,特别是在涉及继承的时候。

=====================

多态-1.编译时多态      方法重载
         2.运行时多态      一个对象可能会具有多个类型

对象是客观的。

人类对对象的认识是主观的

当人看到一个不能识别的,有生命的,区别人的东西时,会类来认识该事物。

也就是Animal a = new Dog();子类对象可以使用父类对象来引用。

Animal被称为编译时类型,而a真正的对象类型是运行时类型。

3个原则:

1.对象不变(运行时类型不变)(客观的肯定不会改变)
2.只能调用编译时类型的方法,方法调用时,检查编译时类型内部是否定义了该方法。
   也就是说,在你以一个一个动物来看待一只狗时,你是不会知道它有散步的方法的。
3.RTTI,运行时,动态类型判定(看运行时类型),子类覆盖了(Overriding)父类方法,那么调用运行时类型对象的方法。

a instanceof 类名(编译时类型)
a为对象变量
判断a是否被声明为后面类的对象。
用在强制类型转换之前。如果转换错了,java.lang.ClassCastException 运行时例外

记住,方法只有覆盖时,调用寻找运行时类型。而Overloading ->编译时多态->看编译时类型。

属性,重载阿,都要看编译时类型。

package com.ljl;

public class TestClass {
    
public void print(B b){
        System.out.println(
"is B");        
    }

    
//    public void print(A a){
//        System.out.println("is A");
//    }
    
    
public static void main(String[] args)
    
{
        TestClass tc 
= new TestClass();
        A a 
= new B();
        tc.print(a);
    }

}


class A{}

class B extends A{}

为什么子类覆盖父类方法时,访问控制符只能更宽泛。因为如果父类方法为public,子类方法为private,那么多态时,察看父类方法可以调用(可调用编译时类型所定义的方法),而动态类型判断时,调用子类方法,发现为private,完蛋了。





posted on 2005-11-29 21:37 北国狼人的BloG 阅读(392) 评论(0)  编辑  收藏 所属分类: 达内学习总结

只有注册用户登录后才能发表评论。


网站导航: