当前位置: 首页 > article >正文

Java基础知识-面试题

一、重写和重载的区别

重写 (Override)定义:

重写是指子类提供父类中已有的方法的具体实现。这允许子类改变方法的行为而不改变方法的签名。

  • 发生时机:重写发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。
  • 访问修饰符:子类中的方法不能比父类中的访问级别更严格。例如,如果父类方法是public,那么子类中重写的方法也必须是public。
  • 注意事项:重写的方法应该保持相同的方法签名(包括返回类型、方法名和参数列表)。对于Java 5及之后版本,如果父类的方法返回类型是某个类,则子类可以将返回类型改为该类的子类(协变返回类型)。
  • 关键字:在Java中,可以使用@Override注解来表明一个方法意在重写父类的方法。这有助于编译器检查是否有匹配的方法用于重写,从而减少错误。

重载 (Overload)定义:

重载是在同一个类中定义多个同名的方法,但是这些方法具有不同的参数列表(不同的参数数量或不同类型的参数)。

  • 发生时机:发生在同一个类中(或者父类和子类之间),方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
  • 访问修饰符:重载方法之间可以有不同的访问修饰符,因为它们被视为独立的方法。
  • 注意事项:方法的返回类型不参与区分重载方法;也就是说,不能仅通过返回类型的不同来重载方法。此外,方法的异常列表也不影响方法重载。
  • 关键字:没有特定的关键字用于表示方法重载。

二、Java三大特征

Java面向对象的三大特征为:封装、继承和多态。

1.封装

Java中的封装是指一个类把自己内部的实现细节进行隐藏,只暴露对外的接口(setter和getter方法)。封装又分为属性的封装和方法的封装。把属性定义为私有的,它们通过setter和getter方法来对属性的值进行设定和获取。

2.继承


Java中的继承是指在一个现有类(父类)的基础上在构建一个新类(子类),子类可以拥有父类的成员变量以及成员方法(但是不一定能访问或调用,例如父类中private私有的成员变量以及方法不能访问和调用)。继承的作用就是能提高代码的复用性。子类拥有父类中的一切(拥有不一定能使用),它可以访问和使用父类中的非私有成员变量,以及重写父类中的非私有成员方法。

3.多态


多态就是指多种状态,就是说当一个操作在不同的对象时,会产生不同的结果。

在Java中,实现多态的方式有两种,一种是编译时的多态,另外一种是运行时多态,编译时的多态是通过方法的重载实现的,而运行时多态是通过方法的重写实现的。

方法的重载是指在同一个类中,有多个方法名相同的方法,但是这些方法有着不同的参数列表,在编译期我们就可以确定到底调用哪个方法。

方法的重写,子类重写父类中的方法(包括接口的实现),父类的引用不仅可以指向父类的对象,而且还可以指向子类的对象。当父类的引用指向子类的引用时,只有在运行时才能确定调用哪个方法。

其实在运行时的多态的实现,需要满足三个条件:1.继承(包括接口的实现)2.方法的重写 3.父类的引用指向子类对象

三、抽象和接口的区别

(1)抽象类可以包含具体的方法和成员变量,而接口不能包含具体的方法和成员变量。

(2)一个类只能继承一个抽象类,而一个类可以实现多个接口。

(3)抽象类的目的是为了作为其他类的基类,而接口的目的是为了描述一个对象可以做什么。

(4)抽象类中的抽象方法必须在子类中实现,而接口中的所有方法都必须在实现类中实现。

(5)抽象类可以有构造方法,而接口不能有构造方法。

(6)抽象类可以拥有非抽象方法,而接口只能拥有抽象方法。

(7)抽象类中的访问修饰符可以是public、protected和default,而接口中的访问修饰符只能是public。

(8)抽象类可以拥有静态方法和静态变量,而接口只能拥有常量。

四、深拷贝和浅拷贝

浅拷贝:创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。因此,原始对象及其副本引用同一个对象。

深拷贝:创建一个新对象,然后将当前对象的非静态字段复制到该新对象,无论该字段是值类型的还是引用类型,都复制独立的一份。当你修改其中一个对象的任何内容时,都不会影响另一个对象的内容。

五、​String、StringBuffer、StringBuilder 的区别​

可变性

String 是不可变的(后面会详细分析原因)。

StringBuilderStringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串,不过没有使用 finalprivate 关键字修饰,最关键的是这个 AbstractStringBuilder 类还提供了很多修改字符串的方法比如 append 方法。

线程安全性

String 中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilderStringBuilderStringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacityappendinsertindexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

性能

每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

对于三者使用的总结:

  • 操作少量的数据: 适用 String
  • 单线程操作字符串缓冲区下操作大量数据: 适用 StringBuilder
  • 多线程操作字符串缓冲区下操作大量数据: 适用 StringBuffer

String 为什么是不可变的

String 类中使用 final 关键字修饰字符数组来保存字符串

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
  //...
}

 

final 关键字修饰的类不能被继承,修饰的方法不能被重写,修饰的变量是基本数据类型则值不能改变,修饰的变量是引用类型则不能再指向其他对象。因此,final 关键字修饰的数组保存字符串并不是 String 不可变的根本原因,因为这个数组保存的字符串是可变的(final 修饰引用类型变量的情况)。

