一、选择题
1、ArrayList list = new ArrayList(20);语句中的 list 集合大小扩充了几次(A)
-
A.0
-
B.1
-
C.2
-
D.3
2、如果去掉了 main 方法的 static 修饰符会怎样(B)
-
A.程序无法翻译
-
B.程序能正常编译,运行时或抛出NoSuchMethodError异常
-
C.程序能正常编译,正常运行
-
D.程序能正常编译,正常运行一会会立刻退出
3、启动 java 程序进程时,输入一下哪个参数可以实现年轻代的堆大小为 50M(C )
-
A.-Xms50M
-
B.-Xmx50M
-
C.-Xmn50M
-
D.-Xss50M
4、下面哪些是 Thread 类的方法(A,B)
-
A.start()
-
B.run()
-
C.exit()
-
D.getPriority()
5、以下语句输出的结果是什么(C)
System.out.print(Integer.MAX_VALUE*2);
System.out.print(Integer.MIN_VALUE*2);
-
A. -2-1
-
B. -1-2
-
C. -20
-
D. -1-1
6、log4j 的优先级从高到低的排序为(A)
-
A. error>warn>info>debug
-
B. warn>info>debug>error
-
C. warn >debug>error>info
-
D. error>warn>debug>info
7、下列哪些方法可以使线程从运行状态进入到阻塞状态(BCD)
-
A.notify
-
B.wait
-
C.sleep
-
D.yield
8、下列关于 Thread 类提供的线程控制的方法中,错误的一项是(A)
-
A. 在线程A中执行线程B的join()方法,则线程A等待直到B执行完成
-
B. 线程A通过调用interrupt()方法来中断其阻塞状态。
-
C. currentThread()方法返回当前线程的引用
-
D. 若线程A调用方法isAlive()返回为true,则说明 A正在执行中
9、设 String s1 =”Topwalk”;String s2 =”Company”; 以 下 方 法 可 以 得 到 字 符 串“TopwalkCompany” 有:(ABD)
-
A. s2+s1;
-
B. s1.concat(s2)
-
C. s1.append(s2);
-
D.StringBuffer buf = new StringBuffer(s1);buf.append(s2);
10、String a = new String(“1”+”2”)最终创建了几个对象(B)
-
A.1
-
B.2
-
C.3
-
D.4
11、int 类型占用(C)个字节?
-
A.2
-
B.4
-
C.8
-
D.16
12、下列那一条语句可以实现快速的复制一张数据库表(C)
-
A. select * into b from a where 1<>1;
-
B. creat table b as select * from a where 0=1;
-
C. insert into b as select * from a where 1<>1;
-
D. insert into b select * from a where 1<>1;
13、选择 Oracle 的分页语句的关键字(A)
-
A. rownum
-
B. limit
-
C.TOP
-
D. pagenum
14、选出可以查询出所有的表和视图的方法:(B)
-
A.preparedStatement.getMetaData().getTables(***);
-
B.connection.getMetaData().getTables(***);
-
C.result.getMetaData().getTables(***);
-
D..DiverManager.getMeta().getTables(***);
15、可以监控到数据库变化的机制有哪些(AB)
-
A. 存储过程
-
B. 数据库日志
-
C. 触发器
-
D. 物化视图
16、清空表所有数据的性能最优的语句是哪一个(B)
-
A. delete from tsuer;
-
B. truncate table tuser;ss
-
C. drop table tuser;
-
D. delete tuser;
17、文件对外共享的协议有哪几个(AB)
-
A. FTP
-
B. Windows共享
-
C. TCP
-
D.SSH
18、关于 Java 中国特殊符号的用法正确的是(AD)
-
A. 判断一个字符串str中是否含有“.”,可以根据str.indexOf(“.”)是否等于-1判断。
-
B. 判断一个字符串str是否含有“.”,可以根据str.indexOf(“\\.”)是否等于-1判断。
-
C. 根据“.”分隔字符串str的写法可以是str.split(“\\.”)
-
D. 根据“.”分隔字符串str的写法可以是str.split(“.”)
19 、请问 java 关键字?(CD)
-
A. run
-
B. low
-
C. import
-
D. implement
20、以下哪些不属于约束(CD)
-
A.主键
-
B.外键
-
C.索引
-
D.唯一索引
-
E.not null
21、下列关于数据库连接池的说法中哪个是错误的(D)
-
A. 服务器启动时会初始建立一定数量的池连接,并一直维持不少于此数目的池连接
-
B.客户端程序需要连接时,池驱动程序会返回一个使用的池连接并将其使用计数加1;
-
C. 如果当前没有空闲连接,驱动程序就会再新建一定数量的连接,新建连接的数量可以由配置参数决定。
-
D. 当使用池连接调用完成后,池驱动程序将此连接标记为空间,其他调用就可以使用这个连接
22、以下哪句是对索引的错误描述(C)
-
A. 选择性差的索引只会降低DML语句的执行速度
-
B. 选择性强的索引只有被Access Path使用到才是有用的索引
-
C. 过多的索引只会阻碍性能的提升,而不是加速性能
-
D.在适当的时候将最常用的列放在复合索引的最前面
-
E. 索引和表的数据都存储在同一个Segment中
23、关于锁 locks,描述正确的是(A)
-
A. 当一个事务在表上防止了共享锁(shared lock),其他事务,能阅读表里的数据
-
B. 当一个事务在表上防止了共享锁(shared lock),其他事务,能更新表里的数据
-
C. 当一个事务在表上防止了排他锁(exclusive lock),其他事务,能阅读表里的数据
-
D. 当一个事务在表上防止了排他锁(exclusive lock),其他事务,能更新表里的数据
24、如下那种情况下,Oracle 不会使用 Full Table Scean(D)
-
A.缺乏索引,特别是在列上使用了函数,如果要利用索引,则需要使用函数索引。
-
B.当访问的数据占整个表中的大部分数据时
-
C.如果时一个表的high water mark 数据块数少于初始化参数DB_FILE_MULTIBLOCK_READ_COUNT
-
D.本次查询可以用到该张表的一个引用,但是该表具有多个索引包含用于过滤的字段
二、常见问答题
2.1 Java基础系列面试题
1. JDK 和 JRE 有什么区别?
- JDK (Java Development Kit):是Java的开发工具包,包含了用于开发Java应用程序的工具,如编译器 (
javac
)、调试器、Javadoc、Java运行时环境(JRE)等。开发者使用JDK来编写和测试Java程序。 - JRE (Java Runtime Environment):是Java的运行时环境,包含了执行Java程序所需的核心类库和Java虚拟机(JVM)。JRE不包含开发工具,只提供运行Java应用程序的环境。
2. == 和 equals 的区别是什么?
- ==:用于比较基本数据类型的值或比较对象的引用是否相同。对于对象,
==
比较的是两个对象在内存中的地址。 - equals():是一个方法,用于比较对象的内容是否相等。对于大多数类,
equals()
方法需要重写,以提供基于内容的比较。
3. 两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?
不一定。根据 Java 的 hashCode()
规范,如果两个对象的 equals()
方法返回 true
,那么它们的 hashCode()
方法必须返回相同的值;但是如果两个对象的 hashCode()
相同,它们不一定相等。因此,hashCode()
仅保证相等性而非相反。
4. final 在 Java 中有什么作用?
- final 关键字用于修饰类、方法和变量:
- 类:被修饰的类不能被继承。
- 方法:被修饰的方法不能被子类重写。
- 变量:被修饰的变量只能被赋值一次,之后无法改变。
5. String 属于基础的数据类型吗?
不,String
是一个对象类型,不是基本数据类型。基本数据类型包括 int
、char
、boolean
等,String
是一个类,用于表示字符串。
6. Java 中操作字符串都有哪些类?它们之间有什么区别?
- String:不可变的字符串对象。
- StringBuilder:可变的字符串对象,适合频繁修改字符串的场景,线程不安全。
- StringBuffer:可变的字符串对象,线程安全,适合在多线程环境中使用。
7. String str="i"与 String str=new String("i")一样吗?
不完全一样:
String str = "i"
:使用字符串常量池,可能会重用已存在的相同字符串。String str = new String("i")
:总是创建一个新的String
对象,不论池中是否已有相同内容的字符串。
8. 如何将字符串反转?
可以使用 StringBuilder
的 reverse()
方法:
String str = "hello"; String reversed = new StringBuilder(str).reverse().toString();
9. String 类的常用方法都有那些?
length()
:返回字符串长度。charAt(int index)
:返回指定位置的字符。substring(int beginIndex, int endIndex)
:返回子字符串。indexOf(String str)
:返回子字符串首次出现的索引。toLowerCase()
、toUpperCase()
:转换大小写。trim()
:去掉前后空格。equals(Object obj)
:比较内容是否相等。split(String regex)
:按指定正则表达式分割字符串。
10. 抽象类必须要有抽象方法吗?
不一定。抽象类可以包含抽象方法,也可以不包含。即使没有抽象方法,它仍然可以包含具体方法和状态。
11. 普通类和抽象类有哪些区别?
-
抽象类:
- 不能实例化。
- 可以包含抽象方法和具体方法。
- 用于提供部分实现和共享代码。
-
普通类:
- 可以实例化。
- 不能包含抽象方法(除非是抽象类的子类)。
12. 抽象类能使用 final 修饰吗?
可以,抽象类可以使用 final
修饰,但这没有实际意义,因为它不能被实例化,且不能被继承。
13. 接口和抽象类有什么区别?
-
接口:
- 不能包含具体实现(Java 8 及以上版本允许 default 和 static 方法)。
- 只支持公共方法和常量。
- 一个类可以实现多个接口(多继承)。
-
抽象类:
- 可以包含具体实现。
- 可以有访问修饰符。
- 一个类只能继承一个抽象类。
14. Java 中 IO 流分为几种?
Java中的 IO 流主要分为两种:
-
字节流:用于处理原始二进制数据。
- 输入流:
InputStream
- 输出流:
OutputStream
- 输入流:
-
字符流:用于处理文本数据。
- 输入流:
Reader
- 输出流:
Writer
- 输入流:
15. BIO、NIO、AIO 有什么区别?
- BIO (Blocking IO):传统的阻塞式 IO,线程在进行 IO 操作时会阻塞,效率较低,适用于连接数较少的场景。
- NIO (Non-blocking IO):引入了通道和缓冲区,支持非阻塞 IO,适合高并发场景。可以使用选择器来管理多个通道。
- AIO (Asynchronous IO):异步 IO,使用回调机制进行 IO 操作,性能更高,适用于高并发和高延迟的场景。
16. Files 的常用方法都有哪些?
在 java.nio.file.Files
类中,常用方法包括:
Files.readAllLines(Path path)
:读取所有行并返回列表。Files.write(Path path, Iterable<? extends CharSequence> lines)
:写入字符串列表到文件。Files.exists(Path path)
:检查文件或目录是否存在。Files.copy(Path source, Path target)
:复制文件。Files.move(Path source, Path target)
:移动或重命名文件。Files.delete(Path path)
:删除文件。Files.createDirectory(Path dir)
:创建目录。Files.list(Path dir)
:列出目录中的所有文件。
2.2 容器系列面试题
1. Java 容器都有哪些?
Java 提供了多种容器类,主要分为以下几类:
-
集合类(Collection):
- List:有序、可重复的元素集合,如
ArrayList
、LinkedList
、Vector
。 - Set:无序、不可重复的元素集合,如
HashSet
、TreeSet
、LinkedHashSet
。 - Queue:用于存储排队元素,支持FIFO(先进先出)访问,如
PriorityQueue
、LinkedList
。
- List:有序、可重复的元素集合,如
-
映射类(Map):
- Map:由键值对组成的集合,键不可重复,值可重复,如
HashMap
、TreeMap
、LinkedHashMap
、Hashtable
。
- Map:由键值对组成的集合,键不可重复,值可重复,如
2. Collection 和 Collections 有什么区别?
- Collection:是一个接口,表示一组对象的集合,它是所有集合类的根接口,包括
List
、Set
和Queue
。 - Collections:是一个工具类,提供了一些静态方法来操作和返回集合,如排序、查找、同步集合等。它本身不是一个集合。
3. List、Set、Map 之间的区别是什么?
-
List:
- 有序集合,允许重复元素。
- 典型实现:
ArrayList
、LinkedList
。
-
Set:
- 无序集合,不允许重复元素。
- 典型实现:
HashSet
、TreeSet
。
-
Map:
- 键值对集合,键唯一,值可以重复。
- 典型实现:
HashMap
、TreeMap
。
4. HashMap 和 Hashtable 有什么区别?
-
线程安全:
HashMap
是非线程安全的,而Hashtable
是线程安全的(但效率较低)。
-
null 值:
HashMap
允许一个null
键和多个null
值,而Hashtable
不允许null
键或null
值。
-
性能:
HashMap
通常比Hashtable
快,因为它没有同步机制。
5. 如何决定使用 HashMap 还是 TreeMap?
-
HashMap:
- 如果不需要排序和有序访问,并且需要高效的插入、删除和查找操作,选择
HashMap
。
- 如果不需要排序和有序访问,并且需要高效的插入、删除和查找操作,选择
-
TreeMap:
- 如果需要根据键的自然顺序或自定义顺序进行排序,选择
TreeMap
。它的操作复杂度为O(log n)。
- 如果需要根据键的自然顺序或自定义顺序进行排序,选择
6. 说一下 HashMap 的实现原理?
HashMap
采用哈希表实现。其核心原理如下:
- 结构:使用数组 + 链表(或红黑树)来存储元素。
- 哈希函数:将键的哈希值映射到数组的索引位置。
- 碰撞处理:当不同的键映射到同一个索引时,
HashMap
使用链表(JDK 8及以后,链表长度超过8会转换为红黑树)来处理碰撞。 - 负载因子:当元素数量超过数组容量 × 负载因子时,
HashMap
会扩展数组。
7. 说一下 HashSet 的实现原理?
HashSet
通过 HashMap
实现。具体原理如下:
- 底层结构:使用
HashMap
存储元素,所有元素都作为HashMap
的键,值是一个固定的对象(例如PRESENT
)。 - 哈希机制:
HashSet
通过HashMap
的哈希函数将元素映射到哈希表中。 - 无重复性:由于
HashMap
的键不可重复,HashSet
也保证不包含重复元素。
8. ArrayList 和 LinkedList 的区别是什么?
-
底层实现:
ArrayList
是基于动态数组实现的。LinkedList
是基于双向链表实现的。
-
访问性能:
ArrayList
支持快速随机访问,查询时间复杂度为 O(1)。LinkedList
在末尾插入和删除效率较高,时间复杂度为 O(1),但查询时间复杂度为 O(n)。
-
内存占用:
ArrayList
由于使用数组,可能会有额外的内存开销(如扩容)。LinkedList
每个节点都有额外的指针开销。
9. 如何实现数组和 List 之间的转换?
-
数组转 List:
List<String> list = Arrays.asList(array);
-
List 转数组:
String[] array = list.toArray(new String[0]);
10. ArrayList 和 Vector 的区别是什么?
-
线程安全:
Vector
是线程安全的,所有方法都使用同步。ArrayList
是非线程安全的,效率更高。
-
扩容机制:
Vector
的默认扩容是原数组的两倍。ArrayList
的默认扩容是原数组的 1.5 倍。
11. Array 和 ArrayList 有何区别?
-
固定 vs 动态:
- 数组大小固定,一旦创建不能更改。
ArrayList
是动态的,可以根据需要调整大小。
-
类型:
- 数组可以存储基本类型和对象。
ArrayList
只能存储对象(基本类型需使用包装类)。
-
性能:
- 数组访问性能更快,
ArrayList
由于使用封装对象可能会有额外开销。
- 数组访问性能更快,
12. 在 Queue 中 poll() 和 remove() 有什么区别?
-
poll():
- 从队列中移除并返回头元素,如果队列为空,返回
null
。
- 从队列中移除并返回头元素,如果队列为空,返回
-
remove():
- 从队列中移除并返回头元素,如果队列为空,抛出
NoSuchElementException
。
- 从队列中移除并返回头元素,如果队列为空,抛出
13. 哪些集合类是线程安全的?
- 线程安全的集合类:
Vector
Hashtable
ConcurrentHashMap
CopyOnWriteArrayList
Collections.synchronizedList(new ArrayList<>())
Collections.synchronizedSet(new HashSet<>())
14. 迭代器 Iterator 是什么?
Iterator
是一种用于遍历集合元素的接口。它提供了一种统一的方法来访问集合中的每个元素。
15. Iterator 怎么使用?有什么特点?
-
使用方法:
Iterator<String> iterator = collection.iterator(); while (iterator.hasNext()) { String element = iterator.next(); // 处理元素 }
-
特点:
Iterator
可以在遍历时安全地删除元素。- 通过
hasNext()
和next()
方法来遍历。
16. Iterator 和 ListIterator 有什么区别?
-
方向:
Iterator
只能向前遍历。ListIterator
可以向前和向后遍历。
-
方法:
ListIterator
提供了更多方法,如add()
和set()
。
-
使用范围:
Iterator
可以用于任何实现Collection
的集合。ListIterator
只能用于实现List
接口的集合。
17. 怎么确保一个集合不能被修改?
可以使用 Collections.unmodifiableCollection()
方法来创建一个不可修改的集合。例如:
Collection<String> original = new ArrayList<>(); Collection<String> unmodifiableCollection = Collections.unmodifiableCollection(original);
在这个集合上调用任何修改方法(如 add()
、remove()
)都会抛出 UnsupportedOperationException
。
2.3 多线程系列面试题
1. 并行和并发有什么区别?
-
并发(Concurrency):指的是在同一时间段内,有多个任务在进行。这些任务可能是同时进行的,也可能是交替进行的,但并不一定是同时在执行。例如,一个 CPU 可以在多核系统中实现并发。
-
并行(Parallelism):指的是在同一时间内,多个任务真正同时执行。通常需要多核 CPU 或多台机器协作完成。例如,在多核处理器上,不同的核心可以同时执行不同的任务。
2. 线程和进程的区别?
-
进程:是操作系统分配资源的基本单位,每个进程都有独立的地址空间,进程间通信需要通过 IPC(进程间通信)机制,如管道、消息队列等。
-
线程:是进程中的一个执行单元,同一进程中的多个线程共享进程的资源(如内存),但线程之间相互独立。创建和切换线程的开销通常小于进程。
3. 守护线程是什么?
守护线程是指在后台运行的线程,主要用于执行一些辅助性任务,例如垃圾回收或监视。守护线程的存在并不会阻止程序的终止,当所有的用户线程结束时,Java 虚拟机将会自动终止所有的守护线程。
4. 创建线程有哪几种方式?
-
继承 Thread 类:创建一个类继承 Thread 并重写 run() 方法,然后实例化并调用 start() 方法。
-
实现 Runnable 接口:创建一个类实现 Runnable 接口,重写 run() 方法,创建 Thread 对象并传入 Runnable 实例,再调用 start() 方法。
-
使用 Callable 接口:实现 Callable 接口的类,重写 call() 方法,使用 FutureTask 作为线程的任务。
-
使用线程池:使用 Executor 框架中的线程池来管理线程的创建和执行。
5. Runnable 和 Callable 有什么区别?
-
Runnable:不返回值的任务,run() 方法没有返回值,无法抛出检查异常。
-
Callable:可以返回值的任务,call() 方法可以返回值并且可以抛出检查异常,通常与 Future 结合使用来获取任务执行的结果。
6. 线程有哪些状态?
线程有以下几种状态:
- 新建(New):线程被创建但未启动。
- 就绪(Runnable):线程已启动,但等待 CPU 时间片。
- 运行(Running):线程正在执行。
- 阻塞(Blocked):线程因请求资源而被阻塞。
- 等待(Waiting):线程处于等待状态,直到被其他线程唤醒。
- 终止(Terminated):线程执行完成或异常退出。
7. sleep() 和 wait() 有什么区别?
-
sleep():使当前线程进入休眠状态,指定时间后自动恢复。它不会释放对象的锁。
-
wait():使当前线程等待,直到其他线程调用 notify() 或 notifyAll() 方法。它会释放对象的锁。
8. notify() 和 notifyAll() 有什么区别?
-
notify():随机唤醒一个在此对象监视器上等待的线程。
-
notifyAll():唤醒所有在此对象监视器上等待的线程。
9. 线程的 run() 和 start() 有什么区别?
-
run():只是一个普通的方法调用,直接调用 run() 方法不会创建新线程,而是在当前线程中执行。
-
start():启动新线程并调用其 run() 方法。调用 start() 方法后,新的线程会被调度执行。
10. 创建线程池有哪几种方式?
-
使用 Executors 工厂类:可以使用
Executors.newFixedThreadPool()
,Executors.newCachedThreadPool()
,Executors.newSingleThreadExecutor()
等。 -
使用 ThreadPoolExecutor:可以通过直接创建 ThreadPoolExecutor 类的实例,提供更细粒度的控制。
11. 线程池都有哪些状态?
线程池的状态通常包括:
- RUNNING:可以接收新任务和处理排队任务。
- SHUTDOWN:不再接收新任务,但会处理已提交的任务。
- STOP:不再接收新任务,停止处理正在执行的任务。
- TERMINATED:所有任务都已完成,线程池已终止。
12. 线程池中 submit() 和 execute() 方法有什么区别?
-
submit():用于提交任务,返回一个 Future 对象,可以获取任务执行的结果或处理异常。
-
execute():用于提交不需要返回值的任务,没有返回 Future,不能处理异常。
13. 在 Java 程序中怎么保证多线程的运行安全?
可以使用以下几种方式来保证多线程的安全:
- synchronized:在方法或代码块上使用 synchronized 关键字。
- Lock 接口:使用 ReentrantLock 提供更灵活的锁机制。
- Atomic 类:使用 java.util.concurrent.atomic 包中的类处理原子操作。
- ThreadLocal:为每个线程提供独立的变量副本。
14. 多线程中 synchronized 锁升级的原理是什么?
synchronized 锁在某些情况下会进行锁升级。一般流程为:
- 偏向锁:当线程第一次访问对象时,获取偏向锁,记录线程 ID。
- 轻量级锁:当其他线程竞争偏向锁时,偏向锁升级为轻量级锁,使用 CAS 操作尝试获取锁。
- 重量级锁:如果轻量级锁无法获取,升级为重量级锁,进入操作系统的阻塞状态。
15. 什么是死锁?
死锁是指两个或多个线程因争夺资源而造成的相互等待的状态,导致它们都无法继续执行。例如,线程 A 持有资源 1,等待资源 2,而线程 B 持有资源 2,等待资源 1。
16. 怎么防止死锁?
可以采取以下措施防止死锁:
- 资源有序分配:确保线程按固定顺序获取资源。
- 使用时间限制:设置获取资源的超时时间,超过时间则放弃。
- 避免锁嵌套:尽量减少锁的嵌套使用。
- 使用尝试锁:使用 tryLock() 方法尝试获取锁,如果获取失败则放弃。
17. ThreadLocal 是什么?有哪些使用场景?
ThreadLocal 是 Java 提供的一种用于存储线程本地变量的工具。每个线程都可以通过 ThreadLocal 创建的变量保持独立的副本。
使用场景:
- 需要每个线程独立的用户会话数据。
- 数据库连接、事务处理等场景中需要每个线程独立的状态。
- 简化线程间的数据传递。
18. synchronized 底层实现原理?
synchronized 是 Java 提供的内置锁,底层实现依赖于 JVM。它通过对象头中的标志位来表示锁的状态,涉及到偏向锁、轻量级锁和重量级锁的升级过程,以保证高效的锁机制。
19. synchronized 和 volatile 的区别是什么?
-
synchronized:保证互斥访问,线程在进入 synchronized 代码块时会加锁,出离时释放锁。
-
volatile:用于标记一个变量为易变的,确保对该变量的写操作立即被其他线程可见,但不提供互斥访问的功能。
20. synchronized 和 Lock 有什么区别?
-
synchronized:是 Java 的内置锁,使用简单,但灵活性较低,锁的释放由 JVM 控制。
-
Lock:是 Java 提供的接口,提供了更高的灵活性,如可中断的锁、超时锁等。使用时需要手动释放锁。
21. synchronized 和 ReentrantLock 区别是什么?
-
synchronized:自动释放锁,简化了代码逻辑,不需要手动释放。
-
ReentrantLock:需要手动释放锁,提供了可重入、可中断等特性,适用于复杂的锁控制场景。
2.4 异常、网络、设计模式系列面试题
1. throw 和 throws 的区别
- throw:是一个关键字,用于在方法内部抛出异常。例如,可以用
throw new Exception("错误信息");
抛出一个新的异常。 - throws:是一个关键字,用于在方法声明中指明该方法可能会抛出的异常类型。它告诉调用该方法的代码需要处理这些异常,例如:
public void myMethod() throws IOException { // 可能抛出IOException的代码 }
2. final、finally、finalize 的区别
- final:是一个关键字,用于修饰类、方法和变量,表示它们不能被修改或重写。例如,声明为
final
的类不能被继承,final
方法不能被重写,final
变量不能被重新赋值。 - finally:是一个代码块,用于在异常处理后总是执行的代码块,通常与
try-catch
语句一起使用。无论是否发生异常,finally
中的代码都会执行。 - finalize:是一个方法,属于
Object
类,用于在垃圾回收前执行一些清理工作。它是被 JVM 调用的,开发者不能直接调用。
3. try-catch-finally 中哪个部分可以省略?
在 try-catch-finally
结构中,可以省略以下部分:
catch
块:如果只想执行try
块中的代码,或者希望在发生异常时仍然执行finally
块,可以省略catch
块。finally
块:可以只写try
块和catch
块而省略finally
块,但 `finally 块常用于确保某些资源被释放。
4. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
是的,即使在 catch
块中执行了 return
语句,finally
块中的代码仍然会执行。这是因为 finally
块的设计是确保在方法结束之前清理资源或执行必要的代码。
5. 常见的异常类有哪些?
常见的异常类包括:
- RuntimeException:表示运行时异常,程序在运行时可能会抛出,例如
NullPointerException
、ArrayIndexOutOfBoundsException
。 - IOException:表示输入输出异常,通常与文件操作相关。
- SQLException:表示数据库操作异常。
- ClassNotFoundException:表示无法找到指定的类。
- IllegalArgumentException:表示方法接收到不合法或不适当的参数。
6. HTTP 响应码 301 和 302 代表的是什么?有什么区别?
- 301 Moved Permanently:表示请求的资源已被永久移动到新位置,后续请求应使用新 URI。
- 302 Found:表示请求的资源临时移动到新位置,客户端应继续使用原 URI 进行后续请求。
区别:
- 301 是永久重定向,搜索引擎会更新其索引。
- 302 是临时重定向,搜索引擎不会更新其索引。
7. forward 和 redirect 的区别?
-
forward:
- 是服务器内部转发请求,用户不会察觉 URL 的变化,URL 保持不变。
- 适用于在同一应用内的请求转发,使用
RequestDispatcher
实现。
-
redirect:
- 是服务器向客户端发送重定向响应,客户端会发起新的请求到指定的 URL。
- URL 会发生变化,适用于跨应用或跨域的请求。
8. 简述 TCP 和 UDP 的区别
-
TCP(传输控制协议):
- 面向连接:在传输数据之前需要建立连接。
- 可靠性:提供数据的可靠传输,保证数据按顺序到达,不会丢失。
- 流量控制和拥塞控制:TCP 具有流量控制机制。
-
UDP(用户数据报协议):
- 无连接:不需要建立连接,数据可以直接发送。
- 不可靠性:不保证数据的传输和顺序,可能会丢失数据。
- 更低的延迟,适用于对速度要求高的应用,如视频会议、在线游戏等。
9. TCP 为什么要三次握手,两次不行吗?为什么?
TCP 需要三次握手的原因:
- 确认连接的存在:确保双方都已准备好进行数据传输。
- 同步序列号:在握手过程中,双方能够确认对方的初始序列号,为数据的可靠传输提供依据。
两次握手不够,因为如果只进行两次,客户端可能在发送请求时无法确认服务器是否已经准备好接收数据,这样可能导致数据丢失。
10. 说一下 TCP 粘包是怎么产生的?
TCP 粘包的产生原因:
- TCP 是面向字节流的协议,数据在传输时可能会被合并成一个包进行发送,尤其在发送的数据量小于 MTU(最大传输单元)时。
- 应用层没有合适的协议来划分数据边界,导致多个消息在 TCP 层被打包成一个数据段。
11. OSI 的七层模型都有哪些?
OSI 七层模型:
- 物理层:负责传输原始的比特流,涉及硬件设备。
- 数据链路层:提供点对点的数据传输,进行帧的封装和校验。
- 网络层:负责数据包的路由选择,处理网络间的传输。
- 传输层:负责端到端的通信,提供可靠或不可靠的数据传输。
- 会话层:管理会话的建立、维护和终止。
- 表示层:处理数据的格式化和转换,负责数据的加密和解密。
- 应用层:为用户提供网络服务,支持各种应用程序。
12. GET 和 POST 请求有哪些区别?
-
GET:
- 请求参数通过 URL 传递,数据长度有限。
- 常用于请求数据,安全性低。
- 可被缓存,可以在浏览器历史记录中查看。
-
POST:
- 请求参数通过请求体传递,数据长度较大。
- 常用于提交数据(例如表单),安全性高于 GET。
- 不可被缓存,浏览器历史记录中不会显示请求参数。
13. 如何实现跨域?
跨域的实现方式:
- CORS(跨域资源共享):在服务器端设置 HTTP 头部允许特定的源访问资源。
- JSONP:通过
<script>
标签加载数据,利用动态添加的脚本解决跨域问题。 - 代理:在同源的服务器上设置一个代理,转发请求到目标跨域服务器。
14. 说一下 JSONP 实现原理?
JSONP(JSON with Padding)的实现原理:
- 通过动态创建
<script>
标签向服务器发送请求,请求的 URL 中包含一个回调函数名作为参数。 - 服务器接收到请求后,会以 JavaScript 代码的形式返回数据,并调用回调函数,将数据作为参数传入。
- 由于
<script>
标签不受同源策略的限制,成功实现跨域请求。
15. 简单工厂和抽象工厂有什么区别?
-
简单工厂:
- 只有一个工厂类,根据参数决定创建哪个产品类的实例。
- 适用于产品数量较少且变化不大的场景。
-
抽象工厂:
- 定义一个接口,用于创建一系列相关或依赖的对象。
- 每个产品系列对应一个具体工厂,适用于产品系列较多且复杂的场景。