Java面向对象面试题总结(上)

简介: 在Java中,重写(Override)与重载(Overload)是两个重要的概念,关联到方法的定义与调用。重写是指子类对继承自父类的方法进行新的实现,以便提供子类特有的行为,其关键在于方法签名一致但方法体不同。重载则允许在同一个类中定义多个同名方法,只要参数列表不同即可,以此提供方法调用的灵活性。重写关注多态性,而重载强调编译时多态。

一、重写和重载

在Java中,重写(Override)和重载(Overload)是面向对象编程中两个非常重要的概念,它们都与方法的定义和调用有关,但两者有着本质的区别。

1、重写(Override)

重写是子类对父类中继承来的方法进行重新定义(也就是方法签名相同,但方法体不同)。当子类需要修改从父类继承来的方法的行为时,就会使用到重写。重写的目的是允许子类提供特定于自己的实现。

重写的规则:

  1. 方法名、参数列表必须相同:这是为了保持多态性,即父类类型的引用可以指向子类对象,并调用实际子类对象的方法。
  2. 返回类型:对于非静态方法,返回类型可以是父类方法的返回类型的子类型(Java 5及以后版本支持协变返回类型)。对于静态方法,返回类型必须相同。
  3. 访问修饰符:子类方法的访问级别不能低于父类方法的访问级别(但可以有更高的访问级别)。
  4. 异常:子类方法抛出的异常应该是父类方法抛出异常的子类或没有异常(Java 7及以后版本支持更灵活的异常处理规则)。

示例:

class Animal {
   
    void eat() {
   
        System.out.println("This animal eats food.");
    }
}

class Dog extends Animal {
   
    @Override
    void eat() {
   
        System.out.println("Dog eats dog food.");
    }
}

在这个例子中,Dog类重写了Animal类的eat方法。

2、重载(Overload)

重载是在同一个类中,允许存在多个同名的方法,只要它们的参数列表不同即可。参数列表不同意味着参数的数量、类型或顺序至少有一项不同。重载的主要目的是提供灵活的方法调用,允许根据传递的参数类型或数量来调用不同的方法实现。

重载的规则:

  1. 方法名必须相同。
  2. 参数列表必须不同(参数的数量、类型或顺序不同)。
  3. 方法的返回类型、访问修饰符以及抛出的异常类型与重载无关。

示例:

class MathUtils {
   
    // 方法1
    int add(int a, int b) {
   
        return a + b;
    }

    // 方法2,重载
    double add(double a, double b) {
   
        return a + b;
    }

    // 方法3,重载(参数数量不同)
    int add(int a, int b, int c) {
   
        return a + b + c;
    }
}

在这个例子中,MathUtils类有三个名为add的方法,但它们的参数列表不同,因此它们是重载关系。

总结

  • 重写是子类对父类方法的重新定义,用于提供特定于子类的实现。
  • 重载是在同一个类中允许存在多个同名但参数列表不同的方法,用于提供灵活的方法调用。
  • 重写是面向对象多态性的体现,而重载是编译时多态性的体现。

二、equals 和 hashcode

1、简述 hashCode() 和 equals(Object obj) 的作用及其关系

hashCode() 方法用于获取对象的哈希码,即一个整数。这个哈希码在基于哈希的集合(如HashSet、HashMap等)中用于确定对象的存储位置。

equals(Object obj) 方法用于比较两个对象是否相等。默认情况下,它比较的是对象的引用地址;但在自定义类中,通常会重写该方法以比较对象的内容。

这两个方法之间的关系是:如果两个对象通过 equals(Object obj) 方法比较是相等的,那么调用这两个对象中任一对象的 hashCode() 方法必须产生相同的整数结果。这是Java集合框架正常工作的基本要求。

2、为什么要在自定义类中同时重写 hashCode() 和 equals(Object obj) 方法?

如果只重写 equals(Object obj) 方法而不重写 hashCode() 方法,那么在基于哈希的集合中,即使两个对象通过 equals(Object obj) 方法比较是相等的,但由于它们的哈希码不同,这些集合也可能无法正确地处理它们(如无法正确去重)。

因此,为了保证自定义对象在Java集合框架中的正确性,当重写 equals(Object obj) 方法时,通常也需要重写 hashCode() 方法,以确保 equals(Object obj) 相等的对象具有相同的哈希码。

3、请解释为什么hashCode()方法可能产生哈希碰撞,以及这是否会影响equals(Object obj)方法的正确性?

哈希碰撞是指不同的对象产生相同的哈希码。由于哈希码是一个整数,而整数的范围是有限的,而对象的数量可以是无限的,因此哈希碰撞是不可避免的。

哈希碰撞本身不会影响 equals(Object obj) 方法的正确性。equals(Object obj) 方法用于比较对象的内容是否相等,而哈希码只是用于在集合中快速定位对象的一种机制。即使两个对象产生了哈希碰撞,只要它们的 equals(Object obj) 方法比较不相等,它们就不会被视为集合中的相同元素。

