Java终焉时刻

目录

#集合

迭代器(超类Iterator)

迭代的理解

什么是迭代器(Iterator)?

Iterator 和 ListIterator 的区别是什么?

泛型

什么是泛型

泛型的使用要求

泛型的作用

什么是泛型通配符?

通配符使用

Collection集合/集合类/Collection集合/集合类

Map接口hash夺命连问

HashMap的工作原理

HashMap 的扩容过程 ​

Hashmap和hashtable ConcurrentHashMap区别(高薪常问)--面试   安率存用

集合和数组对比

手写冒泡排序 冒泡排序

#了解哪些算法--面试?递归+冒泡排序+LRU算法+JVM垃圾回收算法

 ##MyBatis中缓存的LRU算法

 ##递归(太原面试)

什么是递归?

什么情况会使用递归?

使用Java实现一个简单的递归程序​

JVM算法(GC-jvm垃圾回收算法/是一个守护线程)

简单说说GC  

如何请求垃圾收集

如何发现垃圾/发现垃圾的算法 

如何回收垃圾/回收垃圾的算法 

如何优化/GC垃圾回收机制  

#常见的数据结构(必会) 面试

#常见的设计模式  面试问了

什么是设计模式--面试

常用的设计模式有哪些,简单描述下其应用场景?

一、单例模式(单例模式:在spring配置文件中定义的Bean默认为单例模式)

在下面几个场景中适合使用单例模式:——面试

二、工厂模式(spring IOC --new  工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例)

三、代理模式(AOP   代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术)

门面模式(日志)

连接模式(jdbc)

观察者模式(哨兵机制)

策略模式

模板方法模式

迭代器模式

#反射   面试问了

反射的概念

字节码对象获取的3种方式:/获取反射的三种方法/、反射的原理/反射创建类实例的三种方式 /获得一个类的类对象

反射机制的优缺点?

#面向对象三大特征/Java语言的三大特性??  面试问了

重写和重载的区别 面试问了

#面向对象

对象的创建过程分析

对象的创建方式

#接口+抽象+普通类

抽象类与接口的区别 面试

 抽象类和普通类的区别

说出一些常用的类,包,接口,请各举 5 个 

下面哪些类可以被继承? 

#内部类

内部类的特点

内部类有哪些种类?又有哪些使用场景?

静态内部类和非静态内部类有什么区别?

内部类可以引用他包含类的成员吗?有没有什么限制?

#二阶段web前端 

HTML、CSS、JS代码的功能对比-面试

HTML

简述一下src与href的区别

HTML和xml的区别?

 HTML标签 有哪些

css

什么是盒子模型?

css选择器有哪些

js

js的事件冒泡--面试

在JS中==和===的区别

 面试:js的事件冒泡+.vue双向绑定+.vue数据的显示与隐藏

MVVM框架--面试

MVVM思想

什么是vue

Vue的生命周期/钩子函数

vue双向绑定--面试

vue数据的显示与隐藏--面试

高级用法:v-Vue命令/指令

面试问过:v-if和v-show的区别

组件

vue-router 是什么?它有哪些组件

#二阶段服务器

servlet

什么是 Servlet?

Servlet工作流程/Servlet的生命周期

 Get和Post的区别

在Servlet中实现页面的跳转有两种方式:转发和重定向

请求转发和重定向对比

说一下SpringMVC支持的转发和重定向的写法(必会)

Jsp九大内置(隐式)对象和Servlet四大作用域

Servlet四大作用域

tomcat

概念

工作流程

#网络知识被考到的几率非常大

两个非常重要的网络通讯协议(服务交互中使用最多的两个协议)

HTTP协议

TCP协议

浏览器和 Servlet 通信使用的是什么协议?

#遇到报错怎么排查 遇到过哪些错误--面试


#集合

迭代器(超类Iterator)

迭代的理解

软件开发中,各个开发阶段不是顺序执行的,应该是并行执行,也就是迭代的意思

什么是迭代器(Iterator)?

迭代器Iterator 接口提供了很多对集合元素进行迭代的方法

Iterator 和 ListIterator 的区别是什么?

Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
Iterator 对集合只能是前向遍历,ListIterator 既可以前向也可以后向。
ListIterator 实现了 Iterator 接口,并包含其他的功能,比如:增加元素,替换元素等等。

泛型

什么是泛型

大概的类型,是编译时的一种类型,此类型仅仅在编译阶段有效,运行时无效.

泛型的使用要求

泛型的类型必须使用引用类型,比如Student、Integer,通常应用在类,接口,方法的定义上

1、泛型方法:如果在方法上使用泛型,必须两处同时出现:
    1)一个是方法的参数列表中的参数类型
    2)一个是返回值前的泛型类型,表示这是一个泛型方法
——泛型方法: 访问修饰符 <泛型> 方法返回值类型 方法名(形参){}

如果在类和接口上使用泛型,必须在类名和接口名后写上泛型
2、泛型类:         
class 类名<泛型,…>{}
3、泛型接口: interface 接口名<泛型,…>{}

泛型的作用

1、保证类型安全:
把报错的时机提前,而不是运行时才报错:在向集合中添加元素时,会先检查元素的数据类型,不是要求的类型就编译失败,
2、消除了源代码中的许多强制类型转换

什么是泛型通配符?

当使用泛型类或者接口时,泛型类型不确定,可以通过通配符<?>表示。

通配符使用

基本使用:不知道使用什么类型的泛型时此时可以使用?,?表示未知通配符。

受限泛型:在JAVA的泛型中可以指定一个泛型的上限和下限。

1、泛型的上限:
格式: 类型名称 <? extends 类 > 对象名称
意义: 只能接收该类型及其子类
2、泛型的下限:
格式: 类型名称 <? super 类 > 对象名称
意义: 只能接收该类型及其父类型

Collection集合/集合类/Collection集合/集合类

Map接口hash夺命连问

HashMap的工作原理

1、HashMap的底层结构是数组+链表 或者 数组+红黑树 的形式
   如果链表的长度>8并且数组长度>64时,链表会转为红黑树提高查询的效率,当链表的长度<6时,会重新恢复成链表
2、HashMap底层的Entry[ ]数组,初始容量为16,加载因子是0.75f,扩容按约为2倍扩容
3、存放数据:HashMap通过put和get方法存储和获取。当存放数据时,会根据hash(key)%n算法来计算数据的存放位置,n就是数组的长度,其实也就是集合的容量
   1)当计算到的位置之前没有存过数据的时候,会直接存放数据
   2)当计算的位置,有数据时,会发生hash冲突/hash碰撞,,当单线链表达到一定长度后效率会非常低。