String 真正不可变有下面几点原因:

保存字符串的数组被 final 修饰且为私有的,并且String 类没有提供/暴露修改这个字符串的方法。

String 类被 final 修饰导致其不能被继承,进而避免了子类破坏 String 不可变。

六、时间类的转换是怎么进行的

String 转换成Date


 String 转Date
       SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
       Date date = sdf2.parse("2020-03-06");
       System.out.println("补充1:String 转Date----"+date);

Date转换成String

 将Date 转换成String
       System.out.println("补充2:Date 转String------"+sdf2.format(date));

七、 第三方API是怎么在项目中运用的

设置构建工具

大多数现代Java项目使用构建工具如Maven或Gradle来管理依赖关系。确保你的项目已经配置了其中一个工具。

Maven:在pom.xml文件中添加依赖项。

添加依赖项

根据第三方API的说明,在项目的构建文件中添加相应的依赖项。在Maven的pom.xml中添加对应api的依赖像。

编写代码调用API

按照API文档提供的指导编写代码,以调用API提供的服务。

八、自动拆箱和装箱的原理

自动装箱就是 Java 自动将原始类型值转换成对应的对象,比如将 int 的变量转换成 Integer 对象,这个过程叫做装箱,反之将 Integer 对象转换成 int 类型值,这个过程叫做拆箱。因为装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。

装箱过程是通过调用包装器的 valueOf 方法实现的,而拆箱过程是通过调用包装器的 xxxValue 方法实现的。

九、如何自定义异常

  • 创建自定义异常类要创建一个自定义异常,需要做的是定义一个新的类,该类直接或间接地继承自java.lang.Throwable类,通常是继承自Exception或RuntimeException。
  • 如果你创建的异常是受检异常(checked exception),你应该继承Exception类。  
  • 如果你想创建非受检异常(unchecked exception),那么应该继承RuntimeException类。
public class MyCheckedException extends Exception {
    public MyCheckedException(String message) {
        super(message);
    }

    public MyCheckedException(String message, Throwable cause) {
        super(message, cause);
    }
}

 

十、项目中的异常是怎么处理的

使用try-catch-finally块

这是最基本也是最常用的异常处理机制。try块内放置可能抛出异常的代码,catch块用于捕获并处理异常,而finally块(可选)无论是否发生异常都会执行,通常用于清理资源。

使用自定义异常

创建自定义异常可以帮助更精确地表达业务逻辑中的错误情况。通过定义自己的异常类,可以使代码更加清晰易懂,并且便于维护。

使用异常处理框架

对于大型项目,可以考虑使用专门的异常处理框架(如Spring AOP结合自定义注解),它们可以提供统一的异常处理方式,简化跨层异常管理。

定义全局异常处理器

对于Web应用程序,定义一个全局异常处理器(例如,在Spring MVC中使用@ControllerAdvice和@ExceptionHandler注解)可以集中处理所有未被捕获的异常,提供统一的响应格式。

十一、全局异常拦截如何实现?

SpringBoot中,@ControllerAdvice 即可开启全局异常处理,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用@ExceptionHandler注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。


@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(value =Exception.class)
    @ResponseBody
    public String exceptionHandler(Exception e){
        System.out.println("全局异常捕获>>>:"+e);
        return "全局异常捕获,错误原因>>>"+e.getMessage();
    }
}


http://www.kler.cn/a/470359.html

相关文章:

  • 2024AAAI SCTNet论文阅读笔记
  • 【Linux】传输层协议UDP
  • 毕业项目推荐:基于yolov8/yolov5的行人检测识别系统(python+卷积神经网络)
  • Python编程实例-特征向量与特征值编程实现
  • 新年到了!使用Python创建一个简易的接金元宝游戏
  • 源代码编译安装X11及相关库、vim,配置vim(1)
  • 智能服装推荐系统 协同过滤余弦函数推荐服装 Springboot Vue Element-UI前后端分离
  • react vscode prettier 格式化代码
  • 数据结构 - blocks
  • freertos官网源码烧录stlink注意配置
  • javascript e.preventDefault() 的作用和用法
  • Unity3D仿星露谷物语开发18之添加道具到库存栏
  • 按键精灵ios脚本教程:用函数来实现将图片保存到相册
  • Elasticsearch VS Easysearch 性能测试
  • Golang学习笔记_18——接口
  • 海外云服务器能用来做什么?
  • python 如何调整word 文档页眉页脚
  • 移动电商的崛起与革新:以开源AI智能名片2+1链动模式S2B2C商城小程序为例的深度剖析
  • 培训机构Day23
  • 在 Vue 中使用 @ngageoint/geopackage 实现 GeoPackage 数据处理与可视化
  • 常见转义字符
  • 人工智能安全——联邦学习的安全攻击与防护
  • Map集合
  • QT6编程入门(一)
  • 每日一题:BM2 链表内指定区间反转
  • 分布式搜索引擎之elasticsearch基本使用3