栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java面试题总结(含答案)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java面试题总结(含答案)

目录

一、Java基础

JDK 、 JRE 、JVM有什么区别和联系?

== 和 equals 的区别是什么?

两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

final 在 java 中有什么作用?

Java的基础类型有哪些?String属于基础的数据类型吗?

java 中操作字符串都有哪些类?它们之间有什么区别?

String str="i"与 String str=new String(“i”)一样吗?

String 类的常用方法都有那些?

如何将字符串反转?

接口和抽象类有哪些区别?

java 中 IO 流分为几种?

BIO、NIO、AIO 有什么区别?

Files的常用方法都有哪些?

二、容器

java 容器都有哪些?

Collection 和 Collections 有什么区别?

List、Set、Map 之间的区别是什么?

HashMap 和 Hashtable 有什么区别?

如何决定使用 HashMap 还是 TreeMap?

说一下 HashMap 、HashSet的实现原理?

ArrayList 和 linkedList 的区别是什么?

如何实现数组和 List 之间的转换?

ArrayList 和 Vector 的区别是什么?

Array 和 ArrayList 有何区别?

在 Queue 中 poll()和 remove()有什么区别?

哪些集合类是线程安全的?

迭代器 Iterator 是什么?

Iterator 怎么使用?有什么特点?

Iterator 和 ListIterator 有什么区别?

怎么确保一个集合不能被修改?

三、多线程

并行和并发有什么区别?

线程和进程的区别?

守护线程是什么?

创建线程有哪几种方式?

说一下 Runnable 和 Callable 有什么区别?

线程有哪些状态?

sleep() 和 wait() 有什么区别?

notify()和 notifyAll()有什么区别?

线程的 run()和 start()有什么区别?

创建线程池有哪几种方式?

线程池都有哪些状态?

 线程池中 submit()和 execute()方法有什么区别?

在 java 程序中怎么保证多线程的运行安全?

什么是死锁?怎么防止死锁?

ThreadLocal 是什么?有哪些使用场景?

说一下 synchronized 底层实现原理?

synchronized 和 volatile 的区别是什么?

synchronized 和 Lock 有什么区别?

synchronized 和 ReentrantLock 区别是什么?

说一下 atomic 的原理?

四、反射

什么是反射?

什么是 java 序列化?什么情况下需要序列化?

动态代理是什么?怎么实现动态代理?有哪些应用?

五、对象拷贝

为什么要使用克隆?

如何实现对象克隆?

深拷贝和浅拷贝区别是什么?

六、Java Web

jsp 和 servlet 有什么区别?

jsp 有哪些内置对象?作用分别是什么?

说一下 jsp 的 4 种作用域?

session 和 cookie 有什么区别?

说一下 session 的工作原理?

如果客户端禁止 cookie 能实现 session 还能用吗?

如何避免 sql 注入?

什么是 XSS 攻击,如何避免?

什么是 CSRF 攻击,如何避免?

七、异常

throw 和 throws 的区别?

final、finally、finalize 有什么区别?

try-catch-finally 中哪个部分可以省略?

try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

常见的异常类有哪些?

八、网络 

http 响应码 301 和 302 代表的是什么?有什么区别?

forward 和 redirect 的区别?

简述 tcp 和 udp的区别?

tcp 为什么要三次握手,两次不行吗?为什么?

说一下tcp的三次握手和四次挥手?

说一下 tcp 粘包是怎么产生的?

OSI 的七层模型都有哪些?

get 和 post 请求有哪些区别?

如何实现跨域?

九、设计模式

说一下你熟悉的设计模式?

设计模式的六大原则

简单工厂和抽象工厂有什么区别?

常用设计模式 Java 实现----单例模式

常用设计模式 Java 实现----工厂模式

十、Spring/Spring MVC

为什么要使用 spring?

解释一下什么是 aop(切面)?

解释一下什么是 ioc?

spring 有哪些主要模块?

spring 常用的注入方式有哪些?

spring 中的 bean 是线程安全的吗?

spring 自动装配 bean 有哪些方式?

spring 事务实现方式有哪些?

说一下 spring 的事务隔离?

说一下 spring mvc 运行流程?

@RequestMapping 的作用是什么?

@Autowired 的作用是什么?

十一、Spring Boot/Spring Cloud

什么是 spring boot?

为什么要用 spring boot?

springBoot常用注解及解释

spring boot 核心配置文件是什么?

spring boot 有哪些方式可以实现热部署?

jpa 和 hibernate 有什么区别?

什么是 spring cloud?

spring cloud 断路器的作用是什么?

spring cloud 的核心组件有哪些?

十二、Mybatis

mybatis 中 #{}和 ${}的区别是什么?

mybatis 有几种分页方式?

RowBounds 是一次性查询全部结果吗?为什么?

mybatis 逻辑分页和物理分页的区别是什么?

mybatis 是否支持延迟加载?延迟加载的原理是什么?

说一下 mybatis 的一级缓存和二级缓存?

mybatis 和 hibernate 的区别有哪些?

mybatis 有哪些执行器(Executor)?

mybatis 分页插件的实现原理是什么?

mybatis 如何编写一个自定义插件?

十三、MySql

数据库的三范式是什么?

一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几(8)?

如何获取当前数据库版本?

说一下 ACID 是什么?

char 和 varchar 的区别是什么?

float 和 double 的区别是什么?

mysql 的内连接、左连接、右连接有什么区别?

mysql 索引是怎么实现的?

怎么验证 mysql 的索引是否满足需求?

说一下数据库的事务隔离?

