Java 基础常见面试题整理

目录

1、java的基本数据类型有哪些?

Java的基本数据类型包括以下八种:

  • boolean: 用于存储逻辑值,只能存储true和false。
  • byte: 用于存储字节数据,占用8位(一个字节)内存空间。
  • short: 用于存储较短整数,占用16位(两个字节)内存空间。
  • int: 用于存储整数,占用32位(四个字节)内存空间。
  • long: 用于存储长整数,占用64位(八个字节)内存空间。
  • float: 用于存储单精度浮点数,占用32位(四个字节)内存空间。
  • double: 用于存储双精度浮点数,占用64位(八个字节)内存空间。
  • char: 用于存储单个字符,占用16位(两个字节)内存空间,采用Unicode编码。

2、java为什么要有包装类型?

主要原因包括以下几点:

  • 处理基本数据类型的 null 值:基本数据类型(如 int,double 等)不能直接赋值为 null,而包装类型(如 Integer、Double)可以表示 null 值,这对于某些业务逻辑和数据处理来说非常有用。
  • 提供额外功能:包装类型提供了一些额外的方法和功能,这些方法可以用于对基本数据类型进行操作和处理。例如,Integer 类提供了
    parselnt()方法用于将字符串转换为整数。
  • 泛型支持:泛型只能接受对象类型,无法直接使用基本数据类型。因此,使用包装类型可以很方使地在泛型中使用基本数据类型。
  • 自动装箱与拆箱: Java 提供了自动装箱(autoboxing)和自动拆箱(unboxing)的功能,使得基本类型与其对应的包装类型之间的转换更加便捷。
  • 与对象集合的兼容性: Java的集合类(如ArrayList, HashMap等)只能存储对象,不能直接存储基本数据类型。使用包装类型可以方便地将基本数据类型转换为对象类型,从而与集合类兼容。

3、String a = “123” 和 String a = new String(“123”) 区别?

String a = "123"; // a 是一个变量,对字符串常量池中“123”这个对象的引用
// "123" 是一个字符串字面量(字符串对象),它会被存储在字符串常量池中(String Constant Pool)。
// 当字符串常量池不存在“123”对象会创建一个对象,存在则不会创建  
  
String b = new String("123"); // b 是一个变量,但它引用堆的 String 对象  
// 这里,首先 JVM 会检查字符串常量池中是否已经有 "123" 这个字符串。  
// 如果有,它会用常量池中的字符串对象作为参数去调用 String 类的构造函数来创建一个新的 String 对象。  
// 这个新的 String 对象会被分配在堆内存中,并且它的内容(字符数组)会是常量池中字符串对象的一个拷贝。  
// 变量 b 持有对这个新创建的堆上 String 对象的引用,而不是直接引用常量池中的字符串。
// 最多创建2个对象,最少一个

4、String、StringBuilder和StringBuffer的区别?

String、StringBuilder和StringBuffer是Java中用来处理字符串的类,它们之间的区别主要在于性能和线程安全性。

  • String: 一旦创建就不能被修改,任何对String的操作都会产生一个新的String对象。
    不可变性使得String在并发环境下是线程安全的,但是频繁的字符串操作会产生大量临时对象,影响性能。

  • StringBuilder: StringBuilder是可变的,可以进行插入、追加、删除等操作而不会产生新的对象。
    由于StringBuilder是非线程安全的,所以在单线程环境下比StringBuffer具有更好的性能。

  • StringBuffer: 与StringBuilder类似,也是可变的,但是它是线程安全的,所有的方法都是同步的。
    在多线程环境下,为了确保线程安全性,可以使用StringBuffer,但性能相对较差,因为是通过在方法上面加synchronized 关键字来保证同步的。

因此,如果在单线程环境下需要频繁修改字符串,建议使用StringBuilder;如果在多线程环境下需要频繁修改字符串,则应该使用StringBuffer;如果字符串不需要被修改,那么使用String即可。

