面向对象编程(OOPs)面试题及答案

2025年3月30日 | 17分钟阅读

面向对象编程 (OOPs) 是一种基于对象而非仅仅函数和过程的编程范式。它是开发人员中最流行的方法。

如今,科技巨头们要求并招聘那些精通面向对象方法和模式的人才,并为此进行面试。招聘此类人才的优势在于,他们还可以根据组织要求轻松学习其他 OOP 语言。因此,如果您为OOPs 面试题做好了充分准备,您将有更大的机会被公司录用。

在本节中,我们收集了一些面向初学者和经验丰富人士的常见 OOPs 面试题。它可以帮助您通过面试,获得梦想的工作。

OOPs Interview Questions

1) 您对 OOP 有何理解?

OOP 代表面向对象编程。它是一种围绕对象而非函数和过程展开的编程范式。换句话说,它是一种强调对象的应用程序开发方法。对象是一个包含数据和代码的真实世界实体。它允许将数据和代码绑定在一起。


2) 列举七种广泛使用的 OOP 语言。

有多种 OOP 语言,但最广泛使用的有

  • Python
  • Java
  • Go
  • Dart
  • C++
  • C#
  • Ruby

3) 使用 OOPs 概念的目的是什么?

OOP 的目标是在编程中实现继承、隐藏、多态等现实世界实体。OOP 的主要目的是将数据和对数据进行操作的函数绑定在一起,以便除了该函数之外,代码的任何其他部分都无法访问此数据。


4) OOPs 的四个主要特性是什么?

OOP 具有以下四个特性

  • 继承
  • 封装
  • 多态
  • 数据抽象
OOPs Interview Questions

5) 为什么 OOP 如此流行?

面向对象编程范式被认为是一种更好的编程风格。它不仅有助于轻松编写复杂的代码,还允许用户轻松处理和维护它们。不仅如此,OOP 的主要支柱——数据抽象、封装、继承和多态——使得程序员可以轻松解决复杂的场景。由于这些原因,OOP 如此流行。


6) OOP 的优缺点是什么?

OOP 的优点

  • 它遵循自下而上的方法。
  • 它很好地模拟了现实世界。
  • 它允许我们重用代码。
  • 通过使用抽象,避免不必要的数据暴露给用户。
  • OOP 强制设计者进行长时间而广泛的设计阶段,从而带来更好的设计和更少的缺陷。
  • 将复杂问题分解成更小的块。
  • 程序员能够更快地实现他们的目标。
  • 最大限度地降低复杂性。
  • 易于代码的重新设计和扩展,且不影响其他功能。

OOP 的缺点

  • 需要适当的规划。
  • 程序设计很棘手。
  • 程序员应该技术娴熟。
  • 类往往过于通用化。

7) OOPs 有哪些局限性?

  • 需要密集的测试过程。
  • 与面向过程编程相比,解决问题需要更多时间。
  • 使用此方法创建的程序大小可能比使用面向过程编程方法编写的程序大。
  • 使用此方法开发的软件需要大量的预备工作和规划。
  • 如果您没有相应的类文档,OOP 代码很难理解。
  • 在某些情况下,这些程序可能会消耗大量内存。
  • 不适用于小问题。
  • 解决问题需要更多时间。

8) 面向对象编程和结构化编程有什么区别?

面向对象编程结构化编程
它遵循自下而上的方法。它遵循自上而下的方法。
它提供数据隐藏。不允许数据隐藏。
它用于解决复杂问题。它用于解决中等问题。
它允许代码重用,减少代码冗余。不允许代码重用。
它基于对象而非函数和过程。它为程序提供了一个逻辑结构,程序被划分为函数。
由于其数据隐藏功能,它提供了更高的安全性。由于它不支持数据隐藏功能,因此安全性较低。
抽象程度越高,灵活性越高。抽象程度越低,灵活性越低。
它侧重于数据。它侧重于过程或逻辑结构。