说一下 mysql 常用的引擎?

 说一下 mysql 的行锁和表锁?

说一下乐观锁和悲观锁?

mysql 问题排查都有哪些手段?如何做 mysql 的性能优化??

十四、Redis

redis 是什么?都有哪些使用场景?

redis 有哪些功能?

redis 和 memecache 有什么区别?

redis 为什么是单线程的?

什么是缓存穿透和雪崩?怎么解决?

redis 支持的数据类型有哪些?

redis 支持的 java 客户端都有哪些?

jedis 和 redisson 有哪些区别?

怎么保证缓存和数据库数据的一致性?

redis 持久化有几种方式?

redis 怎么实现分布式锁?

redis 分布式锁有什么缺陷?

redis 如何做内存优化?

redis 淘汰策略有哪些?

redis 常见的性能问题有哪些?该如何解决?

十五、JVM

说一下 jvm 的主要组成部分?及其作用?

说一下 jvm 运行时数据区?

说一下堆栈的区别?

队列和栈是什么?有什么区别?

说一下类加载的执行过程?

怎么判断对象是否可以被回收?

java 中都有哪些引用类型?

说一下 jvm 有哪些垃圾回收器?

详细介绍一下 CMS 垃圾回收器?

新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?

简述分代垃圾回收器是怎么工作的?

说一下 jvm 调优的工具?

常用的 jvm 调优的参数都有哪些?

十六、Linux(常用命令)


一、Java基础