然而,哈希碰撞可能会影响基于哈希的集合的性能,因为它可能增加在集合中查找元素的时间复杂度。

4、在重写 hashCode() 方法时,有哪些注意事项?

在重写hashCode()方法时,应该确保在同一个Java应用程序执行期间,只要对象的equals比较中所用的信息没有被修改,那么对该对象多次调用hashCode方法必须始终如一地返回同一个整数。

如果两个对象通过 equals(Object obj) 方法比较是相等的,那么这两个对象的 hashCode() 方法必须产生相同的整数结果。

不要求如果两个对象通过 equals(Object obj) 方法比较是不相等的,那么调用这两个对象中任一对象的 hashCode() 方法必须产生不同的整数结果。但是,为不相等的对象产生不同整数结果可能会提高哈希表的性能。

三、抽象类和接口有什么区别?

抽象类和接口都不能够实例化,但是可以定义抽象和接口类型的引用。一个类如果继承了某个抽象类或者实现某个接口都需要对其中的抽象方法进行实现,否则该类仍然需要被声明为抽象类。

接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部是抽象方法。

四、抽象类是什么?它和接口有啥区别?

接口用于规范,抽象类用于共性。声明方法的存在而不去实现它的类叫做抽象类。接口时抽象类的变体。在接口中,所有的方法都是抽象的。

五、讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序

在Java中,当使用new关键字创建一个类的实例时,会遵循一个特定的顺序来初始化对象。这个顺序涉及到父类和子类的静态数据、构造函数以及字段(成员变量)的初始化。下面是这个顺序的详细解释:

1、静态块和静态变量(父类到子类):

  • 首先,会初始化父类中定义的静态变量和静态初始化块(如果有的话),按照它们在代码中出现的顺序进行。
  • 然后,会初始化子类中定义的静态变量和静态初始化块(如果有的话),也是按照它们在代码中出现的顺序进行。
  • 需要注意的是,静态初始化只会在类被加载到JVM时发生一次,与创建类的实例数量无关。

2、实例变量(父类到子类):

  • 在创建类的实例时,会首先为父类中的实例变量分配内存并默认初始化(例如,数值类型变量初始化为0,对象引用初始化为null)。
  • 然后,会执行父类的非静态初始化块(如果有的话)。
  • 接着,会执行父类的构造函数,此时父类的实例变量可以被显式初始化。
  • 同样的过程会发生在子类上,但会在父类初始化之后进行。子类中的实例变量会被分配内存并默认初始化,然后执行子类的非静态初始化块(如果有的话),最后执行子类的构造函数。

3、构造函数(父类到子类):

  • 在创建对象时,构造函数的调用是遵循从父类到子类的顺序的。这意味着在子类的构造函数中,可以通过super()(显式或隐式)调用父类的构造函数,并且这个调用必须是子类构造函数中的第一条语句(除了注释和变量声明)。
  • 如果子类没有显式调用父类的构造函数,则会自动调用父类的无参构造函数(如果父类没有定义无参构造函数且子类没有显式调用其他构造函数,则会导致编译错误)。

综上所述,当使用new关键字创建类的实例时,执行顺序大致如下:

1、父类静态变量和静态初始化块(按出现顺序)。
2、子类静态变量和静态初始化块(按出现顺序)。
3、父类实例变量默认初始化。
4、父类非静态初始化块(如果有的话)。
5、父类构造函数。
6、子类实例变量默认初始化。
7、子类非静态初始化块(如果有的话)。
8、子类构造函数。

这个顺序确保了父类在子类之前被完全初始化,从而保证了继承体系中的正确性和稳定性。

六、Java 创建对象有几种方式?

  • new 创建新对象
  • 通过反射机制创建对象
  • 采用 clone 创建对象
  • 通过序列化机制
目录
相关文章
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
813 1
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
779 0
|
算法 Java
50道java集合面试题
50道 java 集合面试题
|
12月前
|
Java
Java基础语法与面向对象
重载(Overload)指同一类中方法名相同、参数列表不同,与返回值无关;重写(Override)指子类重新实现父类方法,方法名和参数列表必须相同,返回类型兼容。重载发生在同类,重写发生在继承关系中。
305 1
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
604 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
存储 Java 关系型数据库
Java 项目实战基于面向对象思想的汽车租赁系统开发实例 汽车租赁系统 Java 面向对象项目实战
本文介绍基于Java面向对象编程的汽车租赁系统技术方案与应用实例,涵盖系统功能需求分析、类设计、数据库设计及具体代码实现,帮助开发者掌握Java在实际项目中的应用。
430 0
|
算法 Java
50道java基础面试题
50道java基础面试题
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
451 5
|
安全 Java 编译器
Java面向对象
本文深入讲解了Java面向对象编程(OOP)的四大特性:封装、继承、多态与抽象,以及方法的设计与使用。通过示例展示了如何用类和对象组织代码,提升程序的可维护性与扩展性。

热门文章

最新文章