最近在准备面试,把知识点复习一遍,整理出的笔记记录下,里面会穿插代码和面试例题。
内容不是原创,是总结和收集,如果侵权了请联系作者,若有错误也请各位指正。因为收集的时候忘记把来源记录下来了,所以就不po出处了,请见谅(这是个坏习惯,一定改)。
面试复习之—Java基础(一):面向对象特征
这是面试复习内容的第一篇——面向对象特性,主要是Java基础的内容,所有内容将分为几篇来写。
一、面向对象特性
1、对象的概念
Java 是面向对象的编程语言,对象就是面向对象程序设计的核心。所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每一个实体都是一个对象,它是一种具体的概念。对象有以下特点:
- 对象具有属性和行为。
- 对象具有变化的状态。
- 对象具有唯一性。
- 对象都是某个类别的实例。
一切皆为对象,真实世界中的所有事物都可以视为对象。
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。抽象是指将业务抽象为软件领域的元素(系统、模块或类)。
2、面向对象三大特性
面向对象有三大特性:封装、继承、多态。
继承:继承是从已有类得到继承信息创建新类的过程就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。
封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。封装通过Java的访问权限来实现。封装可以保护类中的信息,只提供外界可访问的信息。
多态:多态是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。
3、继承
继承是类与类的一种关系,是一种“is a”的关系。java中的继承是单继承,即一个类只有一个父类。
Java中的继承只能单继承,但是可以通过内部类继承其他类来实现多继承。
继承的好处是子类拥有父类的所有属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用。
方法的重写
子类如果对继承的父类的方法不适用(不适合),可以自己编写继承的方法,这种方式就称为方法的重写。当调用方法时会优先调用子类的方法。
重写要注意以下条件三个都要与父类继承的方法相同,才叫方法的重写。
- 返回值类型
- 方法名
- 参数类型及个数
重载和重写的区别
方法重载:在同一个类中, 允许存在一个以上的同名方法, 只要它们的参数个数或者参数类型不同即可。在同一个类中处理不同数据的多个相同方法名的多态手段。
方法重写:相对继承而言,子类中对父类已经存在的方法进行区别化的修改。
继承的初始化顺序
- (1)初始化父类再初始化子类
- (2)先执行初始化对象中属性,再执行构造方法中的初始化。
总结:父类对象属性初始化---->父类对象构造方法---->子类对象属性初始化—>子类对象构造方法。
Final关键字
使用final关键字做标识有“最终的”含义。
- final 修饰类,则该类不允许被继承。
- final 修饰方法,则该方法不允许被覆盖(重写)。
- final 修饰属性,则该类的该属性不会进行隐式的初始化,所以 该final属性的初始化属性必须有值,或在构造方法中赋值(但只能选其一,且必须选其一,因为没有默认值!),且初始化之后就不能改了,只能赋值一次。
- final 修饰变量,则该变量的值只能赋一次值,在声明变量的时候才能赋值,即变为常量。
Super关键字
在对象的内部使用,可以代表父类对象。
子类的构造的过程当中必须调用父类的构造方法。其实这个过程已经隐式地使用了我们的super关键字。
这是因为如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法。那么如果自己用super关键字在子类里调用父类的构造方法,则必须在子类的构造方法中的第一行。
要注意的是:如果子类构造方法中既没有显示调用父类的构造方法,而父类没有无参的构造方法,则编译出错。
(补充说明,虽然没有显示声明父类的无参的构造方法,系统会自动默认生成一个无参构造方法,但是,如果你声明了一个有参的构造方法,而没有声明无参的构造方法,这时系统不会动默认生成一个无参构造方法,此时称为父类有没有无参的构造方法。)
4、封装
封装是将代码及其处理的数据绑定在一起的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。封装的目的在于保护信息,使用它的主要优点如下。
- 保护类中的信息,它可以阻止在外部定义的代码随意访问内部代码和数据。
- 隐藏细节信息,一些不需要程序员修改和使用的信息,比如取款机中的键盘,用户只需要知道按哪个键实现什么操作就可以,至于它内部是如何运行的,用户不需要知道。
- 有助于建立各个系统之间的松耦合关系,提高系统的独立性。当一个系统的实现方式发生变化时,只要它的接口不变,就不会影响其他系统的使用。
- 提高软件的复用率,降低成本。每个系统都是一个相对独立的整体,可以在不同的环境中得到使用。
访问权限
- Public:包内、包外所有类中可见(可访问调用)。
- Protected:包内所有的类可见;包外有继承关系的子类可见。
- Default:默认级别。本类、包内可见,其他包不可import引入。
- Private:仅在同一个类中可见。
总结:public>protected>default=package>private。
Main函数
main不是关键字,但是一个特殊的单词,能够被JVM识别。
一个java文件中可以包含很多个类,每个类中有且仅有一个主函数,但是每个java文件中可以包含多个主函数,在运行时,需要指定JVM入口是哪个。
主函数可以被重载,但是JVM只识别main(String[] args),其他都是作为一般函数。这里面的args数组变量可以更改(默认情况下传入了空数组),其他都不能更改。
This关键字
- this关键字代表当前对象。
- 封装对象的属性的时候,经常会使用this关键字。
- 当getter和setter函数参数名和成员函数名重合的时候,可以使用this.xxx区别。
内部类
内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。
内部类类别:
成员内部类、静态内部类、方法内部类、匿名内部类。
内部类的好处:
- 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
- 内部类的方法可以直接访问外部类的所有数据,包括私有的数据。
内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便。
5、多态
面向对象的多态性,即“一个接口,多个方法”。
Java中的多态主要在两个方面:引用多态、方法多态。
引用多态
- 父类的引用可以指向本类的对象;
- 父类的引用可以指向子类的对象。
方法多态
本类对象和子类对象,同样都是父类的引用,当我们指向不同的对象时,它们调用的方法也是多态的。
- 创建本类对象时,调用的方法为本类方法;
- 创建子类对象时,调用的方法为子类重写的方法或者继承的方法;
使用多态的时候要注意:如果我们在子类中编写一个独有的方法(没有继承父类的方法),此时就不能通过父类的引用创建的子类对象来调用该方法!
引用类型转换
向上类型转换(隐式/自动类型转换)
向上类型转换,是小类型转换到大类型;通俗的说就是将子类对象转换为父类对象,父类对象可以是接口。
向上转型会丢失子类特有的方法,只保留父类的方法,如子类重写了父类的方法会优先调用,这叫做动态绑定。
向下类型转换(强制类型转换)
向下类型转换,是大类型转换到小类型(有风险,可能出现数据溢出)。
- (1)向下类型转换的前提是父类对象指向子类对象,在向下转型之前,需先向上转型。
- (2)父类引用的是父类对象,向下转型规程是不安全的,编译时不会报错,运行时会报错,可使用instanceof来判断进行避免。
instanceof运算符
instanceof是Java的一个二元操作符,是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。用来判断引用对象的类型,避免类型转换的安全性问题。
重写和重载
多态一般可以分为两种,一个是重写override,一个是重载overload。
方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西。
要实现多态需要做两件事:
- 1)方法重写(子类继承父类并重写父类中已有的或抽象的方法);
- 2)对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
重写和重载的区别
-
重载Overloaded的方法是不可以改变返回值的类型的。
-
重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。
-
重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。
-
子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。
-
子类方法的访问权限只能比父类的更大,不能更小。
-
如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。
重载Overload 的特点
- 1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int,float),但是不能为fun(int,int));
- 2、不能通过访问权限、返回类型、抛出的异常进行重载;
- 3、方法的异常类型和数目不会对重载造成影响;
- 4、对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
总结:
override(重写,覆盖) (发生在子类与父类中)
- 1、方法名、参数、返回值相同。
- 2、子类方法不能缩小父类方法的访问权限。
- 3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
- 4、存在于父类和子类之间。
- 5、方法被定义为final不能被重写。
overload(重载,过载) (发生在同一个方法中)
- 1、参数类型、个数、顺序至少有一个不相同。
- 2、不能重载只有返回值不同的方法名。
- 3、存在于父类和子类、同类中。