JDK 、 JRE 、JVM有什么区别和联系?
  1. JDK :英文名称(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
  2. JRE :英文名称(Java Runtime Environment),Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
  3. JVM :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心,具体的下文会详细说明。

这三者的关系是:一层层的嵌套关系。JDK>JRE>JVM。

== 和 equals 的区别是什么?

== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;

equals 默认情况下是引用比较,只是很多类重写了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等

两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

答案是 不一定!

hashCode()相等的两个对象他们的equal()不一定相等。

equal()相等的两个对象他们的hashCode()肯定相等。

final 在 java 中有什么作用?

final作为Java中的关键字可以用于三个地方。用于修饰类、类属性和类方法。

特征:凡是引用final关键字的地方皆不可修改!

(1)修饰类:表示该类不能被继承;

(2)修饰方法:表示方法不能被重写;

(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

Java的基础类型有哪些?String属于基础的数据类型吗?

基本数据类型:(共有8种)

整型:byte,short,int,long;长度分别为1,2,4,8;

浮点型:float,double;长度分别为 4,8;

字符型:char;长度为 2;

布尔型:boolean;长度为 1。

注:除了以上8种数据类型,剩下的全部都是引用数据类型(strintg属于引用类型)。

java 中操作字符串都有哪些类?它们之间有什么区别?

String、StringBuffer、StringBuilder

String :是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象。

StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。

StringBuffer线程安全,同步锁(synchronized),多线程仍可以保证数据安全

StringBuilder线程不安全,多线程无法保证数据安全

String str="i"与 String str=new String(“i”)一样吗?

答:不一样。

因为内存的分配方式不一样。String str="i"的方式,Java 虚拟机会将其分配到常量池中;而 String str=new String(“i”)方式,则会被分到堆内存中。

String 类的常用方法都有那些?

和长度有关

返回类型

方法名

作用

int

length()

得到一个字符串的字符个数

和数组有关

返回类型

方法名

作用

byte[]

getByte()

将一个字符串转换成字节数组

char[]

toCharArray()

将一个字符串转换成字符数组

String[]

split(String)

将一个字符串按照指定内容分割开

和判断有关

返回类型

方法名

作用

boolean

equals()

判断两个字符串的内容是否一样

boolean

equalsIsIgnoreCase(String)

忽略太小写的比较两个字符串的内容是否一样

boolean

contains(String)

判断一个字符串里面是否包含指定的内容

和改变内容有关

返回类型

方法名

作用

String

toUpperCase()

将一个字符串全部转换成大写

String

toLowerCase()

将一个字符串全部转换成小写

String

replace(String,String)

将某个内容全部替换成指定内容

String

substring(int,int)

从下标x截取到下标y-1对应的元素

String

trim()

去除一个字符串的前后空格

和位置有关

返回类型

方法名

作用

char

charAt(int)

得到指定下标位置对应的字符

int

indexOf(String)

得到指定内容第一次出现的下标

int

lastIndexOf(String)

得到指定内容最后一次出现的下标

如何将字符串反转?
public static String reverse4(String s) {
  return new StringBuffer(s).reverse().toString();
}

接口和抽象类有哪些区别?

抽象类是什么:

抽象类不能创建实例,它只能作为父类被继承。抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象。从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类的随意性。

如果一个类中有抽象方法则这个类一定是抽象类

抽象类中的方法不一定是抽象方法

抽象类不不能使用final修饰  抽象类是用于被继承的,final修饰的类不可修改,不可继承

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

(2)抽象类中可以有普通成员变量,接口中没有普通成员变量

(3)抽象类中可以包含静态方法,接口中不能包含静态方法

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

(5)接口可以被多重实现,抽象类只能被单一继承

(6)如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法

java 中 IO 流分为几种?

IO流的分类

(1)按照数据的流向:

输入流、输出流

(2)按照流数据的格式:

字符流、字节流

(3)按照流数据的包装过程:

节点流(低级流)、处理流(高级流)

最基本的几种进行简单介绍

•InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。

•OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

IO流图表

BIO、NIO、AIO 有什么区别?

BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。这里使用那个经典的烧开水例子,这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。

NIO (New I/O):同时支持阻塞与非阻塞模式,但这里我们以其同步非阻塞I/O模式来说明,那么什么叫做同步非阻塞?如果还拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。

AIO ( Asynchronous I/O):异步非阻塞I/O模型。异步非阻塞与同步非阻塞的区别在哪里?异步非阻塞无需一个线程去轮询所有IO操作的状态改变,在相应的状态改变后,系统会通知对应的线程来处理。对应到烧开水中就是,为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。

进程中的IO调用步骤大致可以分为以下四步:

  1. 进程向操作系统请求数据 ;
  2. 操作系统把外部数据加载到内核的缓冲区中;
  3. 操作系统把内核的缓冲区拷贝到进程的缓冲区 ;
  4. 进程获得数据完成自己的功能 ;
  5. 当操作系统在把外部数据放到进程缓冲区的这段时间(即上述的第二,三步),如果应用进程是挂起等待的,那么就是同步IO,反之,就是异步IO,也就是AIO 。

Files的常用方法都有哪些?
  • Files. exists():检测文件路径是否存在。
  • Files. createFile():创建文件。
  • Files. createDirectory():创建文件夹。
  • Files. delete():删除一个文件或目录。
  • Files. copy():复制文件。
  • Files. move():移动文件。
  • Files. size():查看文件个数。
  • Files. read():读取文件。
  • Files. write():写入文件。

二、容器

java 容器都有哪些?
JAVA中的容器类主要分为两大类,一类是Map类,一类是Collection类,他们有一个共同的父接口Iterator,它提供基本的遍历,删除元素操作。Iterator还有一个子接口linkIterator,它提供双向的遍历操作。

Collection 和 Collections 有什么区别?

Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。

Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。

List、Set、Map 之间的区别是什么?

List:有序集合、元素可重复;ArrayList基于数组实现的有序集合可以存储多个null;linkedList基于链表实现的有序集合可以存储多个null。

Set:无序集合、元素不可重复;linkHashSet按照插入排序可以存储一个null-------SortSet可排序----------HashSet无序可以存储一个null。

Map:键值对集合、储存键、值和之间的映射,Key无序,唯一;Value不要求有序,允许重复。hashmap 、linkedhashmap  key与value均可以为null.  treemap  key不可以为null,value可以为null.  hashtable、concurrenthashmap key与value均不能为null.

HashMap 和 Hashtable 有什么区别?

HashMap允许键和值是null,而Hashtable则不允许键或者值是null。

Hashtable是同步的,而HashMap不是,所以HashMap更适用于单线程环境,Hashtable则适用于多线程环境。

如何决定使用 HashMap 还是 TreeMap?
如果你需要得到一个有序的结果时就应该使用TreeMap(因为HashMap中元素的排列顺序是不固定的)。除此之外,由于HashMap有更好的性能,所以大多不需要排序的时候我们会使用HashMap。

说一下 HashMap 、HashSet的实现原理?

HashMap 的实现原理:

HashMap是基于Hash算法实现的,

我们通过put(key,value)存储数据,通过get(key)来获取数据

当传入key时,HashMap会根据Key.hashCode()计算出Hash值,根据Hash值将value保存在bucket里 。

当计算出相同的Hash值时,我们称之为Hash冲突,HashMap 的做法是用链表和红黑树存储相同Hash值的value,

当hash冲突的个数比较少时,使用链表存储,

否则使用红黑树。

HashSet 的实现原理:

HashSet是基于HashMap实现的,HashSet 底层使用HashMap来保存所有元素,

因此HashSet 的实现比较简单,相关HashSet 的操作,基本上都是直接调用底层HashMap的相关方法来完成,HashSet不允许有重复的值,并且元素是无序的。

ArrayList 和 linkedList 的区别是什么?

数据结构实现:

ArrayList 是动态数组的数据结构实现,而 linkedList 是双向链表的数据结构实现。

随机访问效率:

ArrayList 比 linkedList 在随机访问的时候效率要高,因为 linkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。

增加和删除效率:

在非首尾的增加和删除操作,linkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。

  综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 linkedList。

如何实现数组和 List 之间的转换?

数组转 List ,使用 JDK 中 java.util.Arrays 工具类的 asList 方法

public static void testArray2List() {
	String[] strs = new String[] {"aaa", "bbb", "ccc"};
	List list = Arrays.asList(strs);
	for (String s : list) {
		System.out.println(s);
	}
}

List 转数组,使用 List 的toArray方法。无参toArray方法返回Object数组,传入初始化长度的数组对象,返回该对象

public static void testList2Array() {
	List list = Arrays.asList("aaa", "bbb", "ccc");
	String[] array = list.toArray(new String[list.size()]);
	for (String s : array) {
		System.out.println(s);
	}
}

ArrayList 和 Vector 的区别是什么?
  • Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
  • vector是线程(Thread)同步(Synchronized)的,所以它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。
如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。

Array 和 ArrayList 有何区别?
  • Array类型的变量在声明的同时必须进行实例化(至少得初始化数组的大小),而ArrayList可以只是先声明。(int[] array = new array[3];或 int[] array = {1,2,3};)
  • Array只能存储同构的对象,而ArrayList可以存储异构的对象。同构的对象是指类型相同的对象,若声明为int[]的数组就只能存放整形数据,string[]只能存放字符型数据,但声明为object[]的数组除外。而ArrayList可以存放任何不同类型的数据
  • Array是始终是连续存放的,而ArrayList的存放不一定连续。
  • Array对象的初始化必须只定指定大小,且创建后的数组大小是固定的,而ArrayList的大小可以动态指定,其大小可以在初始化时指定,也可以不指定,也就是说该对象的空间可以任意增加。
  • Array不能够随意添加和删除其中的项,而ArrayList可以在任意位置插入和删除项。

在 Queue 中 poll()和 remove()有什么区别?
队列的两种实现方式
1、offer()和add()的区别
add()和offer()都是向队列中添加一个元素。但是如果想在一个满的队列中加入一个新元素,调用 add() 方法就会抛出一个 unchecked 异常,而调用 offer() 方法会返回 false。可以据此在程序中进行有效的判断!
2、peek()和element()的区别
peek()和element()都将在不移除的情况下返回队头,但是peek()方法在队列为空时返回null,调用element()方法会抛出NoSuchElementException异常。
3、poll()和remove()的区别
poll()和remove()都将移除并且返回对头,但是在poll()在队列为空时返回null,而remove()会抛出NoSuchElementException异常。

哪些集合类是线程安全的?

Vector

Stack

Hashtable

java.util.concurrent包下所有的集合类

   ArrayBlockingQueue、ConcurrentHashMap、ConcurrentlinkedQueue、ConcurrentlinkedDeque...

迭代器 Iterator 是什么?

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

Java中的Iterator功能比较简单,并且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

(2) 使用next()获得序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

Iterator 怎么使用?有什么特点?
public class TestIterator {
       static List list = new ArrayList();
    static {
        list.add("111");
        list.add("222");
        list.add("333");
    }
    public static void main(String[] args) {
        testIteratorNext();
        System.out.println();
        testForEachRemaining();
        System.out.println();
        testIteratorRemove();
    }
    //使用 hasNext 和 next遍历 
    public static void testIteratorNext() {
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            String str = iterator.next();
            System.out.println(str);
        }
    }
    //使用 Iterator 删除元素 
    public static void testIteratorRemove() {
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            String str = iterator.next();
            if ("222".equals(str)) {
                iterator.remove();
            }
        }
        System.out.println(list);
    }
    //使用 forEachRemaining 遍历
    public static void testForEachRemaining() {
        final Iterator iterator = list.iterator();
        iterator.forEachRemaining(new Consumer() {
            public void accept(String t) {
                System.out.println(t);
            }   
        });
    }
}