HashMap是非线性安全的。

HashMap中的key可以是普通对象吗?需要注意什么?

Map的key和value都可以是任何类型。但是一定要重写他的equals和hashcode方法,否则容易发生内存泄漏

HashMap原理,java8做了什么改变  面试真题
HashMap是以键值对存储数据的集合容器
HashMap是非线性安全的。

HashMap底层数据结构:数组+(链表、红黑树),jdk8之前是用数组+链表的方式实现,jdk8引进了红黑树
Hashmap数组的默认初始长度是16,key和value都允许null的存在
HashMap的内部实现数组是Node[]数组,上面存放的是key-value键值对的节点。

HashMap通过put和get方法存储和获取。
HashMap的put方法,首先计算key的hashcode值,定位到对应的数组索引,然后再在该索引的单向链表上进行循环遍历,用equals比较key是否存在,如果存在则用新的value覆盖原值,如果没有则向后追加。
jdk8中put方法:先判断Hashmap是否为空,为空就扩容,不为空计算出key的hash值i,然后看table[i]是否为空,为空就直接插入,不为空判断当前位置的key和table[i]是否相同,相同就覆盖,不相同就查看table[i]是否是红黑树节点,如果是的话就用红黑树直接插入键值对,如果不是开始遍历链表插入,如果遇到重复值就覆盖,否则直接插入,如果链表长度大于8,转为红黑树结构,执行完成后看size是否大于阈值threshold,大于就扩容,否则直接结束。

Hashmap解决hash冲突,使用的是链地址法,即数组+链表的形式来解决。put执行首先判断table[i]位置,如果为空就直接插入,不为空判断和当前值是否相等,相等就覆盖,如果不相等的话,判断是否是红黑树节点,如果不是,就从table[i]位置开始遍历链表,相等覆盖,不相等插入。
HashMap的get方法就是计算出要获取元素的hash值,去对应位置获取即可。
HashMap的扩容机制,Hashmap的扩容中主要进行两步,第一步把数组长度变为原来的两倍,第二部把旧数组的元素重新计算hash插入到新数组中,jdk8时,不用重新计算hash,只用看看原来的hash值新增的一位是零还是1,如果是1这个元素在新数组中的位置,是原数组的位置加原数组长度,如果是零就插入到原数组中。扩容过程第二部一个非常重要的方法是transfer方法,采用头插法,把旧数组的元素插入到新数组中。

在 java 7 中, ArrayList 的默认大小是 10 个元素, HashMap 的默认大小是 16 个元素

HashMap 的扩容过程 

当向容器添加元素的时候,会判断当前容器的元素个数,如果大于等于阈值(即当前数组的长度乘以加载因子的值的时候),就要自动扩容啦。Java 里的数组是无法自动扩容的,方法 
是使用一个新的数组代替已有的容量小的数组

Hashmap和hashtable ConcurrentHashMap区别(高薪常问)--面试   安率存用

安:HashMap 是非线程安全的,HashTable 和ConcurrentHashMap是线程安全的 

率:HashMap和 ConcurrentHashMap效率较高, HashTable 效率较低

存:HashMap 的键和值都允许有 null 值存在,而 HashTable 则不行。 

用:单线程环境下,用不同步的HashMap;

        多线程环境下,用同步的Hashtable或者ConcurrentHashMap

Hashtable 是同步的,而 HashMap 不是。因此,HashMap 更适合于单线程环境,而 Hashtable 适合于多线程环境。一般现在不建议用 HashTable,即使在多线程环境下, 现在也有同步的 ConcurrentHashMap 替代,

(HashMap 和 HashTable 区别):

1、HashMap 是非线程安全的,HashTable 是线程安全的。

2、HashMap 的键和值都允许有 null 值存在,而 HashTable 则不行。

3、因为线程安全的问题,HashMap 效率比 HashTable 的要高。

4、Hashtable 是同步的,而 HashMap 不是。因此,HashMap 更适合于单线

程环境,而 Hashtable 适合于多线程环境。一般现在不建议用 HashTable, ①

是 HashTable 是遗留类,内部实现很多没优化和冗余。②即使在多线程环境下,

现在也有同步的 ConcurrentHashMap 替代,没有必要因为是多线程而用

HashTable

(HashTable 和 ConcurrentHashMap 区别):

HashTable 使用的是 Synchronized 关键字修饰,ConcurrentHashMap 是JDK1.7使用了锁分段技术来保证线程安全的。JDK1.8ConcurrentHashMap取消了Segment分段锁,采用CAS和synchronized来保证并发安全。数据结构跟HashMap1.8的结构类似,数组+链表/红黑二叉树。

synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率又提升N倍。

哪些集合类是线程安全的?哪些不安全? 面试真题
线性安全的
Vector:比Arraylist多了个同步化机制。
Hashtable:比Hashmap多了个线程安全。
ConcurrentHashMap:是一种高效但是线程安全的集合。

Stack:栈,也是线程安全的,继承于Vector。
线性不安全的
Arraylist
LinkedList
HashSet
TreeSet

Hashmap
TreeMap

list集合的遍历

集合和数组对比

新手小白学JAVA 数组 数组工具类 二维数组_程序媛 泡泡的博客-CSDN博客_java 数组工具类

数组Array:
数组是用于储存多个相同类型数据的集合,是有序的元素序列。
数组一旦创建,长度无法改变,数组的长度通过**数组名.length;**来获取
        查看数组的长度--数组中存放元素的个数   so(a.length);
        数组的下标从0开始,最大下标为数组长度-1,如果访问到了不存在的下标,会数组下标越界异常       

集合Collection:
集合是用于存储对象的数据结构,可以存放不同类型的对象
集合的长度可变

手写冒泡排序 冒泡排序

外层循环的循环变量代表的是轮数1 2 3 4…
    内层循环的循环变量代表的是数组的下标[0,a.length-i)

冒泡排序:

每次拿两个数进行比较,总是把小的放在最前面,大的放在最后面,第二次是第二个数和第三个数比较,如果第三个小于第二个,那么第三个和第二个替换位置,一次这样比较替换,第一轮循环完了呢,放在最后面的那个数就是这 一串数字中最大的数。第二轮循环和第一轮一样,第一个和第二个比较,最小的放在最前面,依次类推。如果有10个数字,那么就进行9次循环,最小的在最前面,最大的放在最后面。

好处呢,就是查询速度快

package cn.tedu.array;

