Java面试题总结及答案总结


Java基础:

0.Java的几种基本数据类型
byte --------1字节—8bit(位);
short-------2字节;
int---------4字节;
long-------8字节;
float-------4字节;
double-----8字节;
char-------2字节;
boolean----1字节;

1.== 和 equals 的区别是什么?
答:equals是判断两个变量或者实例指向同一个内存空间的值是不是相同,而==是判断两个变量或者实例是不是指向同一个内存空间。

2.final在Java中有什么作用?
答:用于修饰类、类属性和类方法。
特征:凡是引用final关键字的地方皆不可修改。

3.继承和接口的区别?
1)不同的修饰符修饰(interface),(extends)
2)在面向对象编程中可以有多继承,但是只支持接口的多继承,不支持‘继承’的多继承,而继承在Java中具有单根性,子类只能继承一个父类。
3)在接口中只能定义全局常量和抽象方法,而在继承中可以定义属性方法,常量,变量等
4)某个接口被类实现时,在类中一定要实现接口中的抽象方法,而继承想调用哪个方法就调用哪个方法。

4.接口和抽象类的区别是什么?
1)接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
2)类可以实现很多个接口,但是只能继承一个抽象类
3)类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
4)抽象类可以在不提供接口方法实现的情况下实现接口。
5)Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量
6)Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。
7)接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。

5.方法重写和重载的区别
重载方法:
1)必须是同一个类
2)方法名(也可以叫函数)一样
3)参数的类型不一样或参数数量不一样
重写方法:
1)方法名相同,参数类型相同
2)返回类型必须完全与被重写方法的返回类型相同

总结:
方法重载:就是一个类中定义了多个方法名相同,而他们的参数的数量不同或者数量相同而类型和次序不同。
方法重写:就是在子类存在方法与父类的方法名字相同,而且参数的个数与类型一样,返回值也一样。

6.抽象类可以用final修饰码?
不能。final修饰的类是不能再被继承和修改的。抽象类需要子类继承后实现内部方法的。

7.面向对象与面向过程的区别?优缺点
1)面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

  • 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
  • 缺点:没有面向对象易维护、易复用、易扩展。

2)面向对象:就是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是描述某个事务在整个解决问题的步骤中的行为。

  • 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护。
  • 缺点:性能比面向过程低。

8.什么是泛型?
答:泛型,即“参数化类型”。适用于多种数据类型执行相同的代码;泛型中的类型在使用时指定;泛型归根到底就是“模版”。
意义: 1、自动进行类型的检查,2、自动进行类型转换
泛型在编译的时候并不会进行指定类型的替换,只是拿着指定的类型进行类型检查

9.泛型通配符的上下限
请添加图片描述
10.内部类与外部类的关系
内部类分为: 静态内部类、非静态内部类、匿名内部类和局部内部类。
内部类可以直接访问外部类的私有属性

11.为什么匿名内部类访问方法内的变量必须是final修饰?
用final修饰实际上就是为了保护数据的一致性。用final修饰后,这个这个引用变量的地址值不能改变,所以这个引用变量就无法再指向其它对象了
注意:在java 1.8中,可以不用final修饰,但是千万不要被误导,因为你不用final修饰,在匿名内部类中修改它的值还是会导致编译报错。因为java 1.8其实会自动给它加上final

12.什么是封装?
将字段或者方法使用private进行修饰
封装的意义在于:安全性,让类的调用者对类的使用成本降低了。

13.super和this
this() 调用自己构造方法
this.func()访问方法
this.data 访问属性
this代表当前对象的引用
super 子类在构造的时候需要先帮助父类构造,代表父类对象的引用。
super()显示调用父类的构造方法。

14.向上转型
向上转型发生的时机:
本质:父类的引用 引用子类对象
1)直接赋值 Animal animal = new Dog();
2)方法传参
3)方法的返回值

15.多态及多态的实现方法
它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为。
方式一: 重写
子类重写父类方法,当子类对象调用重写的方法时,调用的是子类的方法,要想调用父类中被重写的方法,必须使用super关键字。
方式二: 接口
方法三: 抽象类和抽象方法

16.什么是抽象类
答:包含抽象方法的类
1)抽象类不能进行实例化 就是 Shape shape = new Shape();
2)在抽象类当中,可以拥有和普通类一样的数据成员和方法
3)抽象类是可以被继承的,可以发生向上转型。
4)当一个普通类继承了一个抽象类,那么当前这个普通类一定要重写抽象类中的抽象方法
5)当普通类继承了抽象类,且不想实现抽象类中的抽象方法的时候,那么这个普通类可以被修改为抽象类,此时就不需要进行实现了。
6)抽象方法不能是private修饰的,因为抽象方法就是用来被重写的
7)抽象类的出现 就是为了被继承

17.什么是接口
接口:使用关键字interface修饰
1)接口当中的方法,不能有具体实现。接口当中的方法,默认是:public abstract
2)接口当中的成员变量,默认是public static final
3)jdk1.8引入的新特性。default修饰的方法,默认方法。
4)接口不可以进行实例化
5)类和接口之间的关系是,implements
6)一个类可以实现多个接口
7)一个类可以继承类,同时可以实现多个接口
8)接口可以扩展多个接口:interface D extends A,B,C
7)所以接口的出现就是解决Java多继承问题

