1 面向对象与面向过程的区别
- 出发点不同
- 面向对象方法是用符合常规思维的方式来处理客观世界的问题,强调把问题域的要领映射到对象及对象之间的接口上。
- 面面向过程方法强调的则是过程的抽象化与模块化,它是以过程为中心构造或处理客观世界问题的。
- 层次逻辑关系不同
- 面向对象方法则是用计算机逻辑来模拟客观世界中的物理存在,以对象的集合类作为处理问题的基本单位,尽可能地使计算机世界向客观世界靠拢,以使问题的处理更清晰直接, 面向对象方法是用类的层次结构来体现类之间的继承和发展。
- 而面向过程方法处理问题的基本单位是能清晰准确地表达过程的模块,用模块的层次结构概括模块或模块间的关系与功能,把客观世界的问题抽象成计算机可以处理的过程。
- 数据处理方式与控制程序方式不同
- 面向对象方法将数据与对应的代码封装成一个整体,原则上其他对象不能直接修改其数据, 即对象的修改只能由自身的成员函数完成,控制程序方式上是通过“事件驱动”来激活和运行程序。
- 而面向过程方法是直接通过程序来处理数据,处理完毕后即可显示处理结果,在控制程序方式上是按照设计调用或返回程序,不能自由导航,各模块之间存在着控制与被控制、调用与被调用的关系。
- 分析设计与编码转换方式不同
- 面向对象方法贯穿于软件生命周期的分析、设计及编码中,是一种平滑过程,从分析到设计再到编码是采用二致性的模型表示、即实现的是二种无缝连接。
- 而面向过程方法强调分析、设计及编码之间按规则进行转换,贯穿于软件生命周期的分析、设计及编码中,实现的是一种有缝的连接。
2 面向对象的特质
面向对象的特征包括抽象、继承、封装和多态。
- 抽象。抽象就是忽略一个主题中与当前目标无关的邓些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面:一是过程抽象;二是数据抽象。
- 继承。继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承、新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类),派生类可以从它的基类郡里继承方法和实例变量,并且派生类可以修改或增加新的方法使之更适合特殊的需要。
- 封装。封装是指将客观事物抽象成类,每个类对自身的数据和方法实行保护:类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏.
- 多态。多态是指允许不同类的对象对同一消息作出响应。多态包括参数化多态和包含多态。多态性语言具有灵活、抽象、行为共享、代码共享等优势,很好地解决了应用程序函数同名问题。
3 面向对象的开发方式的优点
-
较高的开发效率。
采用面向对象的开发方式,可以对现实的事物进行抽象,可以把现实的事物直接映射为开发的对象,与人类的思维过程相似,同时,由于面向对象的开发方式可以通过继承或者组合的方式来实现代码的重用,因此可以大大地提高软件的开发效率。
-
保证软件的鲁棒性。
正是由于面向对象的开发方法有很高的重用性,在开发的过程中可以重用已有的而且在相关领域经过长期测试的代码,因此,自然而然地对软件的鲁棒性起到良好的促进作用。
-
保证软件的高可维护性。
由于采用面向对象的开发方式,使得代码的可读性非常好,同时面向对象的设计模式也使得代码结构更加清晰明了。同时针对面向对象的开发方式,已有许多非常成熟的设计模式,这些设计模式可以使程序在面对需求的变更时,只需要修改部分的模块就可以满足需求,因此维护起来非常方便。
4 继承
继承是面向对象中的一个非常重要的特性。能过继承,了类可以使用父类中的一些成员变量与方法,从而能够提高代码的复用性,提高开发效率。
继承主要有如下几个特性:
- Java 语言不支持多重继承
- 子类只能继承父类的非私有(public 与protected)成员变量与方法
- 当了类中定义的成员变量和父类中定义的成员变量同名时,子类中的成员变量会覆盖父类的成员变量,而不会继承。
- 当子类中的方法与父类中的方法 有相同的函数签名(相同的方法名,相同的参数个数与类型)时,子类什么覆盖父类的方法,而不会继承。
5 组合和继承的区别
-
组合和继承是面向对象中两种代码复用的方式。
组合是指在新类里面创建原有类的对象,重复利用已有类的功能。被称为 has-a 关系。
继承是面向对象的主要特性之一,它允许设计人员根据其他类的实现来定义一个类的实现。被称为 is-a 关系 -
使用注意事项:
-
除非两个类之间是 is-a 关系,否则不要轻易使用继承,不要单纯地为了实现代码的重用而使用继承,因为过多地使用继承会破坏代码的可维护性。
-
不要仅仅为了实现多态而继承,如果类之间没有 is-a 的关系,可以通过实现接口与组合方式来达到相同的目的。
-
由于 Java 语言只支持间继承,如果 想同时继承两个类或多个类,在 Java 中是无法实现的。在 Java 语言中,能使用组合就尽量不要使用继承
-
6 多态的实现机制
多态是面向对象程序设计中代码重用的一个重要机制,它表示当同一个操作作用在不同对象时,会有不同的语义,从而会产生不同的结果,例如,同样是执行“+”操作,“3+4”用来实现整数相加,而“3”+”4”却实现了字符串的连接。
在 Java 语言中,多态主要有以下两种表现方式:
-
方法的重载(overload)。
重载是指同一个类中有多个同名的方法,但这些方法有着不同的参数,因此在编译时就可以确定到底调用哪个方法,它是一种编译时多态。重载可以被看作一个类中的方法多态性。
-
方法的覆盖(overide)。
子类可以覆盖父类的方法,因此同样的方法会在父类与子类中有着不同的表现形式。在Java 语言中,基类的引用变量不仅可以指向基类的实例对象,也可以指向其子类的实例对象。同样,接口的引用变量也可以指向其实现类的实例对象,而程序调用的方法在运行期才动态绑定(绑定指的是将一个方法调用和一个方法主体连接到一 起),就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。通过这种动态绑定的方法实现了多态。由于只有在运行时才能确定调用哪个方法,因此通过方法覆盖实现的多态也可以被称为运行时多态。
7 重载和覆盖的区别
重载(overload)和覆盖(overide)是 Java 多态性的不同表现方式。
-
重载是在一个类中多态性的一种表现,是指在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型。
在使用重载时,需要注意以下几点:
- 重载是通过不同的方法参数来区分的,例如不同的参数个数、不同的参数类型或不同的参数顺序。
- 不能通过方法的访问权限、返回值类型和抛出的异常类型来进行重载。
- 对于继承来说,如果基类方法的访问权限为 privae,那么就不能在派生类对其重载;如果派生类也定义了一个同名的函数,这只是一个新的方法,不会达到重载的效果。
-
覆盖是指派生类函数覆盖基类函数。覆盖一个方法并对其重写,以达到不同的作用。
在使用覆盖时需要注意以下几点:
- 派生类中的覆盖方法必须要和基类中被覆盖的方法有相同的函数名和参数。
- 派生类中的覆盖方法的返回值必须和基类中被覆盖白方法的返回值相同。
- 派生类中的覆盖方法的返回值必须和基类中被覆盖白方法的返回值相同。
- 基类中被覆盖的方法不能为 private 否则其子类只是定义了一个方法,并没有对其覆盖
-
重载与覆盖的区别:
- 覆盖是子类和父类之间的关系,是垂直关系;重载是同一个类中方法之间的关系,是水平关系。
- 覆盖只能由一个方法或只能由一对方法产生关系;重载是多个方法之间的关系。
- 覆盖要求参数列表相同;重载要求参数列表不同。
- 覆盖关系中,调用方法体是根据对象的类型(对象对应存储空间类型)来决定;而重载关系是根据调用时的实参表与形参表来选择方法体的。
8 抽象类(abstract class) 与接口(interface)的异同
如果一个类中包含抽象方法,那么这个类就是抽象类。在 Java 语言中,可以通过把类或
者类中的某些方法声明为 abstract(abstract 只能用来修饰类或者方法,不能用来修饰属性)来表示一个类是抽象类。接口就是指一个方法的集合,接口中的所有方法都没有方法体,在Java语言中,接口是通过关键字 interface 来实现的。
抽象类(abstract elass)和接口(interface)都是支持抽象类定义的两种机制(注意:此句中的前后两个抽象类的意义不一样,前者表示的是一个实体,后者表示的是一个概念)。二者具有很大的相似性,甚至有时候是可以互换的。但同时,二者也存在很大的区别。
只要包含一个抽象方法的类就必须被声明为抽象类,抽象类可以声明方法的存在而不去实现它,被声明为抽象的方法不能包含方法体。在实现时,必须包含相同的或者更低的访问级别(public–protected-private)。抽象类在使用的过程中不能被实例化,但是可以创建一个对象使其指向具体子类的一个实例。抽象类的子类为父类中的所有抽象方法提供具体的实现,否则它们也是抽象类。接口可以被看作抽象类的变体。接口中的所有方法都是抽象的,可以通过接口来间接地实现多重继承。接口中的成员变量都是 static final 类型。由于抽象类可以包含部分方法的实现,因此,在一些场合下抽象类比接口存在更多的优势。
-
抽象类(abstra)与接口(interface)的相同点:
-
都不能直接实例化。如果要实例化,抽象类变量必须实现所有抽象方法,接口变量必须实现所有接口未实现的方法。
(接口的实现类或抽象类的子类都只有实现接口或抽象类中的方法后才能被实例化。)
-
都可以有实现方法(Java8 以前的接口不能有实现方法)。
* @since 1.8 */ default void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); final ListIterator<E> li = this.listIterator(); while (li.hasNext()) { li.set(operator.apply(li.next())); } }
Java 1.8 新增了default关键字,可以使接口有自己的默认的实现类,而且还不影响接口的实现类。
-
都可以不需要实现类或者继承者去实现所有方法(Java8 以前的接口,Java8 及以后的接口中可以包括默认方法,不需要实现者实现)。
public interface A { default int c(){ return i; } int i = 0; } public class main { public static void main(String[] args) { A a = new A() {}; System.out.println(a.c()); } }
-
-
抽象类(abstra)与接口(interface)的不同点:
-
抽象类和接口所反映出的设计理念不同。抽象类表示的是对象 / 类的抽象,接口表示的是对行为的抽象。
-
abstract class AbstractStudent{ abstract void study(); void sleep(){ System.out.println("sleep"); } void smoke(){ System.out.println("抽烟"); } } //所有的Student被创建都会抽烟,是不是很搞笑? class Student extends AbstractStudent{ Student Demo stu = new Student(); ... }
abstract class AbstractStudent{ abstract void study(); void sleep(){ System.out.println("sleep"); } } interface Smoking{ void smoke(); } //普通的学生,继承AbstractStudent,有学习、睡觉的方法,不抽烟 class Student extends AbstractStudent{
-
抽象类不可以多重继承,接口可以多重继承。即一个类只能继续一个抽象类,却可以继承多个接口。
-
访问修饰符 ——
- 抽象类中的方法可以用 public protected 和 default abstract 修饰符,不能用 private、static、synchronize、native 修饰;变量可以在子类中重新定义,也可以重新赋值;
- 接口的方法默认修饰符是 public abstract, Java8 开始出现静态方法,多加 static 关键字;变量默认是 public static final 型,且必须给其初值,在实现类中也不能重新定义,也不能改变其值。
-
抽象类可以有构造器,接口没有构造器。
1)接口只有定义,其方法不能在接口中实现,只有实现接口的类才能实现接口中定义的方法,而抽象类可以有定义与实现,即其方法可以在抽象类中被实现。
2)接口需要实现(用 implements),但抽象类只能被继承(用 extends)。一个类可以实现
多个接口,但一个类只能继承一个抽象类,因此使用接口可以间接地达到多重继承的目的。
3)接口强调特定功能的实现,其设计理念是“has - a”关系;而抽象类强调所属关系,其设计理念为“is-a”关系。4)接口中定义的成员变量默认为 public static final,只能够有静态的不能被修改的数据
成员,而且,必须给其赋初值,其所有成员方法都是 public、abstract 的,而且只能被这两
个关键字修饰。而抽象类可以有自己的数据成员变量,也可以有非抽象的成员方法,而且,
抽象类中的成员变量默认为 defauht(本包可见),当然也可以被定义为 private、protected 和public,这些成员变量可以在子类中被重新定义,也可以被重新赋值,抽象类中的抽象方法
(其前有 abstract 修饰)不能用 private、static、synchronized、native 等访问修饰符修饰,同时方法必须以分号结尾,并且不带花括号。所以,当功能需要累积时,用抽象类;不需要累
积时,用接口。
5)接口被运用于实现比较常用的功能,便于日后维护或者添加删除方法;而抽象类更倾
向于充当公共类的角色,不适用于日后重新对里面的代码进行修改。
简单点说,接口是一种特殊形式的抽象类,使用接口完全有可能实现与抽象类相同的操
作,但一般而言,抽象类多用于在同类事物中有无法具体描述的方法的场景,所以当子类和父类之间存在有逻辑上的层次结构时,推荐使用抽象类;而接口多用于不同类之间,定义不同类之间的通信规则,所以当希望支持差别较大的两个或者更多对象之间的特定交互行为时,应该使用接口。此外,接口可以继承接口,抽象类可以实现接口,抽象类也可以继承具体类。抽象类也可以有静态的 main 方法。 -
9 内部类有哪些
10 获取父类的类名
11 this与supper的区别