面向对象 上和中 要记住的

通过对象调用的方法,在方法调用过程中,会把调用方法的对象的首地址传给被调用的方法,
以this存储,this因为存储了调用该方法的对象的首地址,所以被称为“当前对象”。 

什么是封装

狭义的封装:通过权限修饰符来限定某些类和某些成员的可见性范围。

继承的目的
(1)代码的复用和扩展
(2)表示事物之间的is-a关系

Java父类中所有的成员变量、成员方法都会继承到子类中,但是因为权限修饰符的限制,
①在父类中由private声明的成员,在子类中不允许直接使用。
②如果子类跨包的,在父类中成员的权限修饰符缺省的,在子类中也不允许直接使用。

如果某个类没有通过extends指明它的父类是谁,那么这个类的直接父类默认就是
java.lang.Object类,或者换句话,Object类是所有类的根父类。

方法的重写

方法的重载(Overload):在同一个类中或父子类中,出现方法名相同,形参列表不同的两个或多个方法,是方法重载,和返回值类型等无关。
方法的重写(Override):子类继承了父类的某个方法之后,如果认为该方法的方法体不适用于子类,那么子类可以选择对方法体进行重写。

 重写时要求:
    (1)方法名保持不变
    (2)形参列表保持不变(形参的类型和个数不变,形参名无所谓)
    (3)返回值类型:
        A:基本数据类型和void,必须保持不变
        B:引用数据类型,可以保持不变,或 < 父类被重写方法的返回值类型
    (4)权限修饰符:
        A:子类要重写父类的方法,该方法的权限修饰符不能是private,跨包不能是缺省,即要求在子类是可见的方法
        B:子类重写时,权限修饰符只能是>=的关系。
    (5)其他要求:后面再补充

如果子类重写了父类的方法,在子类中又想要调用父类被重写方法,可以使用super.被重写方法。

toString方法非常特殊
(1)当我们用System.out.println或print方法打印一个对象时,
会自动调用这个对象的toString()

(2)当对象与字符串进行拼接时,
也会自动调用这个对象的toString()

(3)除此之外的其他使用,需要手动调用toString

多态

1、什么是多态?
多态:多种形态,多种类型的形式

两个角度:
(1)一个父类的变量,可以赋值给它各种子类的对象
换句话说,一个父类的变量,可以在运行时体现为多种不同的子类对象
==> 编译时都是父类类型的变量,运行时是各种子类的对象类型

(2)一个子类对象,可以赋值给不同类型的父类变量,
在编译时,编译器识别的类型也不同,可以用.访问的成员也不同。
==> 运行时是同一个子类的类型,但是编译时却呈现为不同的父类类型。

多态引用的概念和表现

2、多态引用的概念?
当父类的变量指向子类的对象时,就叫做多态引用。
    父类类型 变量名 = 子类的对象;

3、多态引用后的表现:
    编译时类型和运行时类型不一致。
编译时:看左边,是父类类型
运行时:看右边,是子类类型

编译时如果按父类类型处理的话,那么只能访问父类中声明的成员,不能访问子类“扩展”的成员。

运行时是按照实际类型处理的,看new对象的类型,如果是子类的话,并且调用方法时,
那么一定执行子类重写的方法体。如果子类没有重写,仍然执行父类中的方法体。

4、多态的弊端和好处:
(1)编译时,只能调用父类声明的方法,不能调用子类扩展的方法
(2)实现方法的动态绑定
   运行时,看“子类”,如果子类重写了方法,一定是执行子类重写的方法体;变量引用的子类对象不同,执行的方法就不同,实现动态绑定。代码编写更灵活、功能更强大,可维护性和扩展性更好了。
   当然,如果子类没有重写该方法,那么仍然执行从父类继承的方法。

向上转型和向下转型(*****)

总则:向上转型和向下转型都是针对编译器来说的,对象的运行时类型从头到尾都不会发生改变。

ClassCastException异常
当对象的运行时类型(真实的类型,new的类型) <= 接收的变量的类型,赋值可以成功,
不满足<=的关系,运行时就会发生ClassCastException异常。

如何避免这个异常呢?
if(变量 instanceof 类型A)条件满足,再把这个变量向下转为这个类型
这个instanceof的作用是判断某个变量中的对象的运行时类型(new)是否<=类型A,成立,就返回true