18.String 和 StringBuilder StringBuffer 的区别
1)后两者包含了一些string没有的方法,比如reverse方法
2)后两者是可变的,string是不可变的。string的每次拼接,都会产生新的对象后两者每次的拼接都返回的this。

19.StringBuilder和StringBuffer 的区别

  1. StringBuilder和String 出现在单线程情况下
    2)StringBuffer 因为有synchronized关键字 所以一般出现在多线程情况下

20.StringBuilder和String的区别
1)String的拼接“+” 会被优化为StringBuilder.append了
2)在循环当中不可以使用String直接进行拼接,这样会产生大量的临时对象。包括优化后StringBuilder对象。

21.什么是反射机制?
其实就是动态加载一个指定的类,并获取该类中的所有的内容。并将字节码文件中的内容都封装成对象,这样便于操作这些成员。简单说:反射技术可以对一个类进行解剖。

22.深拷贝和浅拷贝的区别
浅拷贝:当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
深拷贝:除了对象本身被复制外,对象所包含的所有成员变量也被复制。

数据结构:

1.堆和栈的区别?
1)申请方式:栈由系统自动分配,而堆是人为申请开辟
2)申请大小:栈获得的空间较小,而堆获得的空间较大
3)申请效率:栈由系统自动分配,速度快,而堆一般速度比较慢;
4)存储内容不同:栈使用的是一级缓存,堆是存放在二级缓存中
5)底层不同:栈是连续的空间,而堆是不连续的空间。
6)堆:可以看成是一棵树;栈:一种先进后出的数据结构

2.List Set Map 的区别?
1)List Set都是继承自Collection接口,Map则不是
2)List特点:元素有放入顺序,元素可重复,Set特点:元素无放入顺序,元素不可重复,重复的元素会被覆盖。
3)set搜索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。list和数组类似,list可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。map适合存储键值对的数据。
4)LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
HashMap是非线程安全的,HashTable是线程安全的;
StringBuilder是非线程安全的,StringBuffer是线程安全的。

3.队列、数组、链表、栈的区别?
1)数组与链表是更加偏向数据存储方式的概念,数组在连续的空间中存储数据,随机读取效率高,但是数据添加删除的效率较低;而链表可以在非连续的空间中存储数据,随机访问效率低,数据添加删除效率高。
2)队列和栈是描述数据存取方式的概念,队列是先进先出,而堆栈是后进先出;队列和栈都可以使用数组或者链表来实现。

4.hashmap与hashtable的区别?
1)HashMap不是线程安全的。HashMap是map接口的子类,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。HashMap允许键和值是null,而Hashtable不允许键或者值是null。
2) HashTable是线程安全。HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。
3)Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。

5.ArrayList与LinkedList的区别?
1)ArrayList的实现是基于数组来实现的,LinkedList是基于双向链表来实现。
2)LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
3)对于随机访问,ArrayList要优于LinkedList。
4)当对数据进行增加和删除的操作时(add和remove操作),LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。

6.Java中的HashMap的工作原理是什么?
答:Java中的HashMap是以键值对(key-value)的形式存储元素的。HashMap需要一个hash函数,它使用hashCode()和equals()方法来向集合/从集合添加和检索元素。当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上。如果key已经存在了,value会被更新成新值。

8.数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList?
1)Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
2)Array大小是固定的,ArrayList的大小是动态的
3)ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
4)对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。

9.数组和链表的区别
1)从逻辑结构的角度:数组必须实现定于固定长度,链表可以动态进行存储分配,可以适应数据动态地增减,方便插入和删除。
2)从内存存储的角度:数组在栈中分配空间,方便但自由度小;链表从堆中分配空间,自由度大但麻烦。
3)从访问方式的角度:数组在内存中是连续的存储。因此可以利用下标索引进行访问;链表是链式存储结构,在访问元素的时候只能通过线性方式由前到后顺序的访问,访问效率比数组低。

线程:

1.进程和线程的区别是什么?
答:进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。

2.并行和并发有什么区别?
并发:是指多个线程任务在同一个cpu上快速地轮换执行,并发只是一种逻辑上的同时执行。
并行:是指多个线程任务在不同cpu上同时进行。

造成线程不安全的原因
1.cpu抢占式执行(根本原因)
2.非原子性:操作并不是一步操作就能执行完成的,当cpu执行一个线程过程时,调度器可能调走cpu,去执行另一个线程,此线程的操作可能还没有结束(通过锁来解决)
3.多个线程同时修改同一个变量
4.指令重排序(编译器优化):为了提高运行效率,编译器做的优化
5.内存可见性:对于一个共享变量,当有一个线程对其进行操作能及时被其他线程看到(很关键的原因)
编译器优化在单线程下没有问题,可以提升程序的执行效率,但是在多线程下就会出现混乱,从而导致线程不安全的问题。

线程安全解决方案
1.使用final修饰变量:不可变的变量自然能够保证可见性
2.加锁(Synchronized/LOCK)

3.创建线程的三种方式
1)继承thread实现run方法:

class MyThread extends Thread

2)实现Runnable重写run方法:

class MyRunnable implements Runable

3)实现Callable重写call方法

class MyCallable implements Callable

上述三种方法都可以定义成为静态内部类之后在main函数中通过new这个内部类对象来调用线程的start方法实现。