5、如何理解面向对象和面向过程?

面向过程是一种以过程为中心的编程方法,它将问题分解为一系列步骤函数。每个函数负责完成一个特定的任务,通过依次调用这些函数来解决问题。

其优点包括:

  • 流程清晰:按照步骤进行编程,易于理解和调试。

然而,它也存在一些局限性:

  • 代码复用性差:功能封装在函数中,但难以复用和扩展。
  • 维护困难:代码结构较为松散,修改可能影响多个部分。

面向对象则是一种以对象为中心的编程方法。它将问题抽象为对象,每个对象具有属性和行为。
其优点包括:

  • 代码复用性高:通过继承和多态实现代码的重用和扩展。
  • 维护方便:修改一个对象的行为不会影响其他部分。
  • 模拟现实世界:更符合人类的思维方式。

面向对象编程的关键概念包括:

  • 对象:表示现实世界中的实体。
  • 类:对象的抽象描述。
  • 封装:隐藏对象的内部实现,只暴露必要的接口。
  • 继承:实现代码的重用和扩展。
  • 多态:不同对象对同一消息的不同响应。

总之,面向对象编程更加注重代码的封装、复用和可扩展性,使得代码更易于维护和扩展。而面向过程编程则更适合一些简单、流程性强的问题。在实际编程中,可以根据具体情况选择合适的编程方法。

6、面向对象的三大基本特征是什么?如何理解?

面向对象的三大基本特征是封装、继承和多态

封装是将对象的属性和行为封装在一起,对外只提供必要的接口。它的意义在于:

  • 信息隐藏:隐藏内部实现细节,提高安全性和可靠性。
  • 模块独立性:减少模块之间的耦合,便于模块的独立开发和测试。

继承允许子类继承父类的属性和方法,从而实现代码的重用和扩展。理解继承可以从以下几个方面考虑:

  • 代码复用:避免重复编写相同的代码。
  • 扩展功能:子类可以在父类的基础上添加新的功能。

多态是指同一个方法在不同的对象上有不同的实现。它的好处包括:

  • 灵活性:根据具体对象的类型执行相应的操作。
  • 可扩展性:方便添加新的子类并实现不同的行为。

7、java是面向对象还是面向过程?

Java 是一种面向对象的编程语言。

8、什么是反射?为什么需要反射?

反射是指在运行时动态地访问和操作类的信息。

需要反射的原因包括:

  • 灵活性:可以在运行时获取类的信息、创建对象、调用方法等,提供了更大的灵活性。
  • 动态加载:支持在运行时动态加载和使用类,无需在编译时确定。
  • 框架和工具开发:便于开发通用的框架和工具,可适应不同的业务需求。
  • 插件机制:支持插件式的扩展,方便添加新的功能。
  • XML 配置:与配置文件结合,实现基于配置的动态功能。
  • 类操作:对类进行各种操作,如修改属性、方法等。
  • 跨模块交互:方便不同模块之间的交互和集成。

通过反射,程序可以在运行时动态地了解和操作类的结构和行为,从而实现更灵活和可扩展的系统设计。

9、为什么不能用浮点数表示金额? 有什么方法解决?

浮点数在计算机内部的表示方法采用的是 IEEE 标准,它兼顾了数据的精度和大小。32 位的浮点数由 1 比特的符号位、8 比特的阶码和 23 比特的尾数组成。浮点数能表示的数据大小范围由阶码决定,而能够表示的精度完全取决于尾数的长度。对于金额,舍去不能表示的部分,就会产生精度丢失
十进制的 0.1 在二进制下将是一个无线循环小数,同样,在进行加法、减法、乘法和除法等运算时,这种精度损失可能会累积,导致结果不正确。为了避免这种情况,建议使用 java.math.BigDecimal 类来表示和计算金额。BigDecimal 提供了用于高精度算术运算的方法,能够精确地表示十进制小数,避免浮点数表示和计算中的精度损失问题。