虚方法(*****)

1、虚方法:可以被子类重写的方法称为虚方法。
2、当我们通过“对象.虚方法”的格式调用一个方法时,要注意如下的原则:
(1)先看这个对象的“编译时类型”是什么,先从编译时类型(或其父类)中寻找匹配的方法
匹配:
A:方法名相同
B:实参列表要么和形参列表完全一致,要么可以兼容
    以实参的“编译时类型”与形参的类型匹配

如果可以找到匹配的方法,编译通过,否则就编译报错。

(2)运行时,在看这个对象的“运行时类型new”是什么,看运行时类型是否重写了刚刚匹配的方法,
如果有重写,就一定执行重写的方法体,
如果没有重写,依然执行刚刚匹配的方法。

3、如果调用的方法不是虚方法(例如,后面会学习的静态方法等不能被子类重写的方法)
或通过 “super.方法”格式发起的方法调用,不适用于上面的规则。

xx.成员变量访问只看xx的编译时类型(面试题)

当多态引用时,通过xx.成员变量方式访问成员变量,此时只看xx的编译时类型。

根父类(*****)

1、如何理解根父类是Object这句话?
(1)所有类都直接或间接的继承Object(字面解释)
(2)Object类型的变量,可以接收任意类型的对象
(3)Object类型的数组,可以任意类型的元素
(4)规定Object[]类型的数组,可以接收任意的对象数组
(5)规定Object[]类型的数组,不可以接收元素是基本数据类型的一维数组
(6)Object类的所有方法(一共11个),在任意类型的对象中都可以找到。

构造器(*****)

1、什么是构造器?它的作用是什么?
构造器的作用是创建对象,并且为对象的实例变量初始化。
2、构造器的特点
(1)构造器的名字必须和类名完全一致,包括大小写。
(2)构造器没有返回值类型,一旦写了返回值类型,它就变成普通方法了。
(3)构造器的修饰符只允许有public,protected,缺省,private四个之一
(4)所有类都有构造器,
如果没有编写构造器,编译器会给你自动加一个默认的无参构造。这里默认的意思是,权限修饰符和class前面默认一致。
(5)程序员也可以手动编写构造器,
一旦我们编写了构造器,编译器就不再给你添加默认的无参构造了。
(6)构造器可以重载,一个类可以有多个构造器。
(7)当声明子类时,在子类的构造器中,默认会调用父类的无参构造。
如果父类没有无参构造,又没有手动调用父类的有参构造,那么编译报错。

结论:
    要么让它默认调用父类的无参构造, 不写
    要么必须手动调用父类的有参构造,  super(实参列表);
    当然也可以手动调用父类的无参构造。 super();

    super(); 或 super(实参列表); 必须在子类构造器的首行。

墙裂建议大家:父类尽量保留无参构造。

非静态代码块

非静态代码块的作用
配合构造器在创建对象时,完成对象实例变量的初始化过程。

它的语法结构:
【修饰符】 class 类名{
    {
        非静态代码块
    }
}
执行特点
非静态代码块是在构造器调用时自动调用的。每new对象,就会执行一次非静态代码块。
先于构造器的代码执行。

实例初始化过程(面试题)

1、实例初始化过程:就是给对象的实例变量赋值的过程

2、刚才讲了3个操作都可以给实例变量赋初始值
(1)声明实例变量时,直接=值
(2)非静态代码块
(3)构造器

实际开发中都是选择构造器这一种方式比较多。
如果这3种方式同时存在,或者其中2种同时存在,那么实例变量的值最后以谁为准呢。
这就要求我们弄清楚它们的执行顺序,后面的会把前面的赋值给覆盖了。

3、实例初始化过程的顺序
(1)super();或super(实参列表);
(2)声明实例变量时,直接=值
(3)非静态代码块
(4)构造器其他代码(除了super();或super(实参列表);)

(1)最先执行的,然后(2)和(3)是按照代码编写的顺序执行,(4)在它们后面

4、编译器会把上面的4个部分的代码,组装成一个一个的<init>实例初始化方法。
你编写了你几个构造器,就有几个<init>实例初始化方法。
组装的顺序就是按照上面的(1),然后(2)和(3)是按照代码编写的顺序组装,(4)在它们后面。

init:initialize初始化
 

this和super(*****)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值