4.线程的 run()和 start()有什么区别?
start(): 用start方法来启动线程,真正实现了多线程运行。产生线程对象后,调用start()方法启动线程处于运行状态(Runnable)中就绪状态(Ready),此时线程等待被cpu调度,调度后在执行run()方法。
run(): run方法是thread中一个普通方法,当程序有两个新建线程时,调用run(),程序会按照顺序运行,并且执行的是主线程。
1)run属于普通方法;而start属于启动线程的方法
2)run方法可以执行多次,而start方法只能执行一次。

5.sleep() 和 wait() 有什么区别?
1)wait()是object中的普通成员方法,sleep()是thread中的静态方法;
2)wait()使用可以不传参数,sleep()必须传入一个大于等于0的参数
3)wait()会让当前线程无限休眠下去,sleep()会立即触发一次cpu的抢占执行(相当于一瞬间的让位动作)
4)wait()使用必须配合加锁和释放锁 sleep()使用不需要加锁和释放锁;
5)wait()会让线程进入WAITING状态;sleep()会让线程进入TIME_WAITING状态;

6.wait为什么要加锁
答:wait在使用的时候需要释放锁,因此必须要加锁。

7.wait为什么要释放锁
答:wait默认是不传任何值的,当不传递任何值的时候表示永久等待,这样就会造成一把锁被一个线程一直持有,为了避免这种问题的发生,所以在使用wait时一定要释放锁。

为什么wait会放到object中,而不是thread?
答:wait 必须要加锁和释放锁,锁又是属于对象级别而非线程级别(线程和锁是一对多的关系,也就是一个线程可以拥有多把锁),为了灵活起见(一个线程当中会有多把锁),就把wait放在object中。

8.interrupted()和isInterrupted()区别:
interrupted()是全局的方法,它判断完之后会重置线程的状态。
isInterrupted()不会重置

9.volatile的作用
1.禁止指令重排序
2.解决线程可见性的问题

10.volatile如何解决内存可见性的问题
实现原理:当操作完变量之后,强制删除掉线程工作内存中的此变量。

11.Java中解决线程安全问题的方案
1)synchronized加锁和释放锁(jvm层面的解决方案,自动进行加锁和释放锁)
2)Lock手动锁

12.线程有哪几种状态?
1)新建状态(NEW)
2)就绪状态 (Runnable)
3)运行状态 (Running)
4)阻塞状态(Blocked)
5)死亡状态(Dead)

13.notify()和 notifyAll()有什么区别?
答:notify()方法随机唤醒对象的等待池中的一个线程,进入锁池;notifyAll()唤醒对象的等待池中的所有线程,进入锁池。

14.synchronized的实现原理
1)在Java层面,是将锁信息存放在对象头中,当使用synchronized修饰代码时会在编译之后在代码的前面和后在代码的前面和后面加监视器锁
2)在操作系统层面:他是使用互斥锁来实现的。

15.synchronized的使用场景
1.使用synchronized来修饰代码块(加锁对象可以自定义);
2.使用synchronized来修饰静态方法(加锁对象是当前的类对象);
3.使用synchronized修饰普通方法(加锁对象是当前类的实例)

16.synchronized和lock的区别?
1)synchronized是JVM提供的锁的解决方案;lock是一个类,需要手动实现。
2)synchronized可以修饰代码块、静态方法、普通方法,而lock只能修饰代码块。
3)synchronized不需要手动释放锁,lock需要手动释放锁。
4)synchronized是非公平锁,而lock可以由用户设定是否为非公平锁(ReentrantLock默认是非公平锁,也可以通过构造函数设置true声明它为公平锁)

17.synchronized和volatile有什么区别?
volatile可以解决内存可见性问题和禁止指令重排序,但volatile不能解决原子性问题;synchronized可以解决任何关于线程安全的问题。

18.造成死锁的原因
死锁定义:两个或两个以上的线程在执行的时候因为资源的争抢造成的阻塞状态
1)互斥条件:(当前对象被一个线程拥有后,不能被其他条件锁拥有)
2)请求拥有条件:(请求获得别人此时拥有的条件)
3)不可剥夺条件:(资源被一个人拥有,若不主动释放,是不可被剥夺的)
4)环路等待条件:(多个线程在获取资源时形成了一个环形拉链
(可被修改的))

19.如何解决死锁问题?
从以下两个条件入手,修改以下条件任意一个:
1.请求拥有条件
2.环形等待条件

20.Thread.sleep(0) VS Object.lock(0)区别?
1)sleep是thread的静态方法;而lock是object的方法;
2)sleep(0) 表示立即出发一次cpu资源的抢占,lock(0)永久的等待下去。

21.wait/notify/notifyAll使用注意事项
1)在使用以上方法的时候必须要加锁。
2)加锁对象和wait/notify/notifyAll的对象必须保持一致。
3)一组wait和notifiy/notifyAll必须是同一对象。
4)notifyAll只能唤醒当前对象的所有等待线程

22.wait(), notify()方法的使用时为什么需要加锁

  • wait的含义是:释放当前对象的锁,并进入阻塞队列;
  • wait方法进行了两步操作,首先是释放了当前对象的锁,其次是进入阻塞队列
  • notify含义是:唤醒当前对象阻塞队列里的任一线程
  • notify方法用来唤醒一个线程必须先找到要唤醒的对象,即获取该对象的锁,才去该对象对应的等待队列中去唤醒一个线程。
  • notifyAll的含义是:唤醒当前对象阻塞队列的所有线程。
  • 因调用wait方法而导致阻塞的线程是放在阻塞队列中的。
  • 因竞争失败导致的阻塞的线程是放在同步队列中的。
  • notify/notifyAll的实质是把阻塞队列中的线程放到同步队列中