10、为什么不能用字符串来存储金额?

使用字符串来存储金额有一些局限性:

  • 计算困难:进行数值计算时,需要额外的处理来转换和解析字符串。
  • 效率较低:在涉及大量金额操作时,性能可能受到影响。
  • 不支持数学运算:无法直接进行加减乘除等常见的数学运算。
  • 易出错:处理字符串转换可能引入错误。
  • 数据类型不一致:与其他数值类型的交互可能需要额外的转换。

然而,在某些情况下,可能会选择使用字符串来存储金额:

  • 格式灵活:可以方便地表示特定的金额格式。
  • 非数值场景:如仅用于显示或存储。

为了更准确和高效地处理金额,通常使用专门的数值类型或类,例如 Java 中的BigDecimal,它提供了高精度的数值计算功能,能够避免常见的数值计算问题。

11、为什么需要克隆?如何实现对象的克隆?深拷贝和浅拷贝的区别?

需要克隆的原因有以下几点:

  • 独立性:创建独立的副本,避免对原始对象的修改影响到其他使用该对象的部分。
  • 隔离性:在不同的上下文或操作中使用相同对象的副本,以防止冲突。
  • 安全性:确保原始对象的完整性和稳定性。

实现对象的克隆有多种方式,以下是一种常见的方法:

  • 实现 Cloneable 接口:确保类实现了 Cloneable 接口。
  • 重写 clone 方法:在类中重写 clone 方法。

深拷贝和浅拷贝的区别在于:

深拷贝:复制对象及其引用的所有嵌套对象。

  • 副本与原始对象完全独立。
  • 修改副本不会影响原始对象。

浅拷贝:只复制对象本身,不复制引用的嵌套对象。

  • 嵌套对象仍与原始对象共享。
  • 修改副本的嵌套对象会影响原始对象。

深拷贝确保了副本的完全独立性,而浅拷贝在处理嵌套对象时可能会出现问题。在需要完全独立的副本时,应使用深拷贝。

12、try-catch-finally中,如果catch中return了,finally还会执行吗?

在 try-catch-finally 语句中,即使在 catch 块中执行了 return 语句,finally 块仍然会执行。

finally 块的作用是确保无论在 try 块中是否发生异常,某些特定的操作都会被执行,例如资源的释放、清理等。

当执行到 catch 块中的 return 语句时,会先将返回值保存起来,然后执行 finally 块中的代码。最后,再返回保存的返回值。

finally 块的执行具有以下特点:

  • 无论是否发生异常,finally 块都会执行。
  • 即使在 finally 块中抛出异常,也会继续执行。
  • finally 块中的返回值不会影响 try 或 catch 块中的返回值。

使用 finally 块可以确保资源的正确释放,以避免资源泄漏等问题。

13、String为什么设计成不可变的?

String 被设计成不可变有以下几个原因:

  1. 安全性和稳定性:避免在多个线程中同时修改字符串时可能出现的竞态条件。
  2. 效率:许多操作可以直接利用字符串的不可变性进行优化。
  3. 缓存友好:相同字符串可以共享,减少内存占用。
  4. 线程安全:无需进行额外的同步操作。
  5. 代码简洁:无需处理可变字符串带来的复杂情况。
  6. 避免误操作:防止意外修改字符串。
  7. 易于实现和理解:简化字符串的内部实现。

不可变的特性使得 String 在多线程环境中更加可靠,并且提高了性能和内存效率。

14、Error和Exception的区别和联系?以及常见的RuntimeException?

在这里插入图片描述

区别:

  • Error: Error是指Java虚拟机无法解决的严重问题,通常由系统内部错误引起,程序无法通过捕获错误来恢复。一般来说,程序不应该捕获Error类型的异常,而应该在发生Error时让程序终止。常见的Error包括OutOfMemoryError(内存耗尽)和StackOverflowError(栈溢出)等。
  • Exception: Exception是指程序运行时可能发生的问题,它可以通过捕获和处理来使程序继续执行。Exception又分为受检异常(Checked Exception)和非受检异常(Unchecked Exception)。受检异常是指在程序编译时需要处理的异常,而非受检异常是指在编译时不需要处理的异常。常见的Exception包括IOException(输入输出异常)和SQLException(数据库访问异常)等。

