JAVA基础面试题(第一期)

85 阅读11分钟

1.什么是序列化和反序列化?

  • 序列化 序列化是将对象转换成字节流的过程,方便与网络传输和持久化存储,java提供了Serializable接口来方便实现序列化,只要实现了这个接口就可以进行序列化
  • 反序列化 是指将字节流重新转换成对象的过程,从字节流中读取信息然后重新创建对象

2.什么是JAVA中不可变类?

java中不可变类是指被final关键字修饰的类,一旦被创建之后其属性(字段)就不可以被修改

final关键字修饰类时不可被继承,修饰方法时不能被重写(但是可以被重载),修饰字段时属性不可以被改变

3.JAVA中Exception和Error有什么区别?

Error和Exception都是继承自Throwable类,其中Error一般指的是JVM层级的内部错误而Exception是指可以被处理的异常

Exception分为checkedException(编译时异常)和uncheckedException(运行时异常),其中编译时异常需要被显示处理,是可以提前预见的(比如IOException),通过try-catch捕获处理或者用throw抛出

4.你认为JAVA的优势是什么?

可以从跨平台,垃圾回收,生态,面向对象四个方面进行处理

跨平台:JAVA是运行在JVM中的,所以不论在什么机器上都可以运行

垃圾回收:JVM中有垃圾回收机制,可以帮助我们管理内存,不需要我们去手动分配内存,可以将注意力集中在代码编写上

生态:JAVA有着非常庞大的生态

面向对象:JAVA是一个严格的面相对象的编程语言有助于代码的可维护性和扩展性

5.什么是JAVA的多态性?

java多态指的是同一个接口或者父类的引用可以指向不同的实例对象,并根据具体的实例对象来执行相应的方法

优点:增强了系统的可扩展性,降低了代码的耦合度

6.JAVA中的参数传递是按值还是按引用?

JAVA中参数传递对于基础类型来说传递的是副本,对于引用类型对象传递的是“引用”即这个对象的地址

所以即使是传入引用,也可以改变这个对象内部的属性

7.JAVA为什么不支持多继承?

因为可能会出现菱形继承问题,如果B,C是A的子类,并且都实现了A的一个方法,假设支持多继承,如果现在D同时继承了B,C那么当子类D想要调用父类A的一个方法的时候就不知道是要调用B的还是调用C的了

扩展:为什么可以多实现呢?

java8之前如果要实现一个类就必须要实现这个类的所有方法,这样就不会出现子类要调用父类的方法了

但是JAVA8之后出现了默认方法(defuault method),为了避免菱形问题再次发生,java强制规定,当多个接口拥有相同的默认方法的时候,子类必须要重写这个方法

8.JAVA面向对象编程和面相过程编程的区别是什么?

面向对象编程:指以对象为中心的一种编程风格,把类或对象当做基本单元来组织代码

面相过程编程:指以过程或者函数为中心的一种编程风格,把过程当做基本单元来组织代码

9.JAVA重载和重写有什么区别?

  • 发生场所:

重载发生在同一个类中,重写发生在父子类中

  • 条件不同:

重载只要求参数名相同,对参数列表,返回值类型,final修饰等都没有要求

重写要求参数列表,参数名,返回值类型都要相同

重载既可以重载静态方法也可以重载非静态方法,重写只能重写非静态方法

  • 访问修饰符:

重载没有限制,重写的方法的修饰符不能比父类的更加严格

10.什么是JAVA的内部类?有什么作用?

JAVA内部类分为

成员内部类(非静态):可以访问外部类的所有所有成员,包括私有成员

静态内部类:无法访问外部类的非静态成员变量,只能访问静态成员变量

局部内部类:只能在局部内访问

匿名内部类:(常用于回调函数等)

11.JAVA8有哪些新特性?

  • 引入了Lambda表达式
  • 引入日期类,接口的默认方法,静态方法
  • 新增Stream流接口
  • 引入Optional类

Lambda表达式:

类似于js中的匿名函数

日期类:

常用:LocalDataTime.now()可以直接获取当前时间

输出的时间格式是 LocalDateTime 的默认字符串表示形式,通常是 yyyy-MM-ddTHH:mm:ss.nnnnnn (例如: 2025-02-17T15:30:45.123456 )

创建一个DateTimeFormatter 类来进行时间格式化

 LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDate = now.format(formatter);
        System.out.println(formattedDate);  // 输出示例:2025-02-17 15:30:45

接口的默认方法和静态方法

java8之后提供了默认方法可以使得接口创建默认方法,此时子类继承的时候就不必实现这个方法

Stream流式接口

Stream流是JAVA8引入的一个高级迭代器用于处理集合元素(Collections)

Stream流只会遍历一次

创建流:

数组创建流:Arrays.stream()或者Stream.of()方法

集合创建流:直接调用集合中的stream()方法或者使用parallelStream()方法创建并发流

操作流:

可以使用.filter方法对数据进行过滤,

映射:使用.map()方法将流中的元素转换成新的流