9) 您对纯面向对象语言有什么理解?为什么 Java 不是纯面向对象编程语言?

将程序中所有事物都视为对象的编程语言被称为纯面向对象语言。纯 OOPs 语言不支持原始类型。纯面向对象语言必须满足其他一些特性

  • 封装
  • 继承
  • 多态
  • 抽象
  • 所有预定义类型都是对象
  • 所有用户定义类型都是对象
  • 对对象执行的所有操作必须仅通过暴露给对象的方法。

Java 不是一种纯面向对象编程语言,因为 Java 中预定义的数据类型不被视为对象。因此,它不是一种纯面向对象语言。


10) 您对类和对象有什么理解?请举例说明。

类:类是对象的蓝图或模板。它是一种用户定义的数据类型。在类中,我们定义变量、常量、成员函数和其他功能。它在运行时不消耗内存。请注意,类不被视为数据结构。它是一个逻辑实体。它是数据绑定的最佳示例。

对象:对象是一个具有属性、行为和特性的真实世界实体。它被称为类的实例。它包含我们在类中定义的成员函数和变量。它占用内存空间。不同的对象具有不同的状态或属性和行为。

下图最佳地说明了类和对象。

OOPs Interview Questions

11) 类和对象有什么区别?

ClassObject
它是一个逻辑实体。它是一个真实世界的实体。
它是概念性的。它是真实的。
它将数据和方法绑定到一个单元中。它就像一个类的变量。
它不占用内存空间。它占用内存空间。
它是一种表示对象蓝图的数据类型。它是类的实例。
它被声明一次。可以根据需要声明多个对象。
声明时使用关键字 class。它使用 new 关键字创建对象。
一个类可以存在而没有任何对象。对象不能没有类而存在。

12) 类和结构体的主要区别是什么?

Class结构
类是共享共同属性的常见对象的集合。结构体是不同数据类型的集合。
它处理数据成员和成员函数。它只处理数据成员。
它支持继承。它不支持继承。
成员变量不能直接初始化。成员变量可以直接初始化。
它是引用类型。它是值类型。
它的成员默认是私有的。它的成员默认是公共的。
关键字 class 定义一个类。关键字 struct 定义一个结构体。
类的实例是一个对象。结构体的实例是一个结构体变量。
在处理复杂数据结构时很有用。在处理小型数据结构时很有用。

13) 您对访问修饰符的概念有什么理解?我们何时应该使用它们?

在 OOPs 语言中,访问修饰符是保留关键字,用于设置类、方法和类其他成员的访问权限。它也称为访问限定符。它包括 public、privateprotected。还有一些其他访问修饰符是特定于语言的。例如,Java 还有一个访问修饰符 default。这些访问修饰符在实现 OOP 主要功能之一,即封装方面,发挥着至关重要的作用。下表描述了可访问性。

OOPs Interview Questions

14) OOP 中的操作符是什么以及它是如何工作的?

操作符是辅助函数。它用于操纵或修改输入或输出流。通过使用插入 (<<) 和提取 (>>) 运算符可以进行修改。请注意,修改输入或输出流并不意味着更改变量的值。操作符有两种类型,带参数不带参数

没有参数的操作符示例有 endl, ws, flush 等。带参数的操作符有 setw(val), setfill(c), setbase(val), setiosflags(flag)。其他一些操作符有 showpos, fixed, scientific, hex, dec, oct 等。


15) 创建构造函数有哪些规则?

  • 它不能有返回类型。
  • 它必须与类名相同。
  • 它不能被标记为静态。
  • 它不能被标记为抽象。
  • 它不能被重写。
  • 它不能是 final。

16) Java 中构造函数和方法有什么区别?