Iterator 和 ListIterator 有什么区别?

一.相同点

都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用。

二.不同点

1.使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。

2.ListIterator有add方法,可以向List中添加对象,而Iterator不能。

3.ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator不可以。

4.ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

5.都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。

怎么确保一个集合不能被修改?
1. Collections. unmodifiableCollection(Collection c) 方法
List list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        Collection readonlyList = Collections.unmodifiableCollection(list);
        readOnlyList.add(4); // 会报错
2. 使用Arrays.asList创建的集合
List integers = Arrays.asList(11, 22, 33, 44);
        integers.add(55);

三、多线程

并行和并发有什么区别?

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。

你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。

你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

并发的关键是你有处理多个任务的能力,不一定要同时。

并行的关键是你有同时处理多个任务的能力。

所以我认为它们最关键的点就是:是否是『同时』。

线程和进程的区别?

1、首先是定义

进程:是执行中一段程序,即一旦程序被载入到内存中并准备执行,它就是一个进程。进程是表示资源分配的的基本概念,又是调度运行的基本单位,是系统中的并发执行的单位。

线程:单个进程中执行中每个任务就是一个线程。线程是进程中执行运算的最小单位。

2、一个线程只能属于一个进程,但是一个进程可以拥有多个线程。多线程处理就是允许一个进程中在同一时刻执行多个任务。

3、线程是一种轻量级的进程,与进程相比,线程给操作系统带来侧创建、维护、和管理的负担要轻,意味着线程的代价或开销比较小。

守护线程是什么?

守护线程(即daemon thread),是个服务线程,准确地来说就是服务其他的线程,这是它的作用——而其他的线程只有一种,那就是用户线程。所以java里线程分2种,

1、守护线程,比如垃圾回收线程,就是最典型的守护线程。

2、用户线程,就是应用程序里的自定义线程。

创建线程有哪几种方式?

主要有三种:

    继承 Thread 重写 run 方法;

    实现Runnable接口,重写 run 方法;

实现Callable接口,通过FutureTask包装器来创建Thread线程。

    实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。

说一下 Runnable 和 Callable 有什么区别?

1、两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;

2、Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞!

线程有哪些状态?

1、新建状态(New):新创建了一个线程对象。

2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于“可运行线程池”中,变得可运行,只等待获取CPU的使用权,

   即在就绪状态的进程除CPU之外,其它的运行所需资源都已全部获得。

3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。

   阻塞的情况分三种:

①.等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,

   必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒,

②.同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。

③.其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时,或者I/O处理完毕时,线程重新转入就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

sleep() 和 wait() 有什么区别?

sleep:Thread类中定义的方法,表示线程休眠,会自动唤醒;

  wait:Object中定义的方法,需要手工调用notify()或者notifyAll()方法。

  sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。 wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

  sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其他被同步锁挡住了的线程也无法得到执行。wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在notfiy方法后增加一个等待和一些代码,看看效果),调用wait方法的线程就会解除wait状态和程序可以再次得到锁后继续向下运行。

notify()和 notifyAll()有什么区别?

notify()和notifyAll()都是用来用来唤醒调用wait()方法进入等待锁资源队列的线程,区别在于:

notify()