import java.util.Arrays;

/**本类用来完成冒泡排序*/
public class TestBubbleSort {
	public static void main(String[] args) {
		//1.创建一个无序的数组
		int[] a = {27,96,73,25,21};
		//2.调用method()完成排序
		int[] newA = method(a);
		System.out.println("排序完毕:"+Arrays.toString(newA));
	}
	public static int[] method(int[] a) {
		//1.外层循环,控制比较的轮数,假设有n个数,最多比较n-1次
		//开始值:1 结束值:<= a.length-1 变化:++
		//控制的是循环执行的次数,比如5个数,最多比较4轮,<= a.length-1,最多取到4,也就是[1,4]4次
		for(int i = 1 ; i <= a.length-1 ; i++) {
			System.out.println("第"+i+"轮:");
			//2.内层循环:相邻比较+互换位置
			for(int j=0; j < a.length-i ; j++) {
				//相邻比较,a[j]代表的就是前一个元素,a[j+1]代表的就是后一个元素
				if(a[j] > a[j+1]) {
					//交换数据
					int t = a[j];
					a[j] = a[j+1];
					a[j+1] = t;
					//System.out.println("第"+(j+1)+"次比较交换后:"+Arrays.toString(a));
				}
			}
			System.out.println("第"+i+"轮的结果:"+Arrays.toString(a));
		}
		return a;//把排序好的数组a返回
	}
}

#了解哪些算法--面试?递归+冒泡排序+LRU算法+JVM垃圾回收算法

 ##MyBatis中缓存的LRU算法

LRU也就是“最近最少使用”,LRU缓存就是使用这种原理实现的,就是缓存一定数量的数据,当超过数据的阈值时就将过期的数据删除掉,例如我们缓存10000条数据,当小于该数据时可以随意的增加,超过时就将过期的数据删除掉。
好比java中实现LRU就有两种方式:一是LinkedHashMap保存缓存数据;一种是自己设计的数据结构,使用链表+HashMap保存缓存数据。

 ##递归(太原面试)

什么是递归?

是指函数在运行过程中直接或间接调用自身的一种算法。使用递归的时候,递归方法一定要有结束条件。

什么情况会使用递归?

1 )数据的定义是按递归定义的。

2 )数据的结构形式是按递归定义的。

使用Java实现一个简单的递归程序

使用递归计算100以内的数的累计求和

public class TestDemo {
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {		
			System.out.println(sum(100));
	}
	/**
	 * @param 求和方法
	 */
	public static int sum(int num){
		if(num == 1){
			return 1;
		}
		return num + sum(num-1);
		
	}
 
}

当num 不等于1的时候,方法一直在自己调用,直到num==1的时候,return 1;递归调用结束。

JVM算法(GC-jvm垃圾回收算法/是一个守护线程)

简单说说GC  

GC 是垃圾回收的意思。垃圾收集器会(立刻)自动进行内存管理。

GC可以自动监测回收不被引用的对象,释放其占用的内存。
我们一般把不被引用的对象标志为null,在下一个垃圾回收周期中,这个对象将是可被回收的。

如何请求垃圾收集

如果要请求垃圾收集,可以调用下面的方法之一:System.gc()或Runtime.getRuntime().gc(),
这两个方法用来提示 JVM 要进行垃圾回收。但是,立即开始还是延迟进行垃圾回收是取决于 JVM 的。


何发现垃圾/发现垃圾的算法(判断一个对象是不是要回收/是否存活)   引根 标复代(引根标父代)

常见的「发现垃圾」的算法有两种,引0用计数算法和根搜索算法。
引用计数算法
原理:堆中的对象每被引用一次,则计数器加1,每减少一个引用就减1,当对象的引用计数器为0时可以被当作垃圾收集。
优点:快。
缺点:无法检测出循环引用。如两个对象互相引用时,他们的引用计数永远不可能为0。
根搜索算法(也叫可达性分析)
原理:根搜索算法是把所有的引用关系看作一张图,从一个节点(GC ROOT)开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即可以当作垃圾。

如何回收垃圾/回收垃圾的算法(回收机制) 

注意:线程私有的不存在垃圾回收, 只有线程共享的才会存在垃圾回收, 所以堆中存在垃圾回收.

「回收垃圾」的常见算法有4种:
标记-清除算法
分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成之后统一回收掉所有被标记的对象。
标记-整理算法
标记-清除算法的改进,首先标记出所有需要回收的对象,在标记完成之后不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,在移动过程中清理掉可回收的对象,这个过程叫做整理。
复制算法
将可用内存按容量分成大小相等的两块,每次只使用其中一块,当这块内存使用完了,就将还存活的对象复制到另一块内存上去,然后把使用过的内存空间一次清理掉。
分代收集算法
当前主流JVM都采用分代收集算法, 这种算法会根据对象存活周期的不同将内存划分为年轻代、年老代、永久代,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。

如何优化/GC垃圾回收机制  

使用结束方法 finalize() 可以用来帮助优化对象,

当一个对象没有被引用时,则可以对它进行垃圾收集标记,在进行”垃圾回收”之前,系统将自动调用对象的 finalize() 方法释放对象所占用的内存

#常见的数据结构(必会) 面试

一、数组Array:
数组是在内存中开辟一段连续的内存空间,存放多个相同类型的元素的集合,是有序的元素序列。

创建数组必须明确说明数组的长度,(即数组中元素的个数),以便在内存中留出一块空间存放所有的数组元素,数组中各数据元素在内存中是顺序存放的.

二、队列queue:
是一种运算受限的线性表,仅允许在表的一端进行插入,而在表的另一端进行删除。
先进先出(也就是说,最先存进去的元素,是可以最先取出的)

三、栈Stack:————面试:stack 是什么?
它也是运算受限的线性表,仅允许在标的一端进行插入和删除操作。
先进后出(也就是说,栈中越早存进去的元素,就越在最下面)

四、链表LinkedList:
是一系列节点Node(链表中每一个元素称为节点)组成,节点可以在运行时动态生成。每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。

创建链表时,不需要给出链表中元素(称为节点)的个数,可以先只创建一个链表头,其他元素在需要时动态地创建并加入到链表,链表的数据无素在内存中不是连续存放的.

五、红黑树

#常见的设计模式  面试问了

考察点一般有两个:常用设计模式的实现 设计模式的使用场景/即每个设计模式用来解决什么样的问题

什么是设计模式--面试

代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

是一些前人总结出来的值得学习的编程“套路”

常用的设计模式有哪些,简单描述下其应用场景?