构造函数方法
构造函数与类名相同。方法名和类名不相同。
它是一种特殊类型的方法,用于初始化其类的对象。它是一组可以在程序中任何时候调用的指令。
它创建一个类的实例。它用于执行 Java 代码。
当我们创建类的对象时,它会被隐式调用。当我们显式调用它时,它才会被执行。
它不能被子类继承。它可以被子类继承。
它没有任何返回类型。它必须有返回类型。
它在 Java 中不能被重写。它在 Java 中可以被重写。
它不能声明为静态。它可以声明为静态。
Java 编译器会自动提供一个默认构造函数。Java 编译器默认不提供任何方法。

17) 面向过程编程与 OOP 有何不同?

面向过程编程面向对象编程
它基于函数。它基于真实世界对象。
它遵循自上而下的方法。它遵循自下而上的方法。
它安全性较低,因为没有适当的数据隐藏方式。它提供了更高的安全性。
数据对整个程序可见。它封装了数据。
不允许代码重用。代码可以重用。
代码的修改和扩展不容易。我们可以轻松修改和扩展代码。
POP 的例子有 C、VB、FORTRAN、Pascal 等。OOPs 的例子有 C++、Java、C#、.NET 等。

18) 错误和异常有什么区别?

比较基础ExceptionError
可恢复/不可恢复异常可以通过使用 try-catch 块来恢复。错误无法恢复。
类型它可以分为两类,即已检查和未检查。Java 中的所有错误都是未检查的。
发生情况它发生在编译时或运行时。它发生在运行时。
它属于 java.lang.Exception 包。它属于 java.lang.Error 包。
已知或未知只有已检查的异常才为编译器所知。错误不会为编译器所知。
原因它主要由应用程序本身引起。它主要由应用程序运行的环境引起。
示例已检查异常:SQLException, IOException
未检查异常:ArrayIndexOutOfBoundException, NullPointerException, ArithmaticException
Java.lang.StackOverFlow, java.lang.OutOfMemoryError

19) 抽象类有什么特点?

抽象类是声明为抽象的类。它不能被实例化,并且总是用作基类。抽象类的特点如下

  • 不允许实例化抽象类。它必须被继承。
  • 抽象类可以同时拥有抽象方法和非抽象方法。
  • 抽象类必须至少有一个抽象方法。
  • 您必须在抽象类中声明至少一个抽象方法。
  • 它始终是公共的。
  • 它使用 abstract 声明。

抽象类的目的是提供基类的通用定义,多个派生类可以共享此定义。


20) 类是否可以继承其基类的构造函数?

不,一个类不能继承其基类的构造函数。


21) 在以下场景中,识别应该使用哪个 OOPs 概念?

一群5个朋友,一个男孩在小组外出时从不贡献任何东西。突然,一个漂亮的女孩加入了同一个小组。从不贡献的男孩现在为小组花费了很多钱。

运行时多态


22) 什么是组合?

组合是 OOP 中最重要的概念之一。它描述了一个类,该类在实例变量中引用一个或多个其他类的对象。它允许我们对对象之间的“has-a”关联进行建模。我们可以在现实世界中找到这种关系。例如,一辆汽车有一个引擎。下图描绘了这一点

OOPs Interview Questions

组合的主要好处是

  • 重用现有代码
  • 设计清晰的 API
  • 在不修改任何外部客户端的情况下,更改组合中使用的类的实现。

23) 复制构造函数和赋值运算符有什么区别?

复制构造函数和赋值运算符 (=) 都用于使用另一个对象初始化一个对象。两者之间的主要区别在于,复制构造函数为两个对象(即现有对象和新创建的对象)分配单独的内存,而赋值运算符不为新创建的对象分配新内存。它使用指向前一个内存块(旧对象所在位置)的引用变量。

复制构造函数的语法

赋值运算符的语法

 
复制构造函数赋值运算符
它是一个重载的构造函数。它是一个操作符。
它创建一个新对象作为现有对象的副本。它将一个对象的值赋给另一个已经存在的对象。
当使用某个现有对象创建新对象时,使用复制构造函数。当我们想要将一个现有对象赋给一个新对象时,它被使用。
两个对象使用独立的内存位置。两个对象共享相同的内存,但使用两个指向相同位置的不同引用变量。
如果类中没有定义复制构造函数,编译器会提供一个。如果赋值运算符没有被重载,则会进行位复制。