唤醒正在等待此对象监视器的单个线程。 如果有多个线程在等待,则选择其中一个随机唤醒(由调度器决定),唤醒的线程享有公平竞争资源的权利

notifyAll()

唤醒正在等待此对象监视器的所有线程,唤醒的所有线程公平竞争资源

线程的 run()和 start()有什么区别?
  1. start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码;
  2. run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码;

创建线程池有哪几种方式?

java中创建线程池的方式一般有两种:

    通过Executors工厂方法创建

通过new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)自定义创建

线程池都有哪些状态?

线程池的生命周期,总共有五种状态

    RUNNING :能接受新提交的任务,并且也能处理阻塞队列中的任务;

    SHUTDOWN:关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。在线程池处于 RUNNING 状态时,调用 shutdown()方法会使线程池进入到该状态。(finalize() 方法在执行过程中也会调用shutdown()方法进入该状态);

    STOP:不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。在线程池处于 RUNNING 或 SHUTDOWN 状态时,调用 shutdownNow() 方法会使线程池进入到该状态;

    TIDYING:如果所有的任务都已终止了,workerCount (有效线程数) 为0,线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态。

    TERMINATED:在terminated() 方法执行完后进入该状态,默认terminated()方法中什么也没有做。

进入TERMINATED的条件如下:线程池不是RUNNING状态;

              线程池状态不是TIDYING状态或TERMINATED状态;

     如果线程池状态是SHUTDOWN并且workerQueue为空;

              workerCount为0;

              设置TIDYING状态成功。
线程池的生命周期流程图

 线程池中 submit()和 execute()方法有什么区别?

1、接收的参数不一样。exucute只能执行实现Runnable接口的线程,submit可以执行实现Runnable接口或Callable接口的线程

2、submit有返回值,而execute没有

在 java 程序中怎么保证多线程的运行安全?

线程的安全性问题体现在:

    原子性:一个或者多个操作在 CPU 执行的过程中不被中断的特性

    可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到

    有序性:程序执行的顺序按照代码的先后顺序执行

导致原因:

    缓存导致的可见性问题

    线程切换带来的原子性问题

    编译优化带来的有序性问题

解决办法:

    JDK Atomic开头的原子类、synchronized、LOCK,可以解决原子性问题

    synchronized、volatile、LOCK,可以解决可见性问题

    Happens-Before 规则可以解决有序性问题

Happens-Before 规则如下:

    程序次序规则:在一个线程内,按照程序控制流顺序,书写在前面的操作先行发生于书写在后面的操作

    管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作

    volatile变量规则:对一个volatile变量的写操作先行发生于后面对这个变量的读操作

    线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作

    线程终止规则:线程中的所有操作都先行发生于对此线程的终止检测

    线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生

    对象终结规则:一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始

多线程锁的升级原理是什么?

锁的级别从低到高:

无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁
偏向锁轻量级锁轻量级锁
适用场景只有一个线程进入同步块虽然很多线程,但是没有冲突:多条线程进入同步块,但是线程进入时间错开因而并未争抢锁

发生了锁争抢的情况:多条线程进入同步块并争用锁

本质取消同步操作CAS操作代替互斥同步互斥同步
优点不阻塞,执行效率高(只有第一次获取偏向锁时需要CAS操作,后面只是比对ThreadId)不会阻塞

不会空耗CPU

缺点适用场景太局限。若竞争产生,会有额外的偏向锁撤销的消耗长时间获取不到锁空耗阻塞,上下文切换,重量级操作,消耗操作系统资源

什么是死锁?怎么防止死锁?
什么是死锁?
所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。
死锁产生的4个必要条件?
  • 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
  • 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
  • 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。
解决死锁的基本方法
  • 资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)
  • 只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)
  • 可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)
资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)

ThreadLocal 是什么?有哪些使用场景?

ThreadLocal 是线程本地存储,在每个线程中都创建了一个 ThreadLocalMap 对象,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。

经典的使用场景是为每个线程分配一个 JDBC 连接 Connection。这样就可以保证每个线程的都在各自的 Connection 上进行数据库的操作,不会出现 A 线程关了 B线程正在使用的 Connection; 还有 Session 管理 等问题。

说一下 synchronized 底层实现原理?

synchronized 和 volatile 的区别是什么?

名称

内存可见性

指令重排序

原子性

线程是否阻塞

synchronized

可见

会重排序

可以保证

会阻塞

volatile

可见

不会重排序

无法保证

不会阻塞

synchronized 和 Lock 有什么区别?
  • 实现层面不一样。synchronized 是 Java 关键字,JVM层面 实现加锁和释放锁;Lock 是一个接口,在代码层面实现加锁和释放锁
  • 是否自动释放锁。synchronized 在线程代码执行完或出现异常时自动释放锁;Lock 不会自动释放锁,需要再 finally {} 代码块显式地中释放锁
  • 是否一直等待。synchronized 会导致线程拿不到锁一直等待;Lock 可以设置尝试获取锁或者获取锁失败一定时间超时
  • 获取锁成功是否可知。synchronized 无法得知是否获取锁成功;Lock 可以通过 tryLock 获得加锁是否成功
  • 功能复杂性。synchronized 加锁可重入、不可中断、非公平;Lock 可重入、可判断、可公平和不公平、细分读写锁提高效率