匹配:使用anyMatch()匹配(只要有一个满足即返回true

allMatch()所有的都满足才返回True

noneMatch()只要有一个满足传入条件就返回false,全部不满足才返回true

组合:reduce()方法

image.png

转换流:将流转换成集合或数组

使用toArray()方法将集合转换成数组

使用collect()方法将集合转换成List()或者其他,比如collect(Collector.toList())

Collectors 是一个收集器的工具类,内置了一系列收集器实现,比如说 toList() 方法将元素收集到一个新的 java.util.List 中;比如说 toCollection() 方法将元素收集到一个新的 java.util.ArrayList 中;比如说 joining() 方法将元素收集到一个可以用分隔符指定的字符串中。

Optional类

用处:优雅地处理可能为null的值,避免显示处理null

创建optional类:

使用静态方法empty(),of(value),ofNullable(value)来创建optional对象

比如Optional option=Optional.ofNullable<>(),这个泛型就是即将要存入对象的泛型

可以使用.isPresent()方法和isEmpty()方法来判断值是否存在(即是否为null)

使用orElse()和orElseGet()方法来处理如果值为null的时候应该怎么做

image.png

Optional中也有filter()方法和Map()方法,通过这两个方法返回新的Optional对象

12.JAVA中Stirng,StringBuffer,StringBuilder之间有什么区别?

String为不可变类,不利于频繁增删改这样的操作

StringBuilder和StringBuffer都是可变的,其中StringBuilder是非现成安全的,StringBuffer是线程安全的

13.JAVA中StringBuilder是如何实现的?

内部使用 char数组(char[] value)来保存字符串序列,当需要增删改的时候直接改变字符数组而不是像String类型一样创建一个新的对象返回;操作字符串的时候如果容量不足会直接扩容两倍来减少扩容容量,提高扩容性能

14.JAVA中基本类型和包装类型的区别是什么?

基本类型有:boolean,char,byte,short,int ,float,long,double

是可以直接存储数值的变量,位于栈上(局部变量在栈上,成员变量在堆上,静态字段在方法区),性能较高且不支持Null

包装类型有:Boolean,character,Byte,Short,Integer,Long,Float,Double

包装类型是类,存储在堆中,可以用于面向对象编程,并且支持null,可以用于面向对象编程

扩展:java中很多地方都是用对象所以会设计自动装(拆)箱

装箱:将基本类型转换成包装类型

拆箱:将包装类型重新转换成基本类型

缓存机制:比如Integer的缓存机制(就是-128~127之间的数很常用所以创建了一个缓存区,用来存放值在这个范围的对象,这样如果两个Integer对象的值相同,这两个Integer对象不是一样的,但是其内部的值指向的是同一个缓存区内的对象)

15.接口和抽象类有什么区别?

接口是自上而下的,是提前知道了一些行为,为了约束这些行为创建出一个接口来进行规范

而抽象类是自下而上的,是写了多个代码之后发现有重复的地方,为了减少代码的复用,将这些公共逻辑封装成一个抽象类减少代码的冗余

  • 方法实现

接口中的方法默认是public和abstract的(java8之后可以有静态方法和默认方法)

抽象类可以包含abstract方法和具体的方法,并且子类可以调用这些具体的方法

  • 构造函数和成员变量 接口不能包含构造函数,接口默认变量类型为public static final,即常量 抽象类可以包含构造函数,并且对成员没有限制

16.JDK和JRE有什么区别?

JDK:java开发工具包

JRE:java运行环境

JRE包含JVM和其他类库

JDK包含完整的JRE和其他开发工具,如编译器(javac),java文档生成器(javadoc)

打包工具(jar),调试器(jdb)等

17.你是用过那些JDK提供的工具?

  1. java命令,运行java应用程序的命令,使用JVM来解释并执行编译后的字节码文件
  2. javac:java编译器,负责将java源代码编译成字节码(.class文件)
  3. javadoc:java文档生成器,用于生成API文档
  4. jar:用来打包
  5. jdb:java调试工具可以在命令行中调试java应用程序,支持断点设置,变量查看等功能

18.JAVA中hashCode()和equals()方法和==有什么区别?

==方法

对于基本类型变量是判断值是否相等

对于引用类型变量判断是否为同一个对象(即内存地址是否相等)

equals()方法,object类中的方法,不过现在大部分类都自主重写了这个方法 ,用于引用类型判断值是否相等

hashCode()方法,返回对象的哈希码,Object类(默认会根据内存地址来生成哈希码)中的方法,基本上每一个类都会重写hashCode()方法

tip:如果两个对象的值equals()方法判断是相等的,那么他们的hashCode()方法也一定是相等的,

反之:如果hashCode()方法是相等的,他们的equals方法不一定相等但是会被放在同一个哈系桶中

因为大部分hashCode()方法都是根据值算出来的

19.JAVA中hashCode()和equals()方法有什么联系?

1.如果两个对象的值equals()方法判断是相等的,那么他们的hashCode()方法也一定是相等的,

反之:如果hashCode()方法是相等的,他们的equals方法不一定相等但是会被放在同一个哈系桶中

因为大部分hashCode()方法都是根据值算出来的

2.在hashMap或者hashSet存储的数据中如果重写了equals()方法就一定要重写hashCode()方法,都则可鞥会造成hashCode和hashMap不能正确的保存和检索值

20.什么是JAVA中的动态代理?

java动态代理是一种在运行时创建代理对象的机制,可以使在运行时决定对象的行为,而不用在编译的时候就确定

可以在不修改类的情况下对其进行修改

扩展:java动态代理只能堆接口进行代理不支持对类进行代理

CGLIB代理:通过字节码技术可以实现对类进行代理

AOP技术就是使用JAVA动态代理和CGLIB代理,默认时使用java代理,如果要代理的类没有实现接口就使用CGLIB进行代理

21.JDK动态代理和CGLIB代理有什么区别?

jdk动态代理:

基于接口,要求目标类(被代理的类)必须实现一个或多个接口,并且只能代理目标类中实现接口的方法

也就是说如果这个目标类自己定义了一个方法不是接口中的方法,那么这个方法是不能被java动态代理的,需要使用CGLIB代理

原理:根据接口生成代理类,将代理类的方法转发到InvocationHandler 的 invoke() 方法,在这里定义对代码的增强

CGLIB代理:通过生成目标类的子类来进行代理,所以这个目标类不能是final类,方法也不能是fianl方法