一、单例模式(单例模式:在spring配置文件中定义的Bean默认为单例模式)

 在内存中只有一份对象 ,某个类的实例在 多线程环境下只会被创建一次出来。

单例模式有饿汉式单例模式、懒汉式单例模式和双检锁单例模式三种。

面试问了优点

单例模式的优点: 
在内存中只有一个对象,节省内存空间。
避免频繁的创建销毁对象,可以提高性能。
避免对共享资源的多重占用。
可以全局访问。

应用场景:如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
1、饿汉式:不管是否会使用到这个单例,都会创建这个单例——线程安全,一开始就初始化。 

单例设计模式1-饿汉式实现方式——

创建包: cn.tedu.design
创建类: Singleton1.java

package cn.tedu.design;
/*本类用于实现单例设计模式实现方案1:饿汉式*/
public class Singleton1 {
    public static void main(String[] args) {
        //5.在main()中,不通过对象,直接通过类名,调用静态方法
        MySingle single1 = MySingle.getSingle();
        MySingle single2 = MySingle.getSingle();
        //6.用==检验是否是同一个对象
        System.out.println(single1 == single2);//true
        System.out.println(single1);
        System.out.println(single2);
    }
}
//0.创建自己的单例程序
class MySingle{
    //1.提供构造方法,并将构造方法私有化
    /*1.构造方法私有化的目的:为了防止外界随意创建本类对象*/
    private MySingle(){ }

    //2.创建本类对象,并将对象也私有化
    //4.2由于静态资源只能调用静态资源,所以single对象也需要设置成静态
    private static MySingle single = new MySingle();

    //3.提供公共的访问方式,返回创建好的对象
    //4.1为了不通过对象,直接调用本方法,需要将本方法设置为静态
    public static MySingle getSingle(){
        return single;
    }
}


2、懒汉式:只有在真正用到这个单例的时候才会创建,没有用到就不会创建----必然面临多个线程同时使用实例时的并发问题——非线程安全,在真正用到这个单例的时候才会初始化。

单例设计模式2-懒汉式实现方式
创建包: cn.tedu.design
创建类: Singleton2.java

package cn.tedu.design;
/*本类用于实现单例设计模式优化实现方案2:懒汉式
* 关于单例设计模式的两种实现方式:
* 1.饿汉式:不管你用不用这个类的对象,都会直接先创建一个
* 2.懒汉式:先不给创建这个类的对象,等你需要的时候再创建--延迟加载的思想
* 延迟加载的思想:是指不会在第一时间就把对象创建好占用内存
*               而是什么时候用到,什么时候再去创建对象
* 3.线程安全问题:由于我们存在唯一的对象single2,并且多条语句都操作了这个变量
*   如果将程序放到多线程的环境下,就容易出现数据安全的问题,所以解决方案:
*   1) 将3条语句都使用同步代码块包裹,保证同步排队的效果
*   2) 由于getSingle2()只有这3条语句,所以也可以将本方法设置为同步方法*/
public class Singleton2 {
    public static void main(String[] args) {
        //5.调用方法查看结果
        MySingle2 single1 = MySingle2.getSingle2();
        MySingle2 single2 = MySingle2.getSingle2();
        System.out.println(single1 == single2);
        System.out.println(single1);
        System.out.println(single2);
    }
}
//0.创建自己的单例程序
class MySingle2{
    //6.2创建一个静态的唯一的锁对象
    static Object o = new Object();
    //1.私有化本类的构造方法
    private MySingle2(){ }
    //2.创建的是本类对象的引用类型变量,用来保存对象的地址值,默认值是null
    private static MySingle2 single2 ;
    //3.提供公共的get方法
    synchronized public static MySingle2 getSingle2(){
        //4.判断之前是否创建过对象,之前创建过就直接走return
        //之前如果没有创建过,才走if,创建对象并将对象返回
        //6.有共享数据+多条语句操作数据,所以尽量提前处理,避免多线程数据安全隐患
        //6.1 解决方案1:加同步代码块
        //6.2 解决方案2:将本方法getSingle2()设置为同步方法
        //因为这个方法里所有的语句都需要同步
        synchronized (o) {//静态方法中使用的锁对象也得是静态的
            if (single2 == null) {//single2还是默认值,说明之前没有创建过对象
                single2 = new MySingle2();//没创建过才创建,并赋值给single2
            }
            return single2;
        }
    }
}


3、双检锁:线程安全,在真正用到这个单例的时候才会初始化。

在下面几个场景中适合使用单例模式:——面试

1、有频繁实例化然后销毁的情况,也就是频繁的 new 对象,可以考虑单例模式;

2、创建对象时耗时过多或者耗资源过多,但又经常用到的对象;

3、频繁访问 IO 资源的对象,例如数据库连接池或访问本地文件;


二、工厂模式(spring IOC --new  工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例)

工厂模式主要是为创建对象提供了接口。

应用场景如下:
        1. 在编码时不能预见需要创建哪种类的实例。
        2. 系统不应依赖于产品类实例如何被创建、组合和表达的细节。

工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公 
共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同 
的操作(多态方法)。当得到子类的实例后,开发人员可以调用基类中的方法而 
不必考虑到底返回的是哪一个子类的实例。 


三、代理模式(AOP   代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术)

代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引 
用。实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、 
保护代理、Cache 代理、防火墙代理、同步化代理、智能引用代理。 

门面模式(日志)

连接模式(jdbc)

观察者模式(哨兵机制)

观察者模式又被称作发布/订阅模式,定义了对象间一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
    2. 应用场景如下:
        1. 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
        2. 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

四、构造者模式


五、责任链模式


六、适配器模式

适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使 
原本因接口不匹配而无法在一起使用的类能够一起工作。 


策略模式

    1. 策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换。此模式让算法的变化独立于使用算法的客户。
    2. 应用场景如下。
        1.  一件事情,有很多方案可以实现。
        2. 我可以在任何时候,决定采用哪一种实现。
        3. 未来可能增加更多的方案。
        4. 策略模式让方案的变化不会影响到使用方案的客户。

模板方法模式

    1. 模板方法模式定义一个操作中的算法的骨架,将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些步骤。
    2. 应用场景如下:
        1. 对于一些功能,在不同的对象身上展示不同的作用,但是功能的框架是一样的。

模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式 
实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不 
同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。 
除此之外,还可以讲讲上面提到的门面模式、桥梁模式、单例模式、装潢模式 
(Collections 工具类和 I/O 系统中都使用装潢模式)等,反正基本原则就是拣 
自己最熟悉的、用得最多的作答,以免言多必失。 

 