synchronized 和 ReentrantLock 区别是什么?
  • synchronized 竞争锁时会一直等待;ReentrantLock 可以尝试获取锁,并得到获取结果
  • synchronized 获取锁无法设置超时;ReentrantLock 可以设置获取锁的超时时间
  • synchronized 无法实现公平锁;ReentrantLock 可以满足公平锁,即先等待先获取到锁
  • synchronized 控制等待和唤醒需要结合加锁对象的 wait() 和 notify()、notifyAll();ReentrantLock 控制等待和唤醒需要结合 Condition 的 await() 和 signal()、signalAll() 方法
  • synchronized 是 JVM 层面实现的;ReentrantLock 是 JDK 代码层面实现
synchronized 在加锁代码块执行完或者出现异常,自动释放锁;ReentrantLock 不会自动释放锁,需要在 finally{} 代码块显示释放

说一下 atomic 的原理?
Atomic通过CAS(Compare And Wwap)乐观锁机制-自旋锁(它的实现很简单,就是用一个预期的值和内存的值进行比较,如果两个值相等,就用预期的值替换内存中的值,并返回true。否则,返回false)保证原子性,【通过降低锁粒度(多段锁)增加并发性能。这一点是java8做出的改进】从而避免synchronized的高开销,执行效率大为提升。

四、反射

什么是反射?
Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。这种在运行时动态的获取信息以及动态调用对象的方法的功能称为Java 的反射机制。

什么是 java 序列化?什么情况下需要序列化?

序列化:将 Java 对象转换成字节流的过程。

反序列化:将字节流转换成 Java 对象的过程。

当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。

序列化的实现:

类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。

注意事项:

    某个类可以被序列化,则其子类也可以被序列化

    声明为 static 和 transient 的成员变量,不能被序列化。static 成员变量是描述类级别的属性,transient 表示临时数据反序列化读取序列化对象的顺序要保持一致

动态代理是什么?怎么实现动态代理?有哪些应用?

动态代理:

当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类创建一个代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处理的新类。这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。

Java 中实现动态的方式:

  • JDK 中的动态代理 
  • Java类库 CGLib

应用场景:

  • 统计每个 api 的请求耗时
  • 统一的日志输出
  • 校验被调用的 api 是否已经登录和权限鉴定
Spring的 AOP 功能模块就是采用动态代理的机制来实现切面编程

五、对象拷贝

为什么要使用克隆?

想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。

克隆分浅克隆和深克隆,浅克隆后的对象中非基本对象和原对象指向同一块内存,因此对这些非基本对象的修改会同时更改克隆前后的对象。深克隆可以实现完全的克隆,可以用反射的方式或序列化的方式实现。

如何实现对象克隆?

1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法;

2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

深拷贝和浅拷贝区别是什么?

浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,

深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。

浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。

深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。

六、Java Web

jsp 和 servlet 有什么区别?

Servlet

    一种服务器端的Java应用程序

    由 Web 容器加载和管理

    用于生成动态 Web 内容

    负责处理客户端请求

Jsp

    是 Servlet 的扩展,本质上还是 Servlet

    每个 Jsp 页面就是一个 Servlet 实例

    Jsp 页面会被 Web 容器编译成 Servlet,Servlet 再负责响应用户请求  

区别

    Servlet 适合动态输出 Web 数据和业务逻辑处理,对于 html 页面内容的修改非常不方便;Jsp 是在 Html 代码中嵌入 Java 代码,适合页面的显示

    内置对象不同,获取内置对象的方式不同

jsp 有哪些内置对象?作用分别是什么?
jsp共有以下9个内置对象:

    1.request  客户端请求,此请求会包含GET/POST请求的参数

    2.response  网页传回客户端的回应

    3.pageContext  网页的属性是在这里管理

    4.session  请求有关的会话期

    5.application  servlet正在执行的内容

    6.out  用来传送回应的输出

    7.config  servlet的架构部分

    8.page  jsp页面网页本身

    9.exception  针对错误网页,未捕捉的例外
作用分别是什么?分别有什么方法?

request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie,header和session数据的有用的方法。

response表示HttpServletResponse对象,并提供了几个用于设置送回浏览器的响应的方法(如cookies,头信息等)。

out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。

pageContext表示一个javax.servlet.jsp.PageContext对象,它是用于方便存取各种范围的名字空间,servlet相关的对象API,并且包装了通用的servlet相关功能的方法。

session表示一个请求的javax.servlet.http.HttpSession对象,Session

可以存储用户的状态信息。

application表示一个javax.servlet.ServletContext对象,这有助于查询有关servlet引擎和servlet环境的信息。

config表示一个javax.servlet.ServletConfig对象,该对象用于存取servlet实例的初始化参数。

page表示从该页面产生的一个servlet实例。

说一下 jsp 的 4 种作用域?

page:代表与一个页面相关的对象和属性。

request:代表与客户端发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;需要在页面显示的临时数据可以置于此作用域。

session:代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。

application:代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域。

session 和 cookie 有什么区别?

1、存储位置不同

cookie的数据信息存放在客户端浏览器上。

session的数据信息存放在服务器上。

2、存储容量不同

单个cookie保存的数据<=4KB,一个站点最多保存20个cookie。

对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。

3、存储方式不同

cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据。

session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。

4、隐私策略不同

cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。

session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。

5、有效期上不同

开发可以通过设置cookie的属性,达到使cookie长期有效的效果。

session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。

6、服务器压力不同

cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。

session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。

7、浏览器支持不同

假如客户端浏览器不支持cookie:

  cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。关于WAP上的应用,常规的cookie就派不上用场了。

  运用session需要使用URL地址重写的方式。一切用到session程序的URL都要进行URL地址重写,否则session会话跟踪还会失效。

