一、Java基础
1.面向对象的特征有哪些方面?
封装:最常见的是把属性私有化封装在一个类里面,只能通过方法去访问。
继承:从已有类得到继承信息创建新类的过程。
抽象:将一类对象的共同特征总结出来构造类的过程。
多态: 父类引用指向子类对象。
2.面向对象的“六原则一法则”
单一职责原则:一个类只做它该做的事情。
开闭原则:软件实体应当对扩展开放,对修改关闭。
依赖倒转原则:面向接口编程。
里氏替换原则:任何时候都可以用子类型替换掉父类型。
接口隔离原则:接口要小而专,绝不能大而全。
合成复用原则:在代码复用上优先考虑合成、聚合(has a)关系,而不是继承(is a)。
迪米特法则:迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。
3.JDK 和 JRE 有什么区别?
- JDK:Java Development Kit 的简称,java 开发工具包,包含了JRE,同时还包含了编译java源码的编译器javac以及很多java程序调试和分析的工具
- JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境,包含了java虚拟机,java基础类库。
简单来说:如果你需要运行 java 程序,只需安装 JRE 就可以了,如果你需要编写 java 程序,需要安装 JDK。
4. == 和 equals 的区别是什么?
== 解读
对于基本类型和引用类型 == 的作用效果是不同的
- 基本类型:比较的是值是否相同;
- 引用类型:比较的是引用是否相同;
equals 解读
equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。
总结 :== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
5. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
不对,两个对象的 hashCode()相同,equals()不一定 true。
6. final 在 java 中有什么作用?
- 修饰的类叫最终类,该类不能被继承。
- 修饰的方法不能被重写。
- 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
- 修饰的引用 表示该引用只有一次指向对象的机会
7. java 中的 Math.round(-1.5) 等于多少?
等于 -1,四舍六入五取偶;Math.round 的意思是+0.5 后,向下取整。
所以 Math.round(1.5) 即 1.5+0.5 = 2; Math.round(-1.5) 即 -1.5+0.5 = -1
8. String 属于基础的数据类型吗?
String是引用类型(类类型),不是基本类型。
基本类型 有八种:整型 (4种),浮点型 ,(2种),布尔型(1种),字符型 (1种)
这八种基本类型分别是:byte, short, int, long, float, double, boolean, char
所长内存分别为:1字节,2字节,4字节,8字节,4字节,8字节,1字节,2字节
正数默认是int类型,小数默认是double类型,
long n = 1L; float n = 1f;
// double是双精度类型,精度是17位有效数字
// float是单精度类型,精度是8位有效数字
9. java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、StringBuffer、StringBuilder。
String是immutable的,其内容一旦创建好之后,就不可以发生改变。
原因是:String底层是用char[] 数组实现的,并且使用final修饰了String和char[]。
StringBuffer、StringBuilder 是可以变长的,内容也可以发生改变。
其中:StringBuffer是线程安全的(内部方法用了synchronize修饰),所以速度较慢;而StringBuilder是非线程安全的,所以速度较快。
10.如何将字符串反转?
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
11.String 类的常用方法都有那些?
- indexOf():返回指定字符的索引。
- charAt():返回指定索引处的字符。
- replace():字符串替换。
- trim():去除字符串两端空白。
- split():分割字符串,返回一个分割后的字符串数组。
- getBytes():返回字符串的 byte 类型数组。
- length():返回字符串长度。
- toLowerCase():将字符串转成小写字母。
- toUpperCase():将字符串转成大写字符。
- substring():截取字符串。
- equals():字符串比较。
12.接口和抽象类有什么区别?
- 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
- 构造函数:抽象类可以有构造函数;接口不能有。
- main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
- 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
- 访问修饰符:接口中的方法jdk1.8以前必须使用public,1.8时可以使用default,到了jdk1.9可以有private(私有方法);抽象类中的方法可以是任意访问修饰符但是jak1.8以前默认为protected,1.8以后默认为default。
13.java 中 IO 流分为几种?
- 按功能来分:输入流(input)、输出流(output)。
- 按类型来分:字节流和字符流。
注意:Java中所有的流都是基于字节流,所以最基本的流是
输入输出字节流: InputStream、OutputStream
在字节流的基础上,封装了字符流: Reader、Writer
进一步,又封装了缓存流: BufferedReader、PrintWriter
以及数据流: DataInputStream、DataOutputStream
对象流: ObjectInputStream、ObjectOutputStream
14.BIO、NIO、AIO 有什么区别?
- BIO:同步并阻塞,一个连接一个线程(面向流)
- NIO:同步非阻塞,一个请求一个线程(面向缓冲)
- AIO:异步非阻塞,一个有效请求一个线程
15.Files的常用方法都有哪些?
- Files.exists():检测文件路径是否存在。
- Files.createFile():创建文件。
- Files.createDirectory():创建文件夹。
- Files.delete():删除一个文件或目录。
- Files.copy():复制文件。
- Files.move():移动文件。
- Files.size():查看文件个数。
- Files.read():读取文件。
- Files.write():写入文件。
二、集合
16.java 容器都有哪些?
17.Collection 和 Collections 有什么区别?
- Collection 是一个集合接口(集合类的一个顶级接口,是List和Set的父接口。
- Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
18.List、Set、Map 之间的区别是什么?
- List 是有顺序的,并且可以重复
- Set 是无序的,不可以重复
- Map 保存数据的方式是键值对
19. HashMap 和 Hashtable 有什么区别?
- 初始大小和扩容方式不同:Hashtable默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。
- 线程安全性不同:
Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步
HashMap不是线程安全的,在多线程并发的环境下,可能会产生死锁等问题。使用HashMap时就必须要自己增加同步处理,- 继承的父类不同:HashMap是继承自AbstractMap类,而HashTable是继承自Dictionary类。不过它们都同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口
- hashMap允许空键值,而hashTable不允许。
20.说一下 HashMap 的实现原理?
HashMap的数据结构:数组+链表+红黑树(jdk1.8以后才有红黑树)
当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根据hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
21.ArrayList 和 LinkedList 的区别是什么?
ArrayList 是数组结构,所以定位很快,但是插入和删除很慢
LinkedList 是双向链表结构,所以插入和删除很快,但是定位很慢
22.如何实现数组和 List 之间的转换?
- List转换成为数组:调用ArrayList的toArray方法。
- 数组转换成为List:调用Arrays的asList方法。
23.ArrayList 和 Vector 的区别是什么?
Vector是同步的,而ArrayList不是。
ArrayList比Vector快
24.Array 和 ArrayList 有何区别?
- (1) Array大小是固定的,ArrayList的大小是动态变化的。
- (2) Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
注意:Array数组在存放的时候一定是同种类型的元素。ArrayList就不一定了,因为ArrayList可以存储Object。
25.在 Queue 中 poll()和 remove()有什么区别?
poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。
26.哪些集合类是线程安全的?
口诀:“喂,SHE”
- vector:就比arrayList多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
- statck:堆栈类,先进后出。
- Hashtable:就比hashmap多了个线程安全。
- enumeration:枚举,相当于迭代器。
- ConcurrentHashMap:是一种高效但是线程安全的集合。
27. 迭代器 Iterator 是什么?
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
28. Iterator 怎么使用?有什么特点?
Java中的Iterator功能比较简单,并且只能单向移动:
- (1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
- (2) 使用next()获得序列中的下一个元素。
- (3) 使用hasNext()检查序列中是否还有元素。
- (4) 使用remove()将迭代器新返回的元素删除。
注意:再循环遍历时,若想删除集合中的某个元素,就要使用Iterator的remove()方法,而不能使用集合的remove()方法,不然会报ConcurrentModificationException,因为集合的大小改变了而Iterator会维护此删除标记
29. Iterator 和 ListIterator 有什么区别?
- Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
- Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
- ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
三、多线程
30.并行和并发有什么区别?
- 并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间段内发生。
- 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
- 在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群。
所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。
31.线程和进程的区别?
- 进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。
- 线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。
32.守护线程是什么?
守护线程(即daemon thread),是个服务线程,准确地来说就是服务其他的线程。
33.创建线程有哪几种方式?
- 继承Thread类创建线程类
定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
创建Thread子类的实例,即创建了线程对象。
调用线程对象的start()方法来启动该线程。
- 通过Runnable接口创建线程类
定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
调用线程对象的start()方法来启动该线程。
- 通过Callable和Future创建线程
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该 Callable对象的call()方法的返回值。
使用FutureTask对象作为Thread对象的target创建并启动新线程。
调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
- 通过线程池启动多线程
34.说一下 runnable 和 callable 有什么区别?
- Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;
- Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。
35.线程有哪些状态?
线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
- 创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
- 就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
- 运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
- 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之>后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
- 死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪
36.sleep() 和 wait() 有什么区别?
- sleep():方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。因为sleep() 是static静态的方法,他会保持对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
- wait():wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程。
37.创建线程池有哪几种方式?
- newFixedThreadPool(int nThreads)
创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。- newCachedThreadPool()
创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。- newSingleThreadExecutor()
这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。- newScheduledThreadPool(int corePoolSize)
创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。
38.在 java 程序中怎么保证多线程的运行安全?
线程安全在三个方面体现:
- 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);
- 可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
- 有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。
39.什么是死锁?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
40.怎么防止死锁?
死锁的四个必要条件:
- 互斥条件:某种资源一次只能被一个线程访问。
- 不可抢占:当某资源正在被线程A持有并且A没有主动放弃的情况下,无法将该资源分配给其他线程。
- 占有且等待:线程A自身占有一定资源的情况下,因资源未满足又等待其他线程释放A所需的其他资源。
- 循环等待:当两个及以上的线程处于相互的占有且等待状态时,就开始循环等待。
解决:
a. 资源预分配策略, 如银行家算法。
b. 资源有序分配策略,比如在线程A没有获取小号资源的情况下,无法去申请对应的大号资源。
41. 简述synchronized和java.util.concurrent.locks.Lock的异同 ?(Lock一般使用ReentrantLock实现类)
- 都是独占锁。 但synchronize加锁和解锁的过程自动进行,易于操作,但不够灵活;而ReentrantLock需要手动进行,不易操作,但非常灵活。
- 都可重入。但synchronize加锁和解锁自动进行,不必担心最后是否释放锁;而ReentrantLock需要手动进行,且次数需一样,否则其他线程无法获得锁。
- synchronized不可响应中断,一个线程获取不到锁就一直等着;ReentrantLock可以相应中断。
- ReentrantLock还可以实现公平锁机制。(公平锁:锁上等待时间最长的线程将获得锁的使用权)
42.当一个线程进入某对象被synchronized修饰的方法后,其它线程是否可进入此对象的其它方法
这要看情况而定(看锁是加在类上还是对象上),如果该对象的其他方法也是有synchronized修饰的,那么其他线程就会被挡在外面。否则其他线程就可以进入其他方法。
43.请你介绍一下volatile?
作用:
1、保证了不同线程对同一变量操作的内存可见性.(当一个线程修改了变量,其他使用次变量的线程可以立即知道这一修改).
2、禁止了指令重排序.
44.请你说明一下在监视器(Monitor)内部,是如何做到线程同步的?
监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。
45.请说明一下线程池有什么优势?
(1)降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
(2)提高响应速度。当任务到达时,任务可以不需要等到线程创建就能执行。
(3)提高线程的可管理性,使用线程池可以对线程进行统一分配、调优和监控。
46.描述一下JVM内存模型(简称JMM)
线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。
注意:本地内存是JMM的一个抽象概念,并不真实存在。
四、反射
47.什么是反射?
反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力
Java反射:
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法
Java反射机制主要提供了以下功能:
(1)在运行时判断任意一个对象所属的类。
(2)在运行时构造任意一个类的对象。
(3)在运行时判断任意一个类所具有的成员变量和方法。
(4)在运行时调用任意一个对象的方法。
48.什么是java序列化,如何实现java序列化?
概念:
序列化:把Java对象转换为字节序列的过程。
反序列化:把字节序列恢复为Java对象的过程。
用途:
(1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
(2) 在网络上传送对象的字节序列。
实现:
序列化:java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。只有实现了Serializable和Externalizable接口的类的对象才能被序列化。
反序列化:java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
49.动态代理是什么?有哪些应用?
在运行时由JDK反射机制动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中。具有解耦意义,灵活,扩展性强。
动态代理的应用:
- Spring的AOP
- 加事务
- 加权限
- 加日志
50. 怎么实现动态代理?
首先必须定义一个接口,还要有一个InvocationHandler(将实现接口的类的对象传递给它)处理类。再有一个工具类Proxy(习惯性将其称为代理类,因为调用他的newInstance()可以产生代理对象,其实他只是一个产生代理对象的工具类)。利用到InvocationHandler,拼接代理类源码,将其编译生成代理类的二进制码,利用加载器加载,并将其实例化产生代理对象,最后返回。
五、 对象拷贝
51.为什么要使用克隆?
想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了,Java语言中克隆针对的是类的实例。
52.如何实现对象克隆?
有两种方式:
1). 实现Cloneable接口并重写Object类中的clone()方法;
2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆.
53.深拷贝和浅拷贝区别是什么?
- 浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化
- 深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变
六、Java Web
54.jsp 和 servlet 有什么区别?
(1)Jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
(2)jsp更擅长表现于页面显示,servlet更擅长于逻辑控制。
(3)Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到。
(4)Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。
55.jsp 有哪些内置对象?作用分别是什么?
JSP有9个内置对象:
- request:封装客户端的请求,其中包含来自GET或POST请求的参数;
- response:封装服务器对客户端的响应;
- pageContext:通过该对象可以获取其他对象;
- session:封装用户会话的对象;
- application:封装服务器运行环境的对象;
- out:输出服务器响应的输出流对象;
- config:Web应用的配置对象;
- page:JSP页面本身(相当于Java程序中的this);
- exception:封装页面抛出异常的对象。
56.说一下 jsp 的 4 种作用域?
JSP中的四种作用域包括page、request、session和application,具体来说:
- application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。(存在时间最长,也最消耗系统资源)
- session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。
- request代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域。
- page代表与一个页面相关的对象和属性。
57.如何避免 sql 注入?
(1) PreparedStatement(简单又有效的方法)
(2)使用正则表达式过滤传入的参数
(3)字符串过滤
(4)JSP中调用该函数检查是否包函非法字符
(5)JSP页面判断代码
七、异常
58. throw 和 throws 的区别?
- throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。
- throw则是指抛出的一个具体的异常类型。
59.final、finally、finalize 有什么区别?
final
final修饰类,方法,基本类型变量,引用的时候分别有不同的意思
修饰类 表示该类不能被继承
修饰方法 表示该方法不能被重写
修饰基本类型变量 表示该变量只能被赋值一次
修饰引用 表示该引用只有一次指向对象的机会finally
finally 是用于异常处理的场面,无论是否有异常抛出,都会执行
finalize
finalize是Object的方法,所有类都继承了该方法。 当一个对象满足垃圾回收的条件,并且被回收的时候,其finalize()方法就会被调用
60.介绍5个你最常见到的runtime exception。
(1)NullPointerException 空指针异常
(2)ArithmeticException 算术异常,比如除数为零
(3)ClassCastException 类型转换异常
(4)ConcurrentModificationException 同步修改异常,遍历一个集合的时候,删除集合的元素,就会抛出该异常
(5)IndexOutOfBoundsException 数组下标越界异常
61.Error和Exception有什么区别?
Error和Exception都实现了Throwable接口
- Error指的是JVM层面的错误,比如内存不足OutOfMemoryError
- Exception 指的是代码逻辑的异常,比如下标越界OutOfIndexException
62.运行时异常(RuntimeException)与一般异常有何异同?
- 运行时异常:又叫做非可查异常,在编译过程中,不要求必须进行显示捕捉
- 一般异常(编译异常):又叫做可查异常,在编译过程中,必须进行处理,要么捕捉,要么通过throws 抛出去.
八、网络
63.forward 和 redirect 的区别?
Forward和Redirect代表了两种请求转发方式:直接转发和间接转发。
直接转发方式(Forward),客户端和浏览器只发出一次请求,Servlet、HTML、JSP或其它信息资源,由第二个信息资源响应该请求,在请求对象request中,保存的对象对于每个信息资源是共享的(重点:地址栏URL不变)。
间接转发方式(Redirect)实际是两次HTTP请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个URL发出请求,从而达到转发的目的。(地址栏URL会发生改变)
64.tcp 为什么要三次握手,两次不行吗?为什么?
为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。
如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。
九、Spring / Spring MVC
65. 解释一下什么是 aop?
AOP(Aspect-Oriented Programming,面向切面编程):把程序中重复的代码提取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上对我们已有的方法进行改进。
66.解释一下什么是 IOC?
IOC(Inversion of Control,控制反转):把创建对象的权利交给框架,削减程序的耦合性
67.spring 有哪些主要模块?
Spring框架至今已集成了20多个模块。这些模块主要被分如下图所示的核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。
68.spring 常用的注入方式有哪些?
Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:
- 构造方法注入
- setter注入
- 基于注解的注入
69.spring 事务实现方式有哪些?
(1)编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
(2)基于 TransactionProxyFactoryBean 的声明式事务管理
(3)基于 @Transactional 的声明式事务管理
(4)基于 Aspectj AOP 配置事务
70.说一下 spring 的事务隔离?
事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如果没有采取必要的隔离机制,就可能发生以下问题:
- 脏读:一个事务读到另一个事务未提交的更新数据。
- 幻读:例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样。
- 不可重复读:比方说在同一个事务中先后执行两条一模一样的select语句,期间在此次事务中没有执行过任何DDL语句,但先后得到的结果不一致,这就是不可重复读。