迭代器模式

    1. 迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
    2. 应用场景如下:
        1. 当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍 历的时候,就应该考虑用迭代器模式。其实stl容器就是很好的迭代器模式的例子。

#反射   面试问了

反射的概念

对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能 就是反射机制

字节码对象获取的3种方式:/获取反射的三种方法/、反射的原理/反射创建类实例的三种方式 /获得一个类的类对象

类名.class
Class.forName(“目标类的全路径”)——最常用
目标类对象.getClass()

反射机制的优缺点?

反射的优点:

反射非常强大,它甚至能直接操作/反射程序的私有属性。
可以解耦;即降低程序的耦合性

缺点:对性能有影响,这类操作总是慢于直接执行java代码。

#面向对象三大特征/Java语言的三大特性??  面试问了

一、封装:
概念:是把过程和数据包裹起来,外界对于数据的操作仅限于我们提供的方式,封装后需要手动提供被封装的资源对外公共的操作方式。

二、继承:
概念:我们可以从现有的类中派生出一个新的类,这个过程称为类继承。子类继承父类方法,使得子类具有父类相同的行为。

三、多态:前提:继承+重写
概念:多态性是指同一个对象有多个不同表现形式

我们所使用的有:
1、向上造型:父类的引用指向子类对象 (父类的引用类型变量保存的是子类对象的地址值)

向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类中声明过的方法,方法体执行的就是子类重过后的功能。但是此时对象是把自己看做是父类类型的,所以其他资源使用的还是父类型的。

2、向下造型:子类的引用的指向子类对象

向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。

四、抽象:抽象就是忽略主题中与当前目标无关的那些方面,以便更好的注意与当前目标有关的方面。在Java中抽象用 abstract 关键字来修饰

重写和重载的区别 面试问了

位置 时间 作用

重载和重写的区别(必会)   Overload 和Override
1、重载:
位置:在同一个类中:同一个类中,存在方法名相同,参数列表不同的方法;
    1)如果参数个数不同,一定构成重载
    2)如果参数个数相同,需要查看对应位置上的参数类型,与参数名无关
时间:发生在编译时
作用:是为了外界调用方法时方便,不管传入什么样的参数,都可以匹配到对应的同名方法
  Overloaded 的方法是可以改变返回值的类型。
2、重写: 
位置:发生在父子类中:

遵循两同两小一大原则  

方法名.参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类(如果父类方法访问修饰符为 private 则子类就不能重写该方法。);
        重写的要求:两同两小一大
        两同:方法名 参数列表 要完全一致
        两小:子类返回值类型小于等于父类的返回值类型(注意此处说的是继承关系,不是值大小)
                比如父类是:void,子类是void
                比如父类是:Cat,子类是MiaoMiao
            子类抛出异常小于等于父类方法抛出异常
        一大:子类方法的修饰符权限要大于等于父类被重写方法的修饰符权限
时间:是指建立了继承关系以后,子类对父类的方法不满意,可以重写,      
作用:在不修改源码的情况下,进行功能的修改与拓展

#面向对象

面向过程(POP):是一种编程思想,强调的是过程——凡事亲力亲为,

面向对象(OOP):也是一种编程思想,强调的是结果——我们不需要关注实现的过程,干这件事的主体并不是自己,自己变成了一个指挥者,只需要关注结果就好。

面向接口编程(IOP): 也是一种编程思想,面向接口编程就是先把客户的业务逻辑线提取出来,作为接口,业务具体实现通过该业务接口的实现类来完成。
                          当客户需求变化时,只需编写该业务接口的新的实现类就可以完成需求。
              代码更加的灵活 松耦合

对象的创建过程分析

Phone p = new Phone(); new对象时,这句代码,内存中会发生什么呢?
1.在栈内存中开辟一块空间,存放引用类型Phone类型的变量p;因为栈先进后出,会先放入栈顶,后续创建新的对象时,会被压栈
2.在堆内存中开辟一块空间,存放Phone类型的对象,并将这个对象进行初始化,比如:String brand = null;
3、执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
4.当对象初始化准备好以后,会生成一个唯一的地址值,然后将此地址值交给引用类型的变量p来保存
5.如果以后想要操作此对象的各种资源,可以通过p变量保存的地址值找到该对象,比如:p.call(); p.price = 66.6;

对象的创建方式

#接口+抽象+普通类

抽象类与接口的区别 面试

 抽象类和普通类的区别

1)抽象类不能用来实例化创建对象;普通类可以
2)如果一个类含有抽象方法,则称这个类为抽象类。抽象方法必须为public或者protected (因为如果为private,则不能被子类继承,子类便无法实现该方法)修饰,缺省情况下默认为public。
3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

说出一些常用的类,包,接口,请各举 5 个 

Java常用包有那些:

Java.lang 
Java.io 
Java.sql 
Java.util 
Java.awt 
Java.net 
Java.math 

Java常用的类:BufferedReader BufferedWriter FileReader FileWirter String Integer 
java.util.Date,System,Class,List,HashMap  Runtime类  StringBuffer类:

常 
用 
的 
接 
口 
: 
Remote 
List 
Map 
Document 
NodeList 

下面哪些类可以被继承? 

1)java.lang.Thread (T)
2)java.lang.Number (T)
3)java.lang.Double (F)
4)java.lang.Math (F)
5)java.lang.Void (F)
6)java.lang.Class (F)
7)java.lang.ClassLoader (T)
答:1、2、7 可以被继承。

#内部类

内部类的特点

定义在一个类中或者方法中的类称为内部类。

1.内部类可以直接访问外部类中的成员,包括私有成员
2.外部类要访问内部类的成员,必须要建立内部类的对象
3.在成员位置的内部类是局部内部类
总结:成员内部类被private修饰以后,无法被外界直接创建对象使用
      所以可以创建外部类对象,通过外部类对象间接访问内部类的资源

内部类有哪些种类?又有哪些使用场景?

内部类可以分为以下四类:

成员内部类【这里是非静态的】
这是最普通的内部类,它定义在一个类的内部中,就如同一个类里的成员变量一样。
成员内部类可以无条件的访问外部类的成员属性和成员方法(包括 private 和 static 类型的成员)
这是因为在成员内部类中,隐式地持有了外部类的引用。
使用场景:当类 A 需要使用类 B ,同时 B 需要访问 A 的成员/方法时,可以将 B 作为 A 的成员内部类。同时我们可以利用 private 内部类禁止其他类访问该内部类,从而做到将具体的实现细节完全隐藏。
什么是成员内部类 
定义在类内部的非静态类,就是成员内部类。成员内部类不能定义静态方法和变量(fifinal修饰的除外)。这是因为成员内部类是非静态的, 
类初始化的时候先初始化静态成员,如果允许成员内部类定义静态变量,那么成员内部类的静态变量初始化顺序是有歧义的。实例: 