假如客户端支持cookie:

  cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。

  session只能在本窗口以及子窗口内有效。

8、跨域支持上不同

cookie支持跨域名访问。

session不支持跨域名访问。

说一下 session 的工作原理?
session 的工作原理是客户端登录完成之后,服务器会创建对应的 session,session 创建完之后,会把 session 的 id 发送给客户端,客户端再存储到浏览器中。这样客户端每次访问服务器时,都会带着 sessionid,服务器拿到 sessionid 之后,在内存找到与之对应的 session 这样就可以正常工作了。

如果客户端禁止 cookie 能实现 session 还能用吗?

一般默认情况下,在会话中,服务器存储 session 的 sessionid 是通过 cookie 存到浏览器里。

如果浏览器禁用了 cookie,浏览器请求服务器无法携带 sessionid,服务器无法识别请求中的用户身份,session失效。

但是可以通过其他方法在禁用 cookie 的情况下,可以继续使用session。

  • 通过url重写,把 sessionid 作为参数追加的原 url 中,后续的浏览器与服务器交互中携带 sessionid 参数。
  • 服务器的返回数据中包含 sessionid,浏览器发送请求时,携带 sessionid 参数。
通过 Http 协议其他 header 字段,服务器每次返回时设置该 header 字段信息,浏览器中 js 读取该 header 字段,请求服务器时,js设置携带该 header 字段。

如何避免 sql 注入?
  1. (简单又有效的方法)使用PreparedStatement
  2. 使用正则表达式过滤传入的参数
  3. 字符串过滤
  4. jsp中调用该函数检查是否包函非法字符
  5. JSP页面判断代码

什么是 XSS 攻击,如何避免?
XSS 攻击原理
攻击者往 web 页面里插入恶意的 HTML 代码(Javascript、css、html 标签等),当用户浏览该页面时,嵌入其中的 HTML 代码会被执行,从而达到恶意攻击用户的目的。如盗取用户 cookie 执行一系列操作,破坏页面结构、重定向到其他网站等。
预防思路
  1. web 页面中可由用户输入的地方,如果对输入的数据转义、过滤处理
  2. 后台输出页面的时候,也需要对输出内容进行转义、过滤处理(因为攻击者可能通过其他方式把恶意脚本写入数据库)
  3. 前端对 html 标签属性、css 属性赋值的地方进行校验

什么是 CSRF 攻击,如何避免?
什么是 CSRF 攻击(跨站请求攻击)
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
防御措施

1.检查Referer字段 

2.添加校验token

七、异常

throw 和 throws 的区别?

throws:用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,谁调用我我就抛给谁。

  用在方法声明后面,跟的是异常类名

  可以跟多个异常类名,用逗号隔开

  表示抛出异常,由该方法的调用者来处理

  throws表示出现异常的一种可能性,并不一定会发生这些异常

throw:则是用来抛出一个具体的异常类型。

  用在方法体内,跟的是异常对象名

  只能抛出一个异常对象名

  表示抛出异常,由方法体内的语句处理

  throw则是抛出了异常,执行throw则一定抛出了某种异常 

final、finally、finalize 有什么区别?

final (可以修饰 类 方法 变量):......

finally(跟try…except连用):不关有没有异常都会执行。

finalize(在java.lang.Object里定义的):这个方法在gc启动,该对象被回收的时候被调用

try-catch-finally 中哪个部分可以省略?
catch 和 finally 语句块可以省略其中一个。

try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
finally 一定会执行,即使是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完之后,才会执行。

常见的异常类有哪些?

Throwable 是异常的根类。

Throwable 包含子类 错误-Error 和 异常-Exception 。

Exception 又分为 一般异常和运行时异常 RuntimeException。

运行时异常不需要代码显式捕获处理。

八、网络 

http 响应码 301 和 302 代表的是什么?有什么区别?

301 表示被请求 url 永久转移到新的 url;

302 表示被请求 url 临时转移到新的 url。

301 搜索引擎会索引新 url 和新 url 页面的内容;302 搜索引擎可能会索引旧 url 和 新 url 的页面内容。

302 的返回码可能被别人利用,劫持你的网址。因为搜索引擎索引他的网址,他返回 302 跳转到你的页面。

forward 和 redirect 的区别?

是servlet种的两种主要的跳转方式。forward又叫转发,redirect叫做重定向。

两者的区别总结:

1. 从地址栏显示来说:

        1)forword是服务器内部的重定向,服务器直接访问目标地址的 url网址,把里面的东西读取出来,但是客户端并不知道,因此用forward的话,客户端浏览器的网址是不会发生变化的。

        2)redirect是服务器根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,所以地址栏显示的是新的地址。

2. 从数据共享来说:

        1)由于在整个定向的过程中用的是同一个request,因此forward会将request的信息带到被重定向的jsp或者servlet中使用。即可以共享数据

        2)redirect不能共享

3. 从运用的地方来说

        1)forword 一般用于用户登录的时候,根据角色转发到相应的模块

        2)redirect一般用于用户注销登录时返回主页面或者跳转到其他网站

4. 从效率来说:

        1)forword效率高,而redirect效率低

5. 从本质来说:

        forword转发是服务器上的行为,而redirect重定向是客户端的行为

简述 tcp 和 udp的区别?

tcp是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来。使用TCP协议传输数据,TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。当数据从A端传到B端后,B端会发送一个确认包(ACK包)给A端,告知A端数据我已收到!