24) 组合和继承的区别是什么?

继承意味着一个对象继承基类的可重用属性。组合意味着一个对象包含其他对象。在继承中,内存中只有一个对象(派生对象),而在组合中,父对象包含所有组合对象的引用。从设计角度来看,继承是对象之间的“is a”关系,而组合是对象之间的“has a”关系。

OOPs Interview Questions

25) 什么是构造函数链?

在 OOPs 中,构造函数链是在初始化对象时调用构造函数(同一类)的序列。当我们需要通过只使用一个实例一个接一个地调用多个构造函数时,它被使用。换句话说,如果一个类有多个构造函数(重载的),并且其中一个尝试调用另一个构造函数,这个过程被称为构造函数链。在 C++ 中,它被称为构造函数委托,并且从 C++ 11 开始存在。

OOPs Interview Questions

26) 继承有哪些局限性?

  • 使用继承的主要缺点是两个类紧密耦合。这意味着一个不能独立于另一个使用。如果父类中的方法或聚合被删除,我们必须重构子类中使用该方法的地方。
  • 继承函数比普通函数运行速度慢。
  • 需要仔细实现,否则会导致不当的解决方案。

27) 继承和多态有什么区别?

继承多态
继承是指派生类继承已存在的类的特性。多态是指你可以用不同的形式定义它。
它指的是在子类中使用超类的结构和行为。它指的是在子类中改变超类的行为。
为了实现多态,它是必需的。为了实现多态,继承不是必需的。
它应用于类。它应用于函数和方法。
它可以是单一、混合、多重、层次、多路径和多级继承。多态有两种类型:编译时和运行时。
它支持代码重用并减少代码行数。它允许对象在运行时(重写)和编译时(重载)决定调用哪种形式的函数。

28) OOP 中的耦合是什么?为什么它有用?

在编程中,关注点分离被称为耦合。这意味着一个对象不能直接改变或修改其他对象的状态或行为。它定义了两个对象之间的连接紧密程度。耦合有两种类型,松散耦合和紧密耦合。

相互独立且不直接修改其他对象状态的对象称为松散耦合。松散耦合使代码更加灵活、可变且易于使用。

依赖于其他对象并可以修改其他对象状态的对象称为紧密耦合。它创建了修改一个对象的代码也需要更改其他对象代码的情况。在紧密耦合中,代码重用很困难,因为我们无法分离代码。

因此,使用松散耦合始终是一个好习惯。


29) 列出不能重载的运算符。

  1. 作用域解析运算符 (::)
  2. 三元运算符 (? :)
  3. 成员访问或点运算符 (.)
  4. 指向成员的指针运算符 (.*)
  5. sizeof 运算符

30) new 和 override 有什么区别?

new 修饰符指示编译器使用新的实现而不是基类函数。而 Override 修饰符有助于重写基类函数。

virtual:表示方法可能被继承者重写。

override:重写基类中虚拟方法的功能,提供不同的功能。

new:隐藏原始方法(不必是虚拟的),提供不同的功能。这只应该在绝对必要时使用。

当您隐藏一个方法时,您仍然可以通过向上转型到基类来访问原始方法。这在某些情况下很有用,但很危险。


31) 举例解释重载和重写?

重载

重载是 OOP 中的一个概念,指一个类中有两个或多个同名但方法签名不同的方法。它也称为编译时多态。例如,在以下代码片段中,方法 add() 是一个重载方法。


OOPs Interview Questions

重写

如果子类和父类中都存在具有相同方法签名的方法,则称为方法重写。这些方法必须具有相同数量的参数和相同类型的参数。它重写父类方法的值。它也称为运行时多态。例如,考虑以下程序。


32) OOP 中的内聚性是什么?