23.wait和LockSupport 的区别
相同点:
1)两个都可以进行休眠
2)二者都可以传参或不传参,并且二者线程状态也是一致的
不同点:
1)wait必须要配合synchronized一起使用,而LockSupport不用加锁
2)wait只能唤醒全部和随机一个线程,而LockSupport可以唤醒指定的线程。

23.CAS的底层实现原理?
Java层面,CAS是实现了unsafe, unsafe类调用了c++的本地方法,通过调用操作系统的原子指令:Atomic::cmpxchg实现。
CAS造成 ABA问题的解决方案:引入版本号
使用AtomicStampedReference代替AtmoicReference来修饰要引入版本号的变量。

24.乐观锁VS悲观锁
乐观锁:认为一般情况不会发生冲突,只有在数据更新时才会检测是否发生了冲突。
乐观锁的具体实现:CAS 比较并且交换
悲观锁:认为在通常情况下一定会发生并发冲突,所以在进入方法之后就会加锁。synchronized是一种悲观锁/可重入锁/非公平锁/非共享锁。

25.公平锁 vs 非公平锁
公平锁:锁的获取顺序和线程方法的先后顺序保持一致。优点:执行是有序的,结果可以预期。
非公平锁:锁的获取顺序和线程获取锁的顺序无关。优点:性能比较高。

25.什么是单例模式,如何设计单例模式
保证整个系统中一个类只有一个对象的实例,实现这种功能的方式就叫单例模式。
实现单例模式的思路:
1)构造私有:
如果要保证一个类不能多次被实例化,那么我肯定要阻止对象被new出来,所以需要把类的所有构造方法私有化。
2)以静态方法返回实例:
因为外界就不能通过new来获得对象,所以我们要通过提供类的方法来让外界获取对象实例。
3)确保对象实例只有一个:
只对类进行一次实例化,以后都直接获取一次实例化的对象。

/**
 * 单例模式案例
 */
public class Singleton {
	//确保对象实例只有一个。
 private static final Singleton singleton = new Singleton();
	//构造方法私有
 private Singleton() {
    }
 //以静态方法返回实例
 public static Singleton getInstance() {
 return singleton;
    }
}

饿汉模式
先把对象创建好,等我要用的时候直接来拿

public class Singleton {
 
 
//先把对象创建好
private static final Singleton singleton = new Singleton();
 
 private Singleton() {
    }
 
//其他人来拿的时候直接返回已创建好的对象
 
public static Singleton getInstance() {
 return singleton;
    }
}

懒汉模式
先不创建类的对象实例,等你需要的时候在创建

/**
 * 单例模式案例
 */
public class Singleton {
 
 private static Singleton singleton = null;
 
 private Singleton() {
    }
  //获取对象的时候再进行实例化
 public static Singleton getInstance() {
     synchronized (Singleton.class) {
 
 if (singleton == null) {
 singleton = new Singleton();
            }
 
   }
 return singleton;
    }
}

网络:

0. tcp 和 udp的区别?
1)UDP无连接、TCP有链接;
2)UDP不稳定、TCP稳定;
3)UDP面向数据报、TCP面向数据流;
4)UDP只有接受缓冲区,没有发送缓冲区;TCP两个缓冲区都有。
5)UDP和TCP使用的场景是不同,如果对稳定性要求比较高,那么应该使用tcp,如果对消息丢失不敏感,要求性能比较高,那么考虑udp。

1.如何使用udp实现稳定的消息传输?
参考tcp实现稳定性的特性来设计
保证稳定性:1.确认应答;2.超时重传;3.连接管理;4.流量控制;阻塞控制。

2.OSI七层模型
1)应用层:将标准的数据转换成程序需要的格式
2)表示层:将设备的数据格式转化成标准的格式
3)会话层:用来管理通迅双方之间的会话
4)传输层:用来确保双方的数据可以正常传输
5)网络层:地址的管理和路由的选择
6)数据链路层:保证相邻节点之间的数据传递
7)物理层:将数字信号传递成为光电信号

3.TCP/IP四层模型
1)应用层:常用协议有HTTP(80),SSH(22),FTP(21),TELNET(23),DNS(53),
2)传输层:常用协议有TCP,UDP
3)网络层:ARP协议,IP协议,ICMP协议,IGMP协议
4)数据链路层

4.TCP三次握手过程
第一次握手:主机A通过向主机B 发送一个含有同步序列号的标志位的数据段给主机B,向主机B 请求建立连接,通过这个数据段, 主机A告诉主机B 两件事:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我。

第二次握手:主机B 收到主机A的请求后,用一个带有确认应答(ACK)和同步序列号(SYN)标志位的数据段响应主机A,也告诉主机A两件事:我已经收到你的请求了,你可以传输数据了;你要用那个序列号作为起始数据段来回应我

第三次握手:主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B 的数据段:"我已收到回复,我现在要开始传输实际数据了,这样3次握手就完成了,主机A和主机B 就可以传输数据了。

5.三次握手的特点
答:没有应用层的数据 ,SYN这个标志位只有在TCP建立连接时才会被置1 ,握手完成后SYN标志位被置0。

6.四次挥手过程
第一次: 当主机A完成数据传输后,将控制位FIN置1,提出停止TCP连接的请求 ;