联系:

Error和Exception都继承自Throwable类,因此它们具有一些共同的特性,如堆栈跟踪和异常信息等。

常见的RuntimeException:

  • NullPointerException(空指针异常): 当试图在一个空对象上调用方法或访问属性时抛出。
  • ArrayIndexOutOfBoundsException(数组下标越界异常): 当试图访问数组中不存在的索引时抛出。
  • IllegalArgumentException(非法参数异常): 当传递给方法的参数不符合方法的要求时抛出。
  • ArithmeticException(算术异常): 当出现除以零的运算时抛出。
  • ClassCastException(类转换异常): 当试图将一个对象转换为它不是的类型时抛出。

15、抽象类和接口的区别是什么?

抽象类和接口是面向对象编程中两种不同的概念,它们在Java中有着明显的区别。

抽象类(Abstract Class):

  • 抽象类可以包含抽象方法和非抽象方法。抽象方法是没有实际实现的方法,需要子类去实现。非抽象方法有默认实现,子类可以选择性地重写这些方法。
  • 一个类只能继承一个抽象类(单继承性)。
  • 抽象类可以包含成员变量,可以有构造函数,可以拥有普通方法。
  • 抽象类可以有访问控制修饰符,可以定义成员变量,可以包含构造方法。

接口(Interface):

  • 接口中所有的方法都是抽象方法,没有方法体。
  • 一个类可以实现多个接口(多继承性)。
  • 接口中的成员变量隐式地是static和final的。
  • 接口不能包含构造函数。
  • 接口中的方法默认是public的,可以省略访问控制符,不能使用其他访问修饰符。

16、==和equals的区别

在 Java 中,== 和 equals() 方法的区别主要包括以下几点:

  • ==:它是一种基本的数据比较操作符,用于比较两个对象的引用(内存地址)是否相等。
  • equals():它是 Object 类中的方法,通常用于定义对象之间的逻辑相等性。

Object默认是判断地址是否相等, Long、Integer、Date、String等都重写了equals方法。

Object类

public boolean equals(Object obj) {
   
        return (this == obj);
    }

Long类

public boolean equals(Object obj) {
   
        if (obj instanceof Long) {
   
            return value == ((Long)obj).longValue();
        }
        return false
Java开发常见面试题面试中经常会被问到的问题。这些问题通常涵盖Java语言基础知识、面向对象编程、集合框架、多线程、异常处理、IO操作、数据库等方面。以下是一些可能被问到的Java开发常见面试题的例子: 1. 什么是Java虚拟机(JVM)?它的作用是什么? 2. 什么是面向对象编程(OOP)?Java中的类和对象有什么区别? 3. Java中的集合框架有哪些?分别介绍一下它们的特点和用途。 4. 什么是多线程?Java中如何创建和管理线程?如何实现线程间的通信? 5. 什么是异常处理?Java中的异常分类是什么?如何处理异常? 6. Java中的IO操作有哪些?分别介绍一下它们的特点和用途。 7. 如何连接和操作数据库?介绍一下JDBC的基本用法。 8. 什么是Java的反射机制?如何使用反射实现动态加载类和调用方法? 9. 什么是Java的注解(Annotation)?如何自定义注解? 10. 什么是Java的设计模式?列举一些常见的设计模式及其应用场景。 以上只是一些常见Java开发面试题的例子,面试时可能还会有其他问题涉及到更深入的知识。建议在面试前充分准备,熟悉Java语言基础知识和常用的开发技术,以便能够给出清晰且准确的答案。引用<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Java面试题大全带答案 110道(持续更新)](https://blog.csdn.net/u012889902/article/details/121614968)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值