2025Java常见面试题
2025-02-09 11:20:17 0 举报
AI智能生成
文件:Java核心技术(基础&进阶) 在这份Java核心技术概览中,我们将深入浅出地探讨Java语言的基础知识以及进阶特性,旨在为初学者和有经验的开发者提供实用而全面的指南。首先,我们会快速回顾Java的基本语法,包括数据类型、控制流语句、数组以及面向对象的程序设计原则。接下来,我们深入探讨Java的核心概念,如异常处理、集合框架以及泛型。此外,读者还将接触到Java的I/O系统、多线程与并发编程,以及网络编程的基础知识。进阶部分则专注于对Java高级特性的探索,例如反射API、注解、以及Java 8引入的Lambda表达式和函数式编程接口。最后,文档还将涵盖对Java虚拟机(JVM)工作机制的介绍,以及性能优化和调试的策略。每章都将配合精心设计的代码示例与实践练习,确保理论与实际应用的紧密结合,让每位学习者都能够扎实掌握Java编程的艺术。
作者其他创作
大纲/内容
Java基础
JDK,JRE,JVM三者的区别和联系
区别:
JDK:Java Develpment Kit ,java开发工具
JRE:Java Runtime Enviroment ,java运行环境
JVM:Java Virtual Machine ,java虚拟机
JDK:Java Develpment Kit ,java开发工具
JRE:Java Runtime Enviroment ,java运行环境
JVM:Java Virtual Machine ,java虚拟机
联系:
JDK = JRE(jre目录) + 开发工具集(例如Javac编译工具等)
JRE(jre目录) = JVM(bin目录) + Java SE标准类库(lib目录)
JDK = JRE(jre目录) + 开发工具集(例如Javac编译工具等)
JRE(jre目录) = JVM(bin目录) + Java SE标准类库(lib目录)
== 和 equals 的区别
== 对于基本类型比较的是值,对于引用类型比较的是地址
equals不能用于基本类型的比较;
如果没有重写equals,equals就相当于==,如果重写了equals方法,equals比较的是对象的内容
值传递和引用传递
值传递和引用传递的区别主要在于传递的内容修改后对源对象的影响,值传递不会改变实参的值,而引用传递会改变实参的值。
Java只有值传递,对于基本类型传递的是变量的副本;对于对象,传递的是对象的引用,源引用不会受影响
final 在java中有什么作用
final 修饰的类叫最终类,该类不能被继承。
final 修饰的方法不能被重写。
final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
continue 和 break 语句有什么区别
break语句是结束整个循环过程,
continue语句只结束本次循环,而不是终止整个循环的执行。
tryCatch执行流程
有异常:try---》catch--》finally
没异常:try--》finally
如果try或catch中有return,finally会在return前先执行
如果try和catch都有return,没有异常返回try的return;有异常返回catch的return;如果finally也有return则返回finally的return
String 和 StringBuilder、StringBuffer的区别
String 不可变的字符串。
StringBuffer 可变字符串,线程安全,效率低。
StringBuilder 可变字符串,线程不安全,效率高。
StringBuffer 可变字符串,线程安全,效率低。
StringBuilder 可变字符串,线程不安全,效率高。
不可变:当对字符串内容修改后,需要重新指定赋值区域
String 和 StringBuilder、StringBuffer 底层都是用char[]实现,扩容为2倍+2。
String 的无参构造创建了一个长度为0的char[],StringBuffer 和 StringBuilder 的无参构造创建了一个长度为16的char[]。
重载(Overload)和重写(Override)的区别
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
重载:一个类中有多个同名的方法,但是不同的参数列表(参数类型不同、参数个数不同或者二者都不同)。
重写:发生在子类与父类之间,子类对父类的方法进行重写,参数都不能改变,返回值类型可以不相同,但是必须是父类返回值的派生类。
普通类和抽象类有哪些区别
普通类不能包含抽象方法,抽象类可以有抽象方法
抽象方法不能被static、final修饰
普通类可以直接实例化,抽象类不能实例化
抽象类子类必须实现抽象类中的所有抽象方法
接口和抽象类有什么区别
接口用interface修饰,抽象类用abstract修饰
接口不能有构造函数,抽象类可以有
接口是多继承,抽象类是单继承
抽象类可以有实例变量,接口只能有常量
throw 和 throws 的区别
throw用于方法体内抛出具体的异常
throws用于方法的声明上,用来声明一个方法可能抛出的所有异常信息
Java四种引用类型:适当控制对象被回收的时机
强引用:不管什么情况都不会被回收
软引用:内存不足时会被回收
弱引用:不管内存是否不足都会回收
虚引用:任何时候都可能会被回收
强引用:不管什么情况都不会被回收
软引用:内存不足时会被回收
弱引用:不管内存是否不足都会回收
虚引用:任何时候都可能会被回收
IO流的分类
按流向分
输入流InputStream
输出流OutputStream
按角色分
节点流
处理流
按数据单位分
字节流
字符流
集合框架
Collection 和 Collections 有什么区别
Collection 是一个集合接口,用于存储单列数据,常用的子接口有Set、List
Collections 是一个操作Set、List、 Map 等集合的工具类。对集合元素进行排序、查询和修改等操作
List、Set、Map 之间的区别是什么
List存储有序,可重复的对象
Set存储无序,不可重复的对象
Map存储键值对象,提供key到value的映射
ArrayList、LinkedList 和 Vector 三者的异同
相同:三个类都实现List接口,存储有序,可重复的对象
不同:
ArrayList线程不安全,效率高,底层用Object数组存储,适用于查找
LinkedList底层使用双向链表存储,适用于修改操作,线程不安全
Vector线程安全,效率低,底层使用Object数组存储
如何实现数组和 List 之间的转换
toArray:转数组
asList:转List
List 常用方法
增:add(object obj)
删:remove(int index)
改:set(int index,object ele)
查:get(int index)
插:add(int index, object ele)
长度:size()
Map 常用方法
增: put(Object key,Object value)
删:remove(Object key)
改: put(Object key,Object value)
查:get(Object key)
遍历:keySet() 遍历所有key,values()遍历所有value,entrySet()遍历所有key-value
长度:size()
HashMap 和 Hashtable
与HashMap相比Hashtable是线程安全的,且不允许key、value是null。
Hashtable默认容量是11。HashMap 默认容量是16。
HashTable是直接使用key的hashCode作为hash值,HashMap是使用扰动函数对key的hashCode进行扰动后作为hash值
Hashtable扩容是原来的2倍+1,HashMap是扩容成原来的两倍
HashMap底层实现原理
HashMap 底层使用的数据结构(JDK1.8):数组 + 链表 + 红黑树
当实例化一个空参的 HashMap 时,在底层创建了一个初始容量为null 的一维数组(Node[])
为什么要改成“数组+链表+红黑树”:主要是为了提升在 hash 冲突严重时(链表过长)的查找性能,使用链表的查找性能是 O(n),而使用红黑树是 O(logn)。
hash冲突解决方法
1.开放地址法 发生冲突就去寻找下一个空的地址
2.再hash法 使用多个扰动函数
3.链地址法 把hash值相同的元素放在同一个链表中
什么时候用链表?什么时候用红黑树?
插入key-value时,当数组某一索引位置上的链表节点数大于等于9,且数组长度大于等于64时,会将该索引上的链表转换成红黑树;而当数组长度小于64时,会将数组进行扩容,因为此时的数据量还比较小
移除时,当数组某一索引位置上的链表节点数为6,并且为红黑树的形式,就会触发红黑树转链表
HashMap 有哪些重要属性
默认初始容量:16, 负载因子:0.75,临界值(扩容阈值):12,最大容量:2^30
HashMap插入流程
1、计算key的hashCode,把hashCode经过扰动函数处理后得到新的hash值
扰动过程:首先获取key的哈希值,然后将哈希值右移16位,再将右移后的hashCode与原来的hashCode做异或运算,再将运算后的结果返回。
2、如果table未初始化或者长度为0时,调用扩容方法
第一次扩容时,就是扩容成初始容量16
3、计算存放的索引位置
计算规则:(n - 1) & hash,n为数组长度
4、判断该索引位置上是否有节点
如果该位置为空,就把元素添加进数组索引处
如果该位置已有元素:将待添加元素的hash值与该位置上的hash值进行比较
如果两个hash值不同,就把待添加元素添加到原有元素的后面(JDK8尾插法,JDK7头插法)
如果两个key的hash值相同,再调用equals方法比较两个key
如果返回true,就用待添加元素替换原有元素
如果返回false,就把待添加元素添加到原有元素的后面
HashMap扩容流程
数组是否初始化
未初始化:扩容成初始容量16
已初始化
判断老数组容量是否超过上限(2的30次方)
是,就把最大的整数Integer.MAX_VALUE赋值给临界值
否,容量和扩容阈值都变为原来的两倍
遍历处理老数组
如果该索引位置只有一个节点,计算该节点在新数组存放的索引位置,然后直接放入新数组
如果该索引位置不止一个节点
如果是红黑树节点,遍历红黑树节点,红黑树在新数组存放索引位置:hash&oldCap(老数组容量)
如果是链表节点,遍历链表节点,链表在新数组存放索引位置:hash&oldCap(老数组容量)
网络编程
简述 tcp 和 udp的区别
TCP协议:
使用TCP协议前,须先建立TCP连接,形成传输数据通道;
传输前,采用“三次握手”方式,点对点通信,是可靠的;
TCP协议进行通信的两个应用进程:客户端、服务端;
在连接中可进行大数据量的传输;
客户端和服务端界限明确;
传输完成后就释放连接,效率低。
使用TCP协议前,须先建立TCP连接,形成传输数据通道;
传输前,采用“三次握手”方式,点对点通信,是可靠的;
TCP协议进行通信的两个应用进程:客户端、服务端;
在连接中可进行大数据量的传输;
客户端和服务端界限明确;
传输完成后就释放连接,效率低。
三次握手:①客户端请求连接服务端;②针对客户端的请求确认应答,并请求建立连接;③针对服务端的请求确认应答,建立连接;
UDP协议:
将数据、源、目的封装成数据包,不需要建立连接;
每个数据报的大小限制在64K内;
发送不管对方是否准备好,接收方收到也不确认,故是不可靠的;
可以广播发送。
将数据、源、目的封装成数据包,不需要建立连接;
每个数据报的大小限制在64K内;
发送不管对方是否准备好,接收方收到也不确认,故是不可靠的;
可以广播发送。
tcp/ip四层协议
应用层 http
传输层 tcp,udp
网络层 ip
数据链路层 网线
反射
反射概述:Java的反射是指程序在运行期可以拿到一个对象的所有信息(对象,方法,属性)
反射优缺点
优点:可以实现动态创建对象和编译,提高灵活性和可扩展性
缺点:性能差,可读性差
反射相关的API
java.lang.reflect.Class类:实现反射的核心类,获取类的对象
获得Class类实例的五种方式
方式一:调用Class类的静态方法 forName(String className)
Class c1 = Class.forName("com.cheng.reflection.User");
Class c1 = Class.forName("com.cheng.reflection.User");
方式二 已知某个类的实例,调用该实例的getClass()方法
Class c2 = user.getClass();
Class c2 = user.getClass();
方式三 已知具体类,通过类的class属性获取,该方法最安全可靠,程序性能最高
Class c3 = User.class;
Class c3 = User.class;
方式四:通过基本内置类型的包装类的TYPE属性获得CLass实例
以int的包装类Intege类为例 源码:public static final Class<integer> TYPE = (Class<integer>) Class.getPrimitiveClass("int");
Class<integer> c4 = Integer.TYPE;</integer></integer></integer>
以int的包装类Intege类为例 源码:public static final Class<integer> TYPE = (Class<integer>) Class.getPrimitiveClass("int");
Class<integer> c4 = Integer.TYPE;</integer></integer></integer>
方式五:通过当前子类的Class对象获得父类的Class对象
Class c5 = c1.getSuperclass();//c1为子类的CLass对象
Class c5 = c1.getSuperclass();//c1为子类的CLass对象
Class的理解
针对于编写好的.java文件进行编译,会生成一个或多个.class文件。接着使用java.exe命令对指定的.class文件进行解释运行。这个解释运行的过程中,我们需要将.class字节码文件使用类加载器加载到内存中(方法区),加载到内存中的.class文件对应的结构即为Class的一个实例
Class可以指向java所有的类型
java.lang.reflect.Method:代表类的方法
getDelcaredMethod()
java.lang.reflect.Field:代表类的属性
getDealaredField()
java.lang.reflect.Constructor:代表类的构造器
getDeclaredConstructor()
stream流
中间操作
筛选与切片:
filter(Predicate predicate):过滤Stream中所有不符合predicate的元素。
limit(long maxSize):该方法用于保证对该流的后续访问中最大允许访问的元素个数,这是一个有状态的,短路方法。
skip(n):跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。
distinct:通过流所生成元素的 hashCode() 和 equals() 去除重复元素,需要重写hashCode方法
filter(Predicate predicate):过滤Stream中所有不符合predicate的元素。
limit(long maxSize):该方法用于保证对该流的后续访问中最大允许访问的元素个数,这是一个有状态的,短路方法。
skip(n):跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。
distinct:通过流所生成元素的 hashCode() 和 equals() 去除重复元素,需要重写hashCode方法
映射:
map:接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
map:接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
排序:
sorted():自然排序(Comparable)
sorted(Comparator com):定制排序(Comparator)
sorted():自然排序(Comparable)
sorted(Comparator com):定制排序(Comparator)
终止操作
查找与匹配:
allMatch:检查是否匹配所有元素
anyMatch:检查是否至少匹配一个元素
noneMatch:检查是否没有匹配的元素
findFirst:返回流中的第一个元素
findAny:返回流中任意一个元素
max:返回流中的最大值
min:返回流中的最小值
count() :返回流中元素的数量。
orEach(Consumer action):遍历流中所有元素,对每个元素执行action。
allMatch:检查是否匹配所有元素
anyMatch:检查是否至少匹配一个元素
noneMatch:检查是否没有匹配的元素
findFirst:返回流中的第一个元素
findAny:返回流中任意一个元素
max:返回流中的最大值
min:返回流中的最小值
count() :返回流中元素的数量。
orEach(Consumer action):遍历流中所有元素,对每个元素执行action。
归约:
reduce(T identity,BinaryOperator) / reduce(BinaryOperator):可以将流中元素反复结合起来,得到一个值。
reduce(T identity,BinaryOperator) / reduce(BinaryOperator):可以将流中元素反复结合起来,得到一个值。
收集:
collect—将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
collect—将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
设计模式
设计原则
开闭原则:对扩展开放,对修改关闭
里氏代换原则:子类可以扩展父类的功能,但不能改变父类原有的功能
依赖倒转原则:高层模块不应该依赖底层模块,两者都应该依赖其抽象;细节应该依赖于抽象
接口隔离原则:一个类对另一个类的一来应该建立在最小接口上
迪米特法则:如果两个实体无须直接通信,那么就不应当发生相互调用,可以通过第三方转发该调用。其目的是减低耦合度
合成复用原则:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承的关系来实现
单例模式
public class Singleton{}

收藏
0 条评论
下一页