第二次: 主机B收到FIN后对其作出响应,确认这一方向上的TCP连接将关闭,将ACK置1;

第三次: 由B 端再提出反方向的关闭请求,将FIN置1 ;

第四次: 主机A对主机B的请求进行确认,将ACK置1,双方向的关闭结束。

三次挥手行不行
有可能可以,要看接收缓冲区中有没有任务,如果没有待结束的任务,两次挥手就可以合并。(捎带应答)

确认应答带来的问题:
1.发送消息丢失
2.ACK丢失
利用超时重传的策略:
策略1: 发送不会以固定的频率发送。策略1采取的是悲观的策略,如果第一次消息发送失败了,那么大概率第二次发送消息也会失败,所以tcp会以指数级超时时间增长的频率来发送消息。
第一次超时重发的时间间隔:500ms
第二次超时重发的时间间隔:2x500ms
第三次超时重发的时间间隔:4x500ms
策略2: 如果经历了一定的重试次数,消息还没有得到应答,那么就会停止发送。

滑动窗口
一次一批一批的发送数据
快重传机制: 每次服务器给客户端响应的ACK都是最大的ACK,如果小的ACK丢失了,会等小的ACK补全之后就可以接收到下一轮的任务。
滑动窗口是越大越好吗?
答:当滑动窗口设置的越大,信息在传递的时候吞吐量就越大,一次需要传递的内容就越大,如果传输的信息比较多而接收端的接受能力比较弱,就会导致接收缓冲区爆满,会导致信息的舍弃,无法进行消息的应答,导致触发大量的超时重传,形成恶循环。

流量控制
流量控制是会查看接收缓冲区的大小,发送消息时,将这个大小放在消息头中的16位窗口大小中,客户端拿到这个值后根据这个值决定下次传递多少数据,但它传递的最大值是不会超过滑动窗口的值的。
当接收大小缓冲区为0时:
(1)停止消息发送
(2)发送检测包,每隔一段时间去询问接收端的缓冲区大小

拥塞控制
发送大量数据,网络阻塞,tcp引入慢启动机制
慢启动机制: 先发送少量的数据,摸清当前的网络拥堵状态,再去决定按照多大的速度传输数据。慢启动只是初始时慢,增长速度还是比较快的。而之前说的快重传指的是ACK返回的始终是数据连续的最大值。

沾包/半包问题
沾包和半包都是指得到的数据不是预期的数据
沾包解决方案:
(1)以\n作为流的边界来处理沾包和半包问题;
(2)每次按照固定大小读取数据包,这样能确定每个数据的边界

7.get和post有什么区别?
1)get是不安全的,因为在传输过程,数据被放在请求的URL中;post的所有操作对用户来说都是不可见的,post放在request body中。
2)get传送的数据量较小;post传送的数据量较大,一般默认为不受限制
3)get限制form表单的数据集的值必须为ASCII字符;而post支持整个ISO10646字符集。
4)get执行效率却比post方法号。get是form提交的默认方法。
5)get通过地址栏传输,post通过报文传输

http接口:url对应的是某种操作,只需对数据操作,切换URL地址
restful接口:URL对应一种数据,对数据的操作,需要切换http请求方法实现

8.get,post请求发送的数据包有什么不同?
1)get请求,发送一个tcp数据包,将http header和data一起发送出去,服务器响应为200.
2)post请求,发送两个tcp数据包,先发送header,服务器响应100 continue 浏览器再发送data 服务器响应200

get请求有request body吗,能否将请求参数放到里面?
答:get请求和post请求都是tcp连接方式,所以两者能做的事一模一样,只是规定上get请求不允许在request body中写参数。

9.输入一个 URL之后会发生什么?
1)校验URL正确性:浏览器的行为,检查是否符合http的规范
2)检测本地缓存
3)访问DNS服务器,实现域名解析:获得所有访问页面的IP和端口号
4)建立TCP链接(三次握手)
5)浏览器会将参数和请求信息发送给服务器端
6)服务器得到请求的参数信息,然后再进行业务处理:服务器端查询数据库/操作数据库。
7)服务器将信息返回给客户端
8)浏览器拿到响应的信息之后,通过浏览器的执行引擎解析结果并展示给用户。
9)TCP是短链接,所以进行连接断开(四次挥手)

10.http和https有什么不同
1)http协议以明文方式发送内容,不提供任何方式的数据加密;运行在TCP上。
2)https协议在http的基础上加入了SSL协议来验证服务器身份,对浏览器和服务器之间的通信加密。运行在SSL/TLS上,而SSL/TLS同样运行在TCP上------主要作用:建立一个信息安全通道;确认网站真实性。

11.https的工作原理
1)客户端URL访问web服务器,请求与服务器建立SSL链接。
2)web服务器收到请求后,将网站的证书信息,发送给客户端。
3)客户端确认SSL链接的安全等级(信息加密等级)。
4)客户端根据最终的安全等级,建立会话密钥,使用服务器端传过来的公钥进行加密,并发送给服务器端。
5)服务器端使用自己私钥解密客户端发送来的密钥。
6)利用密钥实现客户端与服务器端的加密通讯。

12.什么是对称加密、非对称加密?
对称加密:使用同样的密钥进行加密与解密
非对称加密:使用不同样的密钥密钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥能解密,私钥加密—>公钥解密