public class Out { 
private static int a; 
private int b; 
public class Inner { 
public void print() { 
System.out.println(a); 
System.out.println(b); 


}

静态内部类【这里是成员内部类被静态修饰】
这是使用 static 关键字修饰的内部类,静态内部类不持有外部类的引用,可以看作是和外部类平级的类。
我们想在静态内部类中访问外部类的成员只能 new 一个外部类的对象,否则只能访问外部类的静态属性和静态方法。
使用场景:当类 A 需要使用类 B,而 B 不需要直接访问外部类 A 的成员变量和方法时,可以将 B 作为 A 的静态内部类。
静态内部类如何定义 
定义在类内部的静态类,就是静态内部类。 

局部内部类
这是在代码块或者方法中创建的类。
局部内部类的作用域只能在其所在的代码块或者方法内,在其它地方无法创建该类的对象。
我们可以把局部内部类理解为作用域很小的成员内部类。
使用场景:局部内部类只用于当前方法或者代码块中创建、使用,属于一次性产品,使用场景比较少。

匿名内部类
这是一个没有名字的内部类,通常与匿名对象一起使用,实现了创建实现类+实现方法+创建对象并调用方法的功能
概括一下匿名内部类的特点:
1.必须继承一个父类或实现一个接口,并不需要增加额外的方法,只是对继承方法的实现或是覆盖。
2.只是为了获得一个对象实例,并不需要知道其实际的类型。
3.匿名内部类的匿名指的是没有类名,而不是没有引用指向它。
4.匿名内部类不能有构造方法,只能有初始化代码块。因为编译器会帮我们生成一个构造方法然后调用。
5.匿名内部类中使用到的参数是需要声明为 final 的,否则编译器会报错。
那么为什么匿名内部类中使用参数需要声明为final呢?
因为匿名内部类是创建一个对象并返回,这个对象的方法被调用的时机不确定,方法中有修改参数的可能,如果在匿名内部类中修改了参数,外部类中的参数是否需要同步修改呢?Java 为了避免这种问题,限制匿名内部类访问的变量需要使用 final 修饰,这样可以保证访问的变量不可变。
而且,除了静态内部类,剩下的成员内部类、局部内部类、匿名内部类 都会默认隐式地持有外部类的引用。

使用场景:匿名内部类适合创建那种只需要使用一次的类,也就是说创建一个匿名内部类,只需要用一次即可。

静态内部类和非静态内部类有什么区别?

1.静态内部类不需要有指向外部类的引用;非静态内部类需要持有对外部类的引用
2.静态内部类可以有静态方法、属性;非静态内部类则不能有静态方法、属性

3.静态内部类只能访问外部类的静态成员,不能访问外部类的非静态成员;非静态内部类能够访问外部类的静态和非静态成员
4.静态内部类不依赖于外部类对象的实例,直接生成内部类对象;非静态内部类通过外部类的对象实例生成内部类对象

内部类可以引用他包含类的成员吗?有没有什么限制?

一个内部类对象可以访问创建它的外部类对象的内容。

#二阶段web前端 

HTML、CSS、JS代码的功能对比-面试(web标准的三个方面)

结构+表现+行为

HTML、CSS、JS代码的功能对比
HTML+CSS 静态网页 JS:做动态网页
• HTML 定义网页的内容 H5
• CSS 规定网页的布局 CSS3
JavaScript 实现网站的交互 ES6

HTML:超文本标记语言--静态页面   
CSS:层叠样式表--修饰HTML网页   
JS是一门 基于对象 和 事件驱动 的 脚本语言 ,只能在浏览器中执行------用来提高网页与用户的交互性

HTML

简述一下src与href的区别

href 是指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接。
src是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚本,img图片和frame等元素。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内。这也是为什么将js脚本放在底部而不是头部。

HTML和xml的区别?

 HTML标签 有哪些

css

什么是盒子模型?

什么是盒子模型?
指的是将HTML中所有元素都看成一个盒子,盒子与盒子之间的距离,包括盒子的边框以及盒子边框和盒子内容的距离都可以设置

什么是盒子模型?
在网页中,一个元素占有空间的大小由几个部分构成,其中包括元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分。这四个部分占有的空间中,有的部分可以显示相应的内容,而有的部分只用来分隔相邻的区域或区域。4个部分一起构成了css中元素的盒模型。

css选择器有哪些

简单选择器:
标签名选择器
class选择器
id选择器

复杂选择器:
分组选择器
属性选择器

js

js的事件冒泡--面试

在JS中==和===的区别

 面试:js的事件冒泡+.vue双向绑定+.vue数据的显示与隐藏

MVVM框架--面试

MVVM思想

概念:
M是Model,是指业务模型
V是View,是指视图页面
VM是ViewModel,是指内存中开辟空间,在指定视图里渲染指定数据,用于M和V交互数据


MVVM框架,它最大的特点就是:
MVVM框架实现了页面和数据的分离,代码结构更加清晰,责任更加明确,同时实现自动化:数据变化,页面随之变化

什么是vue

Vue概念: 一个轻量级的mvvm前端渐进式框架,封装了HTML CSS JS的代码。实现前端代码的松耦合
        实现了数据驱动/双向绑定 和 组件化的思想(高内聚)——Vue两大核心思想

Vue的生命周期/钩子函数

可以分为3个阶段
一共8个钩子函数:
初始化阶段(组件创建前/后, 挂载前/后)——beforeCreate created,beforeMount  mounted 
更新阶段(组件更新前/后)——beforeUpdate updated 
销毁阶段(销毁前/销毁后)——beforeDestroy  destroy 

    created和mounted的区别?

created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
    mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些

vue双向绑定--面试

vue数据的显示与隐藏--面试

高级用法:v-Vue命令/指令  面试

一、解析获取属性的三种指令

 <!-- 插值表达式 -->——不能解析标签,直接显示在网页上

 <!-- v-text指令,获取属性的值 -->——不能解析标签,直接显示在网页上