在 OOP 中,内聚性是指模块内部元素相互关联的程度。它衡量模块与数据之间关系的强度。简而言之,内聚性代表了模块职责的清晰度。它通常与耦合性形成对比。

它侧重于单个模块或类的预期目的。模块或类的内聚性越高,面向对象设计就越好。

OOPs Interview Questions

内聚性分为两种类型:高内聚低内聚

  • 高内聚与软件的几个所需质量相关联,包括健壮性、可靠性可理解性
  • 低内聚与不希望的质量相关联,例如难以维护、测试、重用甚至理解

高内聚通常与松散耦合相关联,反之亦然。


33) 举一个多态的真实世界例子?

多态的普遍含义是“具有不同形式”。多态的最佳真实世界例子是一个在不同地点或情况下扮演不同的角色。

  • 在家中,一个人可以扮演父亲、丈夫和儿子的角色。
  • 在办公室,同一个人扮演老板或员工的角色。
  • 在公共交通工具上,他扮演乘客的角色。
  • 在医院,他可以扮演医生或病人的角色。
  • 在商店,他扮演顾客的角色。
OOPs Interview Questions

因此,同一个人在不同情况下表现出不同的行为。这被称为多态性。


34) 基类和超类有什么区别?

基类是根类——最通用的类。同时,超类是其他类继承的直接父类。


35) 什么是数据抽象?如何实现数据抽象?

它是 OOP 最重要的特性之一。它允许我们只向用户展示必要的数据或信息,并向用户隐藏实现细节。抽象的一个真实世界示例是驾驶汽车。当我们驾驶汽车时,我们不需要知道发动机是如何工作的(实现),我们只需要知道 ECG 如何工作。

实现数据抽象有两种方法

  • 抽象类
  • 抽象方法

36) 数据抽象有哪些层次?

数据抽象有三个层次

OOPs Interview Questions
  • 物理层:这是数据抽象的最低层。它显示数据实际在内存中是如何存储的。
  • 逻辑层:它包括实际以表的形式存储在数据库中的信息。它还以相对简单的结构存储数据实体之间的关系。在此级别,视图级别向用户提供的信息是未知的。
  • 视图层:这是数据抽象的最高层。实际数据库对用户可见。它的存在是为了方便单个用户对数据库的可用性。

37) OOP 中变量的类型有哪些?

变量有三种类型

OOPs Interview Questions

实例变量:它是一个对象级别的变量。它应该在类内部声明,但必须在方法、块和构造函数外部。它在通过 new 关键字创建对象时创建。可以通过在类内部调用变量名直接访问它。

静态变量:它是一个类级别的变量。它使用关键字 static 在类内部声明,但必须在方法、块和构造函数外部。它存储在静态内存中。它的可见性与实例变量相同。静态变量的默认值与实例变量相同。可以通过调用 class_name.variable_name 访问它。

局部变量:它是一个方法级别的变量。它可以在方法、构造函数或块中声明。请注意,局部变量不允许使用访问修饰符。它只对其声明的方法、块和构造函数可见。在内部,它在堆栈级别实现。它在使用前必须声明和初始化。

面向对象编程中使用的另一种变量是引用变量。

引用变量:它是一个指向类对象的变量。它指向存储在内存中的对象的内存位置。


38) 构造函数可以重载吗?

是的,构造函数可以通过改变构造函数接受的参数数量或改变参数的数据类型来重载。例如:


39) 我们可以重载 Java 中的 main() 方法吗?请举例说明。

是的,我们也可以重载 Java 中的 main() 方法。类中可以定义任意数量的 main() 方法,但方法签名必须不同。请看以下代码。


40) 考虑以下场景

如果一个类 Demo 有一个静态块和一个 main() 方法。两者中都有一个打印语句。问题是哪个会先执行,静态块还是 main() 方法,为什么?

JVM 首先以优先级方式执行静态块。这意味着 JVM 甚至在程序中查找 main() 方法之前,就会先执行静态块。之后才会执行 main() 方法。