13.session与cookie区别
1)cookie保存在客户端,session保存在服务器端
2)session的实现是依赖sessionID的,而sessionID是存储在cookie中,所以如果禁用了cookie那么整个session机制也不能使用。
3)cookie有大小限制,为了防止网络传输中的负担,一般最大值为4k
4)cookie在本地容易被串改,而session在客户端,通常情况下session比cookie更加安全。

session 与cookie相关问题
(1)cookie,在客户端记录信息确认用户身份
http是一种无状态协议(一旦数据变换完毕就会关闭,再次交换就要重新建立连接),服务器从网络连接上无从知道客户端的身份,所以服务器给客户端每个人发一个通行证,每个人访问时都必须携带通行证,服务器端从通行证上确认客户端的信息(同时也在里面记录状态信息)
(2)session,在服务器端记录信息确认身份
session机制是通过检查服务器上的“客户明细表”来确认客户身份,这个表上的内容就是要确认sessionID的信息,如果禁用了cookie,就得不到session,因为sessionID是通过cookie传递的。

如何预防本地用户禁用了cookie后影响到浏览器的session不能使用?
答:将sessionID记录在URL中,每次传递他,这样就不会丢失。

14.http常见状态码
100:这个状态码是告诉客户端应该继续发送请求,这个临时响应是用来通知客户端的,部分的请求服务器已经接受,但是客户端应继续发送求请求的剩余部分,如果请求已经完成,就忽略这个响应,而且服务器会在请求完成后向客户发送一个最终的结果
200:这个是最常见的http状态码,表示服务器已经成功接受请求,并将返回客户端所请求的最终结果
202:表示服务器已经接受了请求,但是还没有处理,而且这个请求最终会不会处理还不确定
204:服务器成功处理了请求,但没有返回任何实体内容 ,可能会返回新的头部元信息
301:客户端请求的网页已经永久移动到新的位置,当链接发生变化时,返回301代码告诉客户端链接的变化,客户端保存新的链接,并向新的链接发出请求,已返回请求结果
404:请求失败,客户端请求的资源没有找到或者是不存在
500:服务器遇到未知的错误,导致无法完成客户端当前的请求。
503:服务器由于临时的服务器过载或者是维护,无法解决当前的请求。

15.SSL层怎么进行数据加密
1)A给出支持SSL协议版本号,一个客户端随机数(Client random)客户端支持的加密方法等信息。
2)B收到信息后,确认双方使用的加密方法,并返回数字证书,一个服务器生成的随机数(server random)。
3)A确认数字证书的有效性,然后生成一个新的随机数(premaster secret),然后使用数字证书中的公钥,加密这个随机数,发给B。
4)B使用自己的私钥,获取A发来的随机数(即premaster secret)
5)A和B通过约定的加密方法,使用前面生成的三个随机数,生成对话密钥,用来加密接下来的通信内容。

总结:

  • CA机构颁发数字证书给鲍勃;
  • 爱丽丝和鲍勃进行SSL握手,爱丽丝通过数字证书确定鲍勃的身份;
  • 爱丽丝和鲍勃传递三个随机数,第三个随机数通过非对称加密算法进行传递;
  • 爱丽丝和鲍勃通过一个对称加密算法生成一个对话密钥,加密接下来的通信内容。

MySql:

1.数据库的三范式是什么?
第一范式(1NF):无重复的列,强调的是列的原子性。
第二范式(2NF):属性完全依赖于主键(确保表中的每列都和主键相关)。
第三范式(3NF):属性不依赖于其他非主属性(确保每列都和主键列直接相关,而不是间接相关)。

2.mysql 主键是什么?
主键(PRIMARY KEY),也称“主键约束”。
MySQL主键约束是一个列或者多个列的组合,其值能唯一地标识表中的每一行。这样的一列或多列称为表的主键,通过它可以强制表的实体完整性。
主键主要是用于其他表的外键关联,以及本记录的修改与删除。

mysql 主键的作用
1)主要的作用是确定该数据的唯一性。比如说ID=1,NAME=张三。我们要在数据库中,找到这条数据可以使用select * from 表 where id=1 这样就可以把张三查找出来了。而这个张三,也可以出现同名,所有用ID来做主键。
2)insert into 是插入操作。当ID设置为了主键,再插入一个相同的主键值,就为报错误,并不会更新,你想要个更新就必须执行UPDATE。

3.索引类型
1)FULLTEXT(全文索引)
目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。
2)HASH
由于HASH的唯一(几乎100%的唯一)及类似键值对的形式,很适合作为索引。
HASH索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。
3)BTREE
BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。
4)RTREE
RTREE在MySQL很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。
相对于BTREE,RTREE的优势在于范围查找。

4.索引种类

  • 普通索引: create index 索引名 on 表名 (字段)
  • 主键索引: 在设置表的主键时就会设置索引,无需显示的创建
  • 唯一索引: create unique index 索引名 on 表名 (字段)
  • 组合索引: create index 索引名 on 表名(字段A,字段B)

5.索引的优点与缺点
优点:
1.大大加快数据的检索速度;
2.加速表和表之间的链接;
3.在使用分组和排序子句进行数据检索时,可以减少查询中分组和排序的时间
缺点:
1.索引需要占物理空间
2.当对表中的数据进行增删和修改时,索引也需要动态维护,这样降低了数据的维护速度。

5.主键索引和普通索引的区别
1)主键索引不需要人为的创建,在创建表的时候就有了
2)主键索引不能删除,而普通索引可以
3)主键索引查询更快,而普通索引因为有回表查询,索引的性能没有主键索引性能高。