  <!-- v-html指令,获取属性的值 -->——可以解析标签

二、双向绑定指令 v-model——vue中的 属性和输入框 进行绑定

值V和M的数据可以实时同步;不管改M还是改V,对方都能同步

三、闪现指令 v-cloak——解决 错误的插值表达式加载时闪烁 问题

插值表达式我们把位置写错等,没有正确解析,直接让用户看到了插值表达式我们是怎么写的----专门提前规避这个问题

实现在页面未渲染完成时先隐藏标签,渲染完成后再展示,这样就解决了闪烁问题

四、判断指令v-if/v-show/v-else-if

 <!--1.判断指令v-if/v-show————判断条件满足时就展示元素,不满足就不展示 -->

面试问过:v-if和v-show的区别

v-if 在编译过程中会被转化成三元表达式,条件不满足时不渲染此节点。

v-show 会被编译成指令,条件不满足时控制样式将此节点隐藏(display:none)

使用场景
v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景。

v-show 适用于需要非常频繁切换条件的场景。

  控制手段

v-show隐藏则是为该元素添加css--display:none,dom元素依旧还在。

v-if显示隐藏是将dom元素整个添加或删除

v-show的元素始终会被渲染并保存在DOM中,v-show只是简单的切换元素的CSS属性display。

而v-if是真正的条件渲染,因为它会确保切换过程中条件块内的时间监听和子组件适当地被销毁和重建。

v-if和v-show的使用场合
一般而言,v-if有更高的切换开销,而v-show有更高的初始化渲染开销。因此如果要非常的频繁切换,则使用v-show。如果在运行的时候很少改变,则使用v-if较好。
 

五、循环指令v-for用来遍历数组

    <!-- 3.1v-for指令,用来循环遍历数组,语法类似for in-->

六、绑定指令 v-bind

   <!-- 当属性的值是变量而不是字符串时,通过v-bind进行标识,vue会自动处理 -->

组件

vue-router 是什么?它有哪些组件

vue-router 是什么?它有哪些组件
  vue-router是用来定义路由规则的
  组件: 1.router-link  2.router-view

#二阶段服务器

servlet

什么是 Servlet?

Servlet 是用来处理客户端请求并产生动态网页内容的 Java 类。通常Servlet是指HttpServlet,用于处理HTTP请求,必须放在tomcat服务器里才有作用
代表了一个服务器端,主要作用是用来和浏览器动态的交换.
1,接受浏览器发来的请求
2,服务器给浏览器做出响应

Servlet工作流程/Servlet的生命周期

 Get和Post的区别

安量率
1. Get是不安全的,因为在传输过程,数据被放在请求的URL地址中;Post的所有操作对用户来说都是不可见的。       
2. Get传送的数据量较小,一般传输数据大小不超过2k-4k(根据浏览器不同,限制不一样,但相差不大这主要是因为受URL长度限制;Post传送的数据量较大,一般被默认为不受限制。       
3. Get执行效率却比Post方法好。Get是form默认的提交方法。 

Servlet中实现页面的跳转有两种方式:转发和重定向

请求转发和重定向对比

请求转发:forward——由服务器端进行的页面跳转
概念:作用是想让AServlet调用BServlet的功能浏览器访问AServlet ,但是AServlet偷偷调用了 BServlet ,此时浏览器的地址栏没变
当浏览器向服务器发送请求访问某一个资源时,该资源将请求转交给另外一个资源进行处理的过程,就叫做请求转发。

重定向:redirect——由客户端进行的页面跳转
概念:当浏览器向服务器发送请求访问某一个资源A时,资源A在响应时通知浏览器需要再进一步请求才能获取到对应的资源,浏览器再次向服务器发送请求访问资源B(如跳转到百度),
最终是由资源B响应浏览器要获取的数据,这个过程叫做重定向。

址共用率
1.从地址栏显示来说
转发    :是请求request的功能          全程1次请求1次响应,地址栏不变   是服务器跳转  只能跳转当前项目
重定向:是响应response的功能       全程2次请求2次响应,地址栏改变   是浏览器跳转  可以跳转到任意网址
2.从数据共享来说
转发    :转发页面和转发到的页面可以共享数据。
重定向:不能共享数据。
3.从使用来说
转发    :一般用于用户登陆的时候,根据角色转发到相应的模块。
重定向:一般用于用户注销登陆时返回主页面或跳转到其它的网站等。
4.从效率来说
转发    :高
重定向:低

forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。

说一下SpringMVC支持的转发和重定向的写法(必会)


1)转发:
forward方式:在返回值前面加"forward:",比如"”"forward:user.do?name=method4"
2) 重定向:
redirect方式:在返回值前面加redirect:, 比如"redirect:http://www.baidu.com"

Jsp九大内置(隐式)对象和Servlet四大作用域

out对象:用于向客户端、浏览器输出数据。
request对象:封装了来自客户端、浏览器的各种信息。
response对象:封装了服务器的响应信息。
exception对象:封装了jsp程序执行过程中发生的异常和错误信息。
config对象:封装了应用程序的配置信息。
page对象:指向了当前jsp程序本身。
session对象:用来保存会话信息。也就是说,可以实现在同一用户的不同请求之间共享数
application对象:代表了当前应用程序的上下文。可以在不同的用户之间共享信息。
pageContext对象:提供了对jsp页面所有对象以及命名空间的访问。

答:JSP共有以下9种基本内置组件(可与ASP的6种内部组件相对应):
request 用户端请求,此请求会包含来自GET/POST请求的参数
response 网页传回用户端的回应
pageContext 网页的属性是在这里管理
session 与请求有关的会话期
application servlet 正在执行的内容
out 用来传送回应的输出
config servlet的构架部件
page JSP网页本身
exception 针对错误网页,未捕捉的例外

Servlet四大作用域

tomcat

概念

1、服务器: 两种概念,一种物理上真实存在的一台电脑,有独立的IP,配置很高
另一种是计算机上装的一个软件,比如mysql服务器软件、tomcat服务器软件等
2、web服务器:就是一台电脑上装了一个软件,用户可以通过浏览器访问这台上的资源
3、Tomcat服务器:就是一个软件,是一个轻量级的web应用服务器.如果你的程序想要被用户(别 
人)访问, 那么,这个程序必须放入Tomcat中

工作流程

Tomcat服务器接受客户请求并做出响应的过程如下:

1)客户端(通常都是浏览器)访问Web服务器,发送HTTP请求。
2)Web服务器接收到请求后,传递给Servlet容器。
3)Servlet容器加载Servlet,产生Servlet实例后,向其传递表示请求和响应的对象。
4)Servlet实例使用请求对象得到客户端的请求信息,然后进行相应的处理。
5)Servlet实例将处理结果通过响应对象发送回客户端,容器负责确保响应正确送出,同时将控制返回给Web服务器。