UDP协议就没有这种确认机制,这就是为什么说TCP协议可靠,UDP协议不可靠,提供这种可靠服务,会加大网络带宽的开销,因为“虚拟信道”是持续存在的,同时网络中还会出现大量的ACK和FIN包。TCP协议提供了可靠的数据传输,但是其拥塞控制、数据校验、重传机制的网络开销很大,不适合实时通信,所以选择开销很小的UDP协议来传输数据。UDP协议是无连接的数据传输协议并且无重传机制,会发生丢包、收到重复包、乱序等情况。

区别:

1:TCP基于连接,UDP基于无连接。

2:TCP对系统资源要求高,UDP少。

3:TCP是基于字节流的,UDP是数据报文模式。

4:TCP复杂,UDP简单。

tcp 为什么要三次握手,两次不行吗?为什么?

        两次握手只能保证单向连接是畅通的。

Step1:A -> B : 你好,B。

Step2:A <- B : 收到。你好,A。

这样的两次握手过程, A 向 B 打招呼得到了回应,即 A 向 B 发送数据,B 是可以收到的。

但是 B 向 A 打招呼,A 还没有回应,B 没有收到 A 的反馈,无法确保 A 可以收到 B 发送的数据。

    只有经过第三次握手,才能确保双向都可以接收到对方的发送的 数据。

Step3:A -> B : 收到,B。

这样 B 才能确定 A 也可以收到 B 发送给 A 的数据。

说一下tcp的三次握手和四次挥手?
三次握手过程:

第一次握手:tcp客户端发送一个SYN包序号是j(seq=j),客户端进入SYN_send状态,等服务器确认;

第二次握手:服务器收到客户端发送的这个SYN包,向客户端发送一个ACK确认包(ack=j+1),同时还发送一个SYN包(seq=k)。

第三次握手:客户端收收到SYN包和ACK包之后,再向服务器发送一个ACK确认包(ack=k+1) 发送完建立连接成功
四次挥手过程:

tcp连接时全双工的,需要每一个方向都单独进行关闭,首先执行的一方将执行主动关闭,另一方执行被动关闭

(1)第一次分手: tcp客户端发送一个FIN包(seq=j)

(2)第二次分手:服务器收到FIN包(seq=j)后,发回一个ACK确认包(ack=j+1)

(3)第三次分手:服务器发送一个FIN包(seq=k)到客户端

(4)第四次分手:客户端收到服务器发送的FIN包(seq=K)后,发送ACK包(ack=k+1)断开连接

 第二次握手和第三次握手之间需要等待一段时间确认数据全部接收完毕,才执行三握

说一下 tcp 粘包是怎么产生的?

1、什么是 tcp 粘包?

发送方发送的多个数据包,到接收方缓冲区首尾相连,粘成一包,被接收。

2、原因

TCP 协议默认使用 Nagle 算法可能会把多个数据包一次发送到接收方。

应用程读取缓存中的数据包的速度小于接收数据包的速度,缓存中的多个数据包会被应用程序当成一个包一次读取。

3、处理方法

  1. 发送方使用 TCP_NODELAY 选项来关闭 Nagle 算法
  2. 数据包增加开始符和结束,应用程序读取、区分数据包。
在数据包的头部定义整个数据包的长度,应用程序先读取数据包的长度,然后读取整个长度的包字节数据,保证读取的是单个包且完整。

OSI 的七层模型都有哪些?

OSI七层模型

功能

数据格式

对应的网络协议

对应的网络协议

应用层

提供为应用软件而设的接口,以设置与另一应用软件之间的通信

数据ATPU

DNS、HTTP、FTP、IMAP4、POP3、SSH、TELNET…

应用层

表达层

把数据转换为能与接收者的系统格式兼容并适合传输的格式

数据ATPU

会话层

负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接

数据ATPU

传输层

把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息

数据组织成数据段Segment

TCP、UDP、PPTP、TLS/SSL…

传输层

网络层

决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络数据

分割和重新组合数据包Packet

IP(v4·v6)、ICMP(v6)、IGMP、Ipsec…

网络层

数据链路层

负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成帧。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串

将比特信息封装成数据帧frame

Wi-Fi(IEEE 802.11)、ARP、WiMAX(IEEE 802.16)、PPP、PPPoE、L2TP…

数据链路层

物理层

在局部局域网上传送数据帧(data frame),它负责管理计算机通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机接口卡等

传输比特(bit)流

get 和 post 请求有哪些区别?
  1. GET把参数包含在URL中,POST通过request body传递参数
  2. GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  3. GET请求在URL中传送的参数是有长度限制的,而POST么有。
  4. GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  5. GET请求只能进行url编码,而POST支持多种编码方式。
  6. GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  7. 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  8. GET参数通过URL传递,POST放在Request body中。
  9. GET在浏览器回退时是无害的,而POST会再次提交请求。
  10. GET产生的URL地址可以被Bookmark,而POST不可以。

GET和POST还有一个重大区别:

GET产生一个TCP数据包;POST产生两个TCP数据包。

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

因为POST需要两步,时间上消耗的要多一点,GET比POST更有效!

1. GET与POST都有自己的语义,不能随便混用。

2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。

3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

如何实现跨域?

跨域:当浏览器执行脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域。

  1. 这里的同源指访问的协议、域名、端口都相同。
  2. 同源策略是由 Netscape 提出的著名安全策略,是浏览器最核心、基本的安全功能,它限制了一个源中加载脚本与来自其他源中资源的交互方式。
  3. Ajax 发起的跨域 HTTP 请求,结果被浏览器拦截,同时 Ajax 请求不能携带与本网站不同源的 cookie。