6.事务特性(ACID)
1)隔离性:并发事物执行时,隔离问题 — 事物在执行期间不能相互影响
2)原子性:要么全部成功,要么全部失败
3)持久性(永久性):事务再执行完成后,结果要一直保存下来
4)一致性:事务在执行前后,数据要保证是正确(比如转账前后金额总数要一致)

事务的隔离级别
1.串行化:可避免脏读、不可重复读、幻读的发生
2.可重复读:可避免脏读、不可重复读的发生
3.读已提交:可避免脏读的发生
4.读未提交:最低级别,任何情况都无法保证

7.并发事务存在的问题:
1)脏读:事务A读取到了事务B没提交的数据,然后事务B回滚了。
2)不可重复读:事务A使用相同的查询条件,读取到了不一样的结果,因为在这个过程中,事务B修改了数据
3)幻读:事务A将数据修改之后,事务B又添加了一条数据,导致事务A执行的结果和预期不一致

8.不可重复读和幻读的区别
不可重复读的侧重点在于修改,侧重于修改,数据原本是存在的;
幻读侧重点在于添加或删除,数据忽然出现或者消失了。

9.表操作
创建表:create tables tables_name(字段1,字段2,…);
删除表:drop table table_name;
查询所有表:show tables; (删除所有数据以及表结构)
修改表结构:alter table table_name add clumom 字段名 类型;
新增数据:
添加单条数据:insert into table_name(字段名…) values(…)
添加多行信息:insert into table_name(字段名…) values(…),(…)
修改数据:update 表名 set 字段名=值 where…
清空数据:delete; (清空表中数据,保留表结构)
全列查询:select * from 表名;
指定列查询:select 列明 from 表名;
表达式查询:select math+10 from 表名; 【禁止使用】
别名查询:select uname as username from 表名;
聚合查询:
聚合函数包括: count()、sum()、avg()、max()、min()
去重:distinct —— select distinct 列名 from 表名;
排序:order by 成绩 desc/asc; desc是倒叙;asc是升序
where查询:
  Null和’‘不是同一个意思
分页查询:limit
  limit 3,3 ——> 查询3条数据,跳过前3条,查询的是第4-6条数据
模糊匹配查询:like : select * from exam_result where name like ‘%三%’;—’%三’:代表以“三”结尾的,‘三%’:代表以“三”开头的。%代表通配符。

**primary key 主键约束:**它是NOT NULL和UNIQUE的结合。也就是说当一个字段被primary key修饰后,那么这个字段就是不能为空且是独一无二的!!
因为是独一无二的,所以,一般搭配:auto_increment

foreign key 外键约束:
外键用于关联其他表的主键或唯一键,语法:foreign key(字段名)references 主表(列)

group by

联合查询
inner join 内链接
以左边的表为准就是左外链接

什么是JDBC,JDBC数据库连接的步骤是什么?
jdbc就是Java数据库连接,是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法
jdbc连接数据库的步骤:
1)加载jdbc驱动程序
2)创建数据库的连接
3)创建preparedStatement
4)执行sql语句
5)遍历结果集
6)处理异常,关闭jdbc对象资源

数据库优化的几种方法
第一个方法:选取最适用的字段属性
mysql可以支持大数据量的存取,但是数据库中的表越小,在上面执行的查询就越快。所以可以将表中的字段宽度设置的尽可能小

第二个方法:使用连接来代替子查询
可以使用select语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。

第三个方法:使用联合(UNION)来代替手动创建的临时表
mysql可以把需要使用临时表的两条或者更多的select查询合并到一个查询中

第四个方法:事务

第五个方法:锁定表
由于在事务执行的过程中,数据库将会被锁定,因此其他的用户请求只能暂时等待直到该事务结束。有些情况下我们可以通过锁定表的放大来获得更好的性能。

第六个方法:使用外键

JVM :

1.JVM的类加载机制是什么?
答:JVM 的类加载机制是指 JVM 把描述类的数据从 .class 文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是 JVM 的类加载机制。

2.jvm的主要组成部分?及其作用

  • 堆(线程共享)
    new Object()所有的对象都存在此区域,此区域也是JVM中最大的一块区域; JVM垃圾回收就是针对此区域。
  • JVM栈(Java虚拟机栈)(线程私有)
    1)局部变量:8大基础数据类型,对象的引用;
    2)操作栈:每个方法都会对应一个操作栈;
    3)动态链接;指向常量池的方法引用;
    4)方法返回地址:存储的PC寄存器()相当于cpu上的一级缓存)的地址。
  • 本地方法栈(线程私有)
    它与JVM栈比较类似,只不过JVM栈是给Java和JVM使用,而本地方法栈是为本地方法(c,c++)服务。
  • 程序计数器(线程私有)
    用来记录线程执行的行号
  • 元空间(jdk1.8)(线程共享)
    jdk1.7叫做方法区—存放运行时常量池、字符串常量池,并且其是属于jvm的
    但是当jdk更新到1.8的元空间后,这部分已经属于本地内存了,并且将字符串常量池移动到堆里面。

3.jvm类加载机制的步骤
加载
1、根据类的路径全名加载二进制流;
2、将静态的存储结构转换成运行时的数据结构;
3、在内存中生成一个此类的方法入口
总结:将静态文件转换成运行内存
效验
1、文件格式效验
2、字节码效验。
准备
将类中的静态变量在内存中进行分配的过程
解析
初始化final修饰的常量
初始化
此步骤开始将执行权从jvm转移到自己写的程序,开始执行构造函数。