#网络知识被考到的几率非常大

两个非常重要的网络通讯协议(服务交互中使用最多的两个协议)

HTTP协议

Http 协议简介:
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是一种客户端和服务器端之间数据传输的格式规范
HTTP是基于TCP/IP通信协议来传输数据,建立连接要通过三次握手,断开连接要经过四次挥手        

TCP协议

TCP是传送控制协议,是面向连接的可靠数据传输协议,TCP会确保数据会可靠的传输到对方.

TCP的三次握手--面试

为了准确无误地把数据送达目标处,TCP协议采用了三次握手策略。 

TCP/IP 协议是  传输层的  一个面向连接的  安全可靠的   传输协议,

三次握手是为了保证能建立一个安全可靠的连接,

第一次握手:客户端发起,客户端会向服务端发送一个报文,在报文里面:SYN(sen四声 位)标志位置为1,表示发起新的连接。

第二次握手:当服务端收到这个报文之后就知道客户端要和我建立一个新的连接,于是服务端就向客户端发送一个确认消息包,在这个消息包里面:ack(啊四声 ke)标志位置为1,表示确认客户端发起的第一次连接请求。

以上两次握手之后,对于客户端而言:已经明确了我既能给服务端成功发消息,也能成功收到服务端的响应。但是对于服务端而言:两次握手是不够的,因为到目前为止,服务端只知道一件事,能收到客户端发给我的消息,但是我响应给客户端的消息,客户端不知道能不能收到。

所以,还需要进行第三次握手:第三次握手就是当客户端收到服务端发送的确认响应报文之后,还要继续去给服务端进行回应,也是一个ack标志位置1的确认消息。通过以上三次连接,不管是客户端还是服务端,都知道我既能给对方发送消息,也能收到对方的响应。那么,这个连接就被安全的建立了。​

四次挥手:由客户端首先发起的,第一次挥手客户端会发送一个报文,在报文里面FIN(份 位)标志位置1,当服务端收到这个报文就知道了客户端想要和我断开连接,但是此时服务端不一定能做好准备,因为当客户端发起断开连接的请求后,对于服务端而言还极有可能有未发送完的消息,还需继续发送,所以此时对于服务端而言只能进行一个消息确认(第二次挥手),即告诉客户端我知道你要和我断开连接,但是我这边还可能没有做好准备,你需要等我一下,等会儿我会告诉你(第三次挥手),于是,发完这个消息确认包过后,可能稍过片刻,服务端会继续发送一个断开连接的报文(第三次挥手),FIN位置1的报文,表示服务端已经做好断开连接的准备,当这个报文发给客户端的时候,客户端同样要给服务端发送一个消息确认的报文(第四次挥手),经过这四次的相互沟通和连接,我就知道了不管是客户端还是服务端都已经做好了断开连接的准备,于是连接断开了。

三次握手:

第一次握手:客户端向服务端发送一个报文,SYN(sen四声 位)标记为1,表示发起新的连接。

第二次握手:服务端收到报文之后,知道客户端要和我建立一个新的连接,会向客户端发送一个确认消息包,ack(啊四声 ke)标记为1

以上两次握手之后,客户端:已经明确了我既能成功给服务端发消息,也能成功收到服务端的响应。但是服务端:只知道能成功收到客户端的消息,但是不知道客户端能不能成功收到我的响应

第三次握手:客户端收到服务端发送的确认消息包之后,要给服务端回应确认消息包,ack标记为1。

通过三次握手,不管是客户端还是服务端,都知道我既能给对方发送消息,也能收到对方的响应。连接安全的建立了。​

四次挥手:

第一次挥手:客户端向服务端发送一个报文,FIN(份 位)标记为1,表示想要断开连接,

第二次挥手:客户端发起断开连接的请求后,服务端极有可能有未发送完的消息,只能发送一个消息确认包,告诉客户端我这边还没有做好准备,需要等我一下,等会儿我会告诉你

第三次挥手:发完消息确认包过后,可能稍过片刻,服务端会向客户端发送一个断开连接的报文,FIN位标记为1,表示已经做好断开连接的准备

第四次挥手:客户端要给服务端发送一个消息确认的报文,

通过四次挥手,不管是客户端还是服务端都已经做好了断开连接的准备,连接安全的断开了。

这就是我对三次握手和四次挥手的一个理解


为什么要三次握手? 
三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是 双方确认自己与对方的发送与接收是正常的。 
SYN:同步序列编号(Synchronize Sequence Numbers)。是TCP/IP建立连接时使用的握手信号。
第一次握手:客户端给服务器发送一个SYN。客户端发送网络包,服务端收到了。服务器得出结论:客户端的发送能力,服务端的接收能力正常。
第二次握手:服务端收到SYN报文之后,会应答一个SYN+ACK报文。服务端发包,客户端收到了。客户端得出结论:服务端的接收和发送能力,客户端的接收和发送能力正常。但是此时服务端不能确认客户端的接收能力是否正常。
第三次握手;客户端收到SYN+ACK报文之后,回应一个ACK报文。客户端发包,服务端收到了。服务器得出结论:客户端的接收和发送能力,自己的接收发送能力都正常。
通过三次握手,双方都确认对方的接收以及发送能力正常。

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

       现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
 

TCP三次握手、四次挥手过程及原理_Harvey_D的博客-CSDN博客_三次握手和四次挥手

浏览器和 Servlet 通信使用的是什么协议?

浏览器和 Servlet 通信使用的是 HTTP 协议

http常见的状态码有哪些?--面试

#遇到报错怎么排查 遇到过哪些错误--面试

打开前端网页F12开发者工具查询-检查请求路径问题+检查传过来的参数是否是我们期望的+检查返回值问题

常见报错:

1)400异常 接受的用户传过来的 参数类型不匹配

 2)404 请求路径不匹配/找不到路径——可能是业务名或者请求路径字母打错了

3)405 前端ajax的请求类型axios.get/post与后端接收@…Mapping的请求类型不匹配.

(会直接在浏览器页面上显示405)

4)500:后端服务器报错,需要去后端idea程序里控制台里的Cause后面看报错

http协议的八种请求类型

请求类型一共有八种,常用的有四种get/delete/post/put,最常用的有两种 get/post

get/delete是一类
post/put是一类

Ajax有四种get/post/put/delete请求类型

.http和https的区别--面试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值