4.什么是jvm的双亲委派模型,优点和缺点是什么?
当加载一个类的时候,那么这个类不会直接加载,而是将这个加载任务直接交给父类,当找不到父类的时候,才尝试自己加载。
优点:
1)唯一性:父类只会加载一次
2)安全性:上层的类是系统提供的类,避免加载自定义的类,从而一定程度上保证了安全性
缺点:
破坏双亲委派模型(3次):
1、JDK1.2 提出的双亲委派模型,为了兼容老版本代码,因此在JDK1.2的时候就出现了破坏双亲委派模型的场景
2、因为双亲委派模型自身的缺点,比如在父类当中要调用子类的方法是没有办法实现的
3、人们对热更新的追求,导致了双亲委派模型的破坏

5.jvm怎么判断对象是否可以被回收?
1)引用计数器算法:
给每个对象创建一个计数器,当有程序应用次类的时候计数器+1,不使用的时候计数器-1,当计数器为0时,则表示此对象没人用,那么就可以将它判断为死亡对象,等待垃圾回收器的回收。
缺点:会导致循环引用的问题
2)可达性分析算法(HotSpot默认使用的算法):
找 看有没有 GC Roots
什么对象可以作为GC Roots:
1)虚拟机栈中的引用对象;
2)方法区中类静态属性引用的对象;
3)方法区中常量引用的对象;
4)本地方法栈中的引用对象。

6.说一下 jvm 有哪些垃圾回收算法?
1)标记清除算法

  • 使用可达性分析(存货的对象和死亡的对象)
  • 缺点:内存碎片
    2)复制算法
    将内存分为两部分,将S0存货的对象移到S1中,清零S0,下一次将S1中存活的对象放进S0中。
  • 优点:性能高 ; 缺点:内存的利用率低
    3)标记整理算法(老生代一般会使用此算法)
    不会产生内存碎片

7.说一下 jvm 有哪些垃圾回收器?
1) Serial 串行执行的垃圾回收器(单线程的)

  • 整个程序需要停下来去运行垃圾回收程序
  • 使用的是复制算法

2)Serical Old 老年代垃圾回收器

  • 使用的是标记整理算法

3)PerNew (并行垃圾回收器)它是 Serial 的多线程版本。

  • 有多条CG线程
  • 使用复制算法

4)Parallel Scavenge(并发垃圾回收器 新生代)

  • 可以和用户线程一同执行
  • 使用复制算法

5)Parallel Scavenge Old(并发垃圾回收器 老生代)

  • 可以和用户线程一同执行
  • 使用标价整理算法

6)CMS(Concurrent Mark Sweep) —— 垃圾整理算法
CMS 的 STW(stop the word)可以控制到非常短的时间
执行分为4步:
1、进行初始标记(过程非常短,会出现STW)
2、进行并发标记(标记过程与用户线程同时进行)
3、重新标记(虽然还需要STW,但是时间非常短,因为此时重新标记的内容是在进行并发标记的时候用户线程产生的垃圾)
4、并发清楚(和用户线程同时进行)

7)G1垃圾回收器
JDK 11 上是默认的垃圾回收器

8.JMM作用及3大特征:
解决不同的操作系统在去操作内存时的性能差异

1、原子性
2、可见性
3、有序性

2、3用volatile来保证的

Linux:

1.Linux的基本命令

1)ls命令
功能:对于目录,该命令列出该2目录下的所有子目录与文件。对于文件,将列出文件名以及其他信息。

  • -a 列出目录下的所有文件 包括以 . 开头的 含文件。
  • -d 将目录象文件一样显示 ,而不是显示其下的文件。 如 ls –d 指定目录
  • -k 以 k 字 的形式表示文件的大小。ls –alk 指定文件。
  • -l 列出文件的详细信息。
  • -r 对目录反向排序。
  • -t 以时间排序。
  • -R 列出所有子目录下的文件。(递归)

2)pwd命令
功能:显示用户当前所在的目录

3)cd命令
功能:改变工作目录。将当前工作目录改变到指定的目录下。
cd … :返回上级目录
cd ~  进入用户家目录
cd -  返回最近访问目录

4)touch指令
语法:touch [选项]…文件…
功能:touch命令参数可更改文档或目录的日期时间,包括存取时间和更改时间,或者新建一个不存在的文件。
举例:touch test.txt

5)mkdir指令
语法:mkdir [选项]dirname…
功能:在当前目录下创建一个名为“dirname”的目录

  • -p, --parents 可以是一个路径名称。此时若路径中的某些目录尚不存在,加上此选项后,系统将自动建立好那些尚不存在的目录,即一次可以建立多级目录。

举例:mkdir -p test/test1 : 递归建立多个目录

6)rm指令
语法:rm [-f-i-r-v] [dirName/dir]
功能:删除文件或目录

  • -f 即使文件属性为只读(即写保护) 亦直接删除
  • -i 删除前逐一询问确认
  • -r 删除目录及其下所有文件
    千万不要运行 rm -rf /

Spring:

1)请求转发和请求重定向的区别?
请求重定向:url层面,url地址发生了改变(变成了重定向的地址)。可以正常拿到页面的外部资源

请求转发:请求转发URL地址不变。有可能会导致外部资源访问不到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值