java面试复习

持续更新

doc文档:java-interview: 面试

目录

1.面试对象三大特征?

2.修饰符的区别?

3.重写与重载?

4.ArrayList和LinkedList的区别?

5.高并发集合中的问题?

6.JDK1.8的新特性?

7.java接口与抽象类的区别?

8.JVM相关问题?

9.hashcode与equals使用?

11.java代理有哪些?

12.java处理异常方式?

13.String、StringBuffer、StringBuild使用?

14.java异常种类?

15.Redis的持久化机制?

16.Redis的缓存回收机制?

17.Redis的缓存雪崩、缓存穿透,缓存击穿原因及处理?

18.数据库的隔离级别?

19.synchronized与lock的区别?

20.并发与并行的区别?

21.线程与进程的区别如何通信?

22.IOC与DI是什么?

23.Spring创建bean生命周期及线程安全?

24.nacos实现注册中心的原理?

25.voliate怎么禁止指令重排?

26.mysql的数据库引擎有哪些?

27.map及list怎么实现扩容?

28.WebScoket与HTTP区别?


1.面试对象三大特征?

答:封装、继承、多态。

封装:

将类内部的实现机制隐藏起来,对外界来说它的内部细节是看不到的,只提供特定的访问方法,这样能便于我们进行修改,保护数据的同时,提高代码的可维护性。

继承:

从已经有的类中派生出新的类,新的类可以继承已有类非私有的方法和属性,并且可以去拓展新的能力,比如新的方法属性,在Java中,通过extends关键字来实现继承。提高代码的可复用性。

多态:

同一个类型的对象,在不同的情况下所具有的不同形态。具体来说,多态是通过对父类的引用来调用子类中实现的方法,实现不同对象的同一操作,从而提高了代码的重用性和扩展性。多态的实现方式有两种:重写和重载。

2.修饰符的区别?

Default:仅在同一包内可见。

Private:只能在所定义的类中使用。

Protect:可以被定义在同一包内的所有类访问,或 者在其他包中定义的子类访问。

Public:可以被任何类和对象访问。

3.重写与重载?

重写:子类重写父类的方法,在程序运行过程中,选择合适的方法调用。

重载:方法名相同,方法的参数个数类型不同,针对不同的数据做统一处理。方法的修饰符和返回值类型可以不同,但不能作为区分的依据

提高代码的灵活性和可读性。

4.ArrayList和LinkedList的区别?

答:ArrayList:

基于动态数组实现的,它的元素在内存中是连续的,并且支持随机访问。当插入或删除元素时,需要对数组进行复制和移动,因此插入、删除操作的时间复杂度为O(n),但它的查询操作的时间复杂度为O(1)。

ArrayList适用于元素的读取操作比较频繁的场景,例如分页查询、统计数据等。同时,不适用于频繁的插入、删除操作。

LinkedList:

基于双向链表实现的,它每个元素都保存了前后两个元素的引用。当插入或删除元素时,只需要调整前后两个元素的引用即可,因此插入、删除操作的时间复杂度为O(1),但查询操作的时间复杂度为O(n)。

LinkedList适用于频繁的插入、删除操作,例如队列、栈等数据结构。不适用于读取操作比较频繁的场景。

5.高并发集合中的问题?

答:

线程安全:

Vector、Hashtable、Stack的性能相较于其他并发集合来说并不出色,主要原因是它们在每个方法上都使用了 synchronized 关键字进行同步,导致在多线程环境下存在性能瓶颈。但是相对于非线程安全的集合类,它们仍然具有重要的作用,可以保证多线程环境下的数据安全性。

ConcurrentHashMap、ConcurrentLinkedQueue、CopyOnWriteArrayList 等,这些集合类内部采用了更加高效的并发控制机制,具有更好的性能和更好的扩展性,可以满足更复杂的多线程并发需求。因此在开发中建议尽量采用这些并发集合类。

线程不安全:

多个线程同时访问一个集合容器时,可能会出现数据冲突或数据混乱的情况,如

ArrayList、HashSet、HashMap等

6.JDK1.8的新特性?

答:

Lambda表达式和函数式接口:JDK 1.8引入了Lambda表达式,使得编写函数式编程更加方便。同时,还引入了新的函数式接口,如Predicate、Function等,简化了代码编写。

Stream API:Stream API提供了一种更简洁、易于使用的方式来处理集合数据。它可以对集合进行各种操作,如过滤、映射、排序等,而无需编写循环和临时集合对象。

接口默认方法和静态方法:JDK 1.8允许在接口中定义默认方法和静态方法。默认方法可以为接口提供默认的实现,而静态方法则可以在接口中定义一些通用的实用方法。

方法引用:方法引用使得开发人员可以直接引用已经存在的方法,而不是通过lambda表达式来调用。这使得代码更具可读性和简洁性。

重复注解:JDK 1.8允许在同一地方多次使用相同的注解,简化了代码的编写。

Optional类:Optional类提供了一种优雅的方式来处理可能为空的对象,避免了空指针异常的问题。

Date/Time API:JDK 1.8引入了全新的日期和时间API,提供了更好的日期和时间处理功能。

7.java接口与抽象类的区别?

答:

定义:

接口是一种规范,只定义了需要实现的方法,没有实现逻辑;抽象类是一种半实现 半规范的类,可以包含具体方法的实现。

多继承:

接口支持多继承,可以实现多个接口;而类只能继承一个抽象类,但可以实现多个 接口。

实例化:

接口不能被实例化,只能被实现;抽象类可以被实例化,但不能直接实例化,需要 通过继承子类来实例化。

访问修饰符:

接口中的方法默认为公共的,不能定义为私有或受保护;抽象类中的方法可以 使用各种访问修饰符。

成员变量:

接口中只能定义常量,不能定义成员变量;抽象类可以定义成员变量。

默认实现:

接口中的方法没有默认实现,所有实现类都需要实现接口定义的方法;抽象类中 的方法可以有默认实现,子类可以选择性地进行重写。

8.JVM相关问题?

答:

(1):首先new在堆内存分配一块空间,初始化对象的成员变量,调用对象的构   造方法,返回对象的引用。

(2):如果在DCL中的共享变量需要跨多个线程并发访问,而且需要确保其可见   性和顺序性,那么就需要在共享变量上加上volatile关键字。这样可以确   保每个线程在访问共享变量时都能够获得最新的值,并且不会受到指令重排   序的影响。

(3):对象头保存标记信息,GC信息;实例数据保存对象的属性值;填充数据在   实例数据后填充空白;对齐空白:填充字节。一个是空白,一个是横线。

(4):标记号:是否可回收

  类型指针:确定对象类型

  锁信息:谁持有锁,锁状态

  哈希码:标识一个对象的唯一值

              其他信息:如数组长度

(5):直接定位:如对象名,属性值

  间接定位:通过对象之间的关联关系,如遍历

(6):静态分配:在编译时分配,static

  动态分配:运行时分配,通过new等关键字

(7):在Java中,一个空的Object对象通常占用16个字节的内存空间

9.hashcode与equals使用?

答:

Hashcode方法返回对象的哈希码,它是一个整数值,用于确定对象在哈希表中的存储位置。

Equals用于比较对象的内容是否一致,使用equals,必须重写hashcode,因为调用equals前,会执行hashcode,比较hash值是否相同,若相同,比较内容,即比较地址。

==与euqals:

语法不同:"=="是运算符,而"equals"是方法。

功能不同:"=="比较的是两个对象的引用是否相等,即比较对象的地址值;而"equals"默认比较的也是对象的引用,但可以在重写该方法时进行自定义的比较。

对于基本数据类型,"=="比较的是值是否相等;对于引用数据类型,"=="比较的是引用是否相等。

对于字符串类型,"=="比较的是两个字符串对象的引用是否相同,而"equals"比较的是字符串的内容是否相同。

"equals"通常用于自定义类中,比较两个对象的实际内容,以确定它们是否相等。可以重写equals方法来定义相等的概念,而"=="则不能被重写。

一般情况下,如果两个对象的引用相等(即"=="返回true),则它们的equals方法必定返回true;但equals方法返回true,并不一定意味着两个对象的引用相等

11.java代理有哪些?

答:

静态代理:在编译时就确定代理关系的代理模式,需要自定义接口和代理类。代理类实现了接口,并在方法中调用被代理对象的方法,可以增强被代理对象的功能。

动态代理:在运行时根据需要动态生成代理类的代理模式。Java提供了一个Proxy类和一个InvocationHandler接口,通过实现InvocationHandler接口来实现动态代理。使用动态代理可以简化静态代理中的代码量,并且可以代理任意类型的对象。

CGLIB代理:基于字节码的动态代理,通过继承被代理类来生成代理类。CGLIB底层使用ASM字节码技术,可以在运行时动态生成被代理类的子类,并重写父类的方法,实现代理功能。

JDK动态代理:基于接口的动态代理,使用Java原生的动态代理技术。通过实现InvocationHandler接口来实现代理逻辑,并使用Proxy类的静态方法newProxyInstance来生成代理对象。

12.java处理异常方式?

答:

抛出异常:throw e;写在方法内部,执行这个,一定会出异常。

捕获异常:try{}catch(Exception e){}finally{}捕获异常。

声明异常:throws,写在类或方法上,表明这个方法可能会出现异常,写在类上,表明这个类的所有方法都可能出异常,方法调用者需要捕获异常进行处理,或者继续声明异常。

13.String、StringBuffer、StringBuild使用

答:

String a=”a”;

在常量池中,查找是否有a这个字符串,有则指向这个地址,没有则在常量池创建   一个新的字符串a,并指向这个地址

String a=new String (“a”);

在内存中创建新的Stirng对象,内容为a,占用内存

StringBuffer与StringBulid都可对字符串进行操作,StringBuffer线程安全,在多线程   使用,单线程使用StringBuild,效率更高

14.java异常种类?

答:

在Java中,异常分为三种主要类型:

检查型异常(Checked Exceptions):编译器会强制要求开发人员处理的异常。开发人员必须在代码中使用try-catch块或者在方法签名中使用throws关键字声明异常,并处理或传递这些异常。常见的检查型异常包括IOException、SQLException等。

运行时异常(Runtime Exceptions):也称为非检查型异常,是指在运行时可能发生的错误,但不需要强制处理。这些异常一般由程序逻辑错误引起,如数组越界、空指针引用等。常见的运行时异常包括NullPointerException、ArrayIndexOutOfBoundsException等。

错误(Errors):系统级别的错误,通常由JVM直接抛出,并且无法捕获或处理。错误往往表示系统不可恢复的状态,如内存溢出、线程死锁等。常见的错误包括OutOfMemoryError、StackOverflowError等。

根据异常的继承关系,检查型异常和运行时异常都继承自Exception;而Error不是Exception的子类,而是直接继承自Throwable。

15.Redis的持久化机制?

答:

redis持久化机制:

RDB:

通过在redis.conf配置,如:save 900 1

RDB持久化是通过将Redis的内存数据快照保存到磁盘上的二进制文件中 实现的。在执行RDB快照操作时,Redis会将当前内存中的数据以快照的形式 保存到磁盘上,该过程是异步进行的。也就是说,在执行RDB保存快照操作 时,Redis服务器可以继续处理来自客户端的读写请求,不会阻塞客户端。

AOF:

即在你执行写操作时,将命令写入AOF文件中,可能是写一次保存 一次,一秒一次,可通过配置实现通常与RDB异步保存一同使用,保证 数据的安全性和稳定性。

16.Redis的缓存回收机制?

答:

定时回收:Redis可以设置一个定时器,定期扫描内存中的key,检查其是否过期,过期的key会被自动删除。通过在key的设置过期时间(TTL),Redis可以自动进行定时回收。

惰性回收:惰性回收是在获取某个key时,判断其是否过期,如果过期则删除。这样可以避免全局扫描内存,节省了时间和资源。但是这种方式在读取过期key时会对性能产生一定的影响。

此外,Redis还可以通过设置最大内存限制来控制缓存的大小,在内存超过限制时会使用一些内存淘汰策略来删除一些旧的key,以释放内存空间。常见的内存淘汰策略有:LRU(最近最少使用)、LFU(最少使用)、Random(随机删除)等。

17.Redis的缓存雪崩、缓存穿透,缓存击穿原因及处理?

答:

缓存穿透:即在缓存中查询一个不存在的键,在流量大的情况下,因为不存在这个 键,会频繁的去存储层查,加载到缓存中,导致服务挂掉。

解决办法:使用过滤器去筛选,将可能出现的键存到一个的的bitmap,不在 这 个map的键就不会去查

缓存击穿:针对一些设置了过期时间的热点数据,在一段时间内有大量的请求过来, 当这个热点数据过期的时候,缓存会把这个键删除,于是大量的并发请求没有在缓 存中查找到这个键,就会去存储层查询这个键,加载到缓存上,这就会导致后端 的压力突然过大。

解决办法:使用互斥锁或分布式锁保证同一时间只有一个请求访问

缓存雪崩:大量的缓存数据的过期时间一样,导致缓存中的大部分数据过期被删 除,没有在缓存中查找到这个键,就会去存储层查询这个键,导致压力过大

解决办法:针对这些热点数据,将他们的过期时间错开,减少后端的压力

缓存雪崩是缓存中大量数据同时失效或过期,导致所有请求直接访问数据库或后端 服务;缓存击穿是热点数据缓存失效时,大量并发请求同时访问数据库,增加了数 据库的负载。

18.数据库的隔离级别?

答:

读未提交(Read Uncommitted):事务可以读取并读取其他事务尚未提交的数据,可能导致脏读、不可重复读和幻读的问题。

读已提交(Read Committed):事务只能读取已经提交的数据,解决了脏读的问题。但仍可能出现不可重复读和幻读的问题。

可重复读(Repeatable Read):事务在执行过程中多次读取同一个数据,在事务结束之前对该数据的读取结果保持一致,避免了不可重复读的问题。但仍可能出现幻读的问题。

串行化(Serializable):事务串行执行,互相之间不会产生并发冲突,可以避免脏读、不可重复读和幻读的问题。但会导致并发性能下降。

19.synchronized与lock的区别?

答:

实现方式:

synchronized是Java中的关键字,

lock是一个接口,在使用时需要显式地创建一个锁对象来进行加锁和解锁操作。常 用的锁类有ReentrantLock和ReentrantReadWriteLock。

粒度:

synchronized关键字可以在方法或代码块级别使用,只能对整个方法或代码块进行 加锁操作,无法分开对不同的数据进行加锁。

lock接口提供了更细粒度的锁操作,可以对不同的资源进行独立的加锁和解锁操作, 实现更灵活的线程同步控制。

公平性:

synchronized关键字对线程获取锁的顺序没有特别的保证,可能会导致某些线程一 直获取不到锁,也称为非公平锁。

lock接口的实现类可以提供公平锁和非公平锁两种机制,可以根据实际需求选择合 适的锁类型。

中断响应:

synchronized关键字的加锁操作是不可中断的,如果某个线程获取不到锁,将会一 直等待。

lock接口的加锁操作可以响应中断,可以通过线程的interrupt()方法中断正在等待 锁的线程。

条件变量:

lock接口提供了Condition对象,可以通过Condition对象实现更灵活的线程等待和 唤醒机制。

synchronized关键字的等待和唤醒操作是由Java虚拟机自动管理的,不支持自定义 条件变量。

20.并发与并行的区别?

答:

并发指的是系统具有同时处理多个任务的能力。在并发中,任务之间可以交替执行,通过时间片轮转等机制来实现任务的切换。并发可以提高系统的吞吐量和资源利用率,但是由于任务之间的切换,可能会增加系统的开销和复杂性。

并行则是指系统同时执行多个任务,每个任务在独立的处理单元上进行处理。在并行中,多个处理单元可以同时执行不同的任务,相对于并发来说,更加高效。并行可以通过多核处理器、分布式处理等方式来实现。

简而言之,可以把并发看作是同时处理多个任务的能力,而并行则是真正同时执行多个任务的能力。并发强调任务之间的交替执行,而并行强调独立处理单元上的任务同时执行。

21.线程与进程的区别如何通信?

答:

调度方式:进程是操作系统进行资源分配和调度的基本单位,线程是进程内的执行单元,由进程调度和管理。

系统资源:进程拥有独立的系统资源,如内存空间、文件句柄等,线程与所属进程共享这些系统资源。

内存使用:每个进程拥有独立的内存地址空间,而线程与所属进程共享同一内存地址空间,可以直接访问同一进程的内存。

通信方式:进程之间通信需要使用操作系统提供的IPC(进程间通信)机制,如管道、信号量、消息队列等,而线程之间可以直接通过共享内存、全局变量等方式进行通信。

创建和销毁开销:创建进程的开销较大,需要分配独立的内存空间和系统资源,而创建线程的开销较小,只需要为其分配堆栈空间和相关信息即可。

安全性:进程之间相互独立,互不影响,一个进程出错不会影响到其他进程,而线程在同一进程内共享相同的资源,一个线程的错误可能会影响到其他线程。

执行能力:由于进程拥有独立的内存空间,进程之间的切换开销较大;而线程与所属进程共享内存,线程之间的切换开销较小,执行效率高。

总结来说,进程是资源分配和调度的基本单位,拥有独立的内存和系统资源,而线程是进程内的执行单元,共享同一进程的资源,可共享内存和数据等。

22.IOC与DI是什么?

答:

IOC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)是两个相关的概念,都是用于解决软件开发中的耦合问题。

IOC(Inversion of Control)是一种设计原则,它通过将对象的创建和管理的控制权由应用程序转移到容器中,实现对对象之间关系的解耦。传统的程序开发中,对象之间的关系由程序员手动管理和创建,而使用IOC容器后,程序员只需要通过配置对应的关系,由容器负责创建和管理对象。这样做的好处是在整个应用程序中降低了各个模块之间的耦合性,提高了代码的可维护性和可测试性。

DI(Dependency Injection)是IOC的一种具体实现方式。它通过将对象所依赖的其他对象的引用通过构造函数、方法参数或属性的方式,注入到对象中进行使用。也就是说,对象不再负责自己依赖关系的创建和管理,而是通过外部注入的方式来获取依赖的对象。 通过依赖注入,对象之间的关系由容器来管理,对象不需要关心依赖关系的具体实现,这样可以降低对象之间的耦合性,提高代码的可维护性、可测试性和可扩展性。

综上所述,IOC和DI都是用于解决对象之间的耦合关系的问题,通过将对象的创建和依赖关系的管理交给容器来负责,降低了对象之间的耦合性,提高了代码的可维护性和可测试性。

23.Spring创建bean生命周期及线程安全?

答:

实例化阶段:在该阶段,Spring通过调用默认构造函数或工厂方法来创建bean的实例。

属性赋值阶段:在该阶段,Spring通过setter方法或直接赋值来为bean的属性注入值。

初始化阶段:在该阶段,Spring调用bean的初始化方法,可以自定义一个方法,并且通过在bean的配置中指定init-method来调用该方法。

使用阶段:在该阶段,bean可以被应用程序使用,执行特定的业务逻辑。

销毁阶段:在该阶段,Spring调用bean的销毁方法,可以自定义一个方法,并且通过在bean的配置中指定destroy-method来调用该方法。

24.nacos实现注册中心的原理?

答:Nacos 实现注册中心的原理主要包括以下几个方面:

1. 服务注册:当一个服务实例启动时,它会向 Nacos 注册中心发送注册请求,将自己的元数据信息(比如 IP 地址、端口号、健康状态等)注册到 Nacos 服务器上。

2. 服务发现:客户端或消费者通过向 Nacos 注册中心发送服务发现请求,获取正在运行的服务实例列表。Nacos 会返回注册在其上的服务实例信息,包括 IP 地址、端口号等。客户端可以通过选择其中的一个服务实例与之通信。

3. 服务健康监测:Nacos 支持对注册的服务实例进行健康检查。当一个服务实例发生故障时,Nacos 会检测到其健康状态的改变,并从服务实例列表中移除该实例,避免将请求转发给不可用的服务实例。

4. 高可用:Nacos 支持集群模式,可以通过部署多个 Nacos 服务器来提高系统的可用性和容错性。当一个 Nacos 服务器发生故障时,其他服务器可以继续提供服务并保持数据一致性。

5. 数据同步:Nacos 使用集中式存储来存储注册信息,并通过数据同步来保持多个 Nacos 服务器之间的数据一致性。当一个 Nacos 服务器上的注册信息发生变化时,它会将这些变化通过数据同步机制广播到其他服务器上,以保持数据的一致性。

总之,Nacos 通过提供注册和发现服务的功能,实现了微服务架构中统一的服务注册与发现机制。它通过存储注册信息并提供查询服务,使得服务提供者和服务消费者可以更方便地找到对应的服务实例,并能够实时获取服务实例的健康状态。同时,Nacos 还支持集群部署和数据同步,以保证系统的高可用性和数据的一致性。

25.voliate怎么禁止指令重排?

答:

volatile关键字的实现原理是通过使用内存屏障(Memory Barrier)来实现的。内存屏障是一种硬件指令,用于强制处理器按照指定的顺序执行读写操作,并清空处理器的指令流水线。

26.mysql的数据库引擎有哪些?

答:

MySQL数据库的引擎有多种选择,每种引擎都有自己的特点和适用场景。以下是一些常见的MySQL引擎:

1. InnoDB:默认的MySQL引擎,提供了ACID事务支持,支持行级锁定和外键约束,适用于大多数企业级应用。

2. MyISAM:较早的MySQL引擎,不支持事务和行级锁定,但具有较快的插入和查询速度,适用于读密集型应用和非事务性的应用。

3. Memory (Heap):将表数据存储在内存中,速度非常快,但对于临时数据和缓存的适用性较高,数据在重新启动时会丢失。

4. Archive:适用于需要快速插入和检索大量历史和归档数据的应用。它使用压缩技术来优化存储空间使用。

5. NDB Cluster:也称为MySQL Cluster,是一个分布式数据库引擎,具有高可用性和容错性,适用于大规模的实时应用。

6. CSV:将数据以纯文本形式存储在CSV文件中,适用于数据导入导出或临时存储。

以上只是MySQL中一些常见的引擎,每个引擎都有其自身独特的优点和适用场景。在选择引擎时,需要根据应用的特点、需求和性能要求进行评估和决策。

27.map及list怎么实现扩容?

答:

1. 当HashMap中的元素数量超过负载因子(默认为0.75)乘以当前容量时,触发扩容操作。

2. 创建一个新的数组,容量是原数组的两倍。

3. 遍历原数组中的每个元素,重新计算其在新数组中的位置。

4. 将原数组中的元素重新分配到新数组中的对应位置。

5. 扩容完成后,HashMap的容量变为新数组的长度。

需要注意的是,HashMap的扩容操作可能会导致性能下降,因为要重新分配元素并重新计算哈希值。因此,在设计HashMap时,应该合理选择初始容量和负载因子,以尽量减少扩容的次数和影响性能的情况发生。

1. 当ArrayList中的元素数量超过当前容量时,触发扩容操作。

2. 创建一个新的数组,容量是原数组的1.5倍(可以通过`ensureCapacity`方法手动指定扩容的大小)。

3. 将原数组中的元素复制到新数组中。

4. 扩容完成后,ArrayList的容量变为新数组的长度。

在复制元素的过程中,会将原数组中的元素按照顺序复制到新数组对应的位置上。如果ArrayList中有null元素,则也会复制到新数组中。

需要注意的是,ArrayList的扩容操作会涉及到数组的拷贝,因此在频繁进行大量元素插入或删除操作时可能会影响性能。为了减少扩容操作的次数,我们可以在创建ArrayList时就设置一个合适的初始容量,以便尽量减少扩容操作的发生。

28.WebScoket与HTTP区别?

答:

1. 连接方式:

   - HTTP是一个无状态的、请求-响应式的协议。客户端向服务器发送请求,服务器返回响应后,连接立即关闭。这种方式在每个请求周期中需要建立和断开连接,无法支持持久连接。

   - WebSocket是一个全双工的、长连接的协议。它使用单个TCP连接,通过在同一个连接上进行双向通信来实现实时性。一旦建立WebSocket连接,客户端和服务器之间可以持久地发送消息。

2. 通信方式:

   - HTTP是基于请求-响应模型的。客户端发送请求,服务器返回响应。它是一个单向通信模型,只能由客户端主动发起请求。

   - WebSocket支持双向通信。在建立连接后,服务器可以主动发送消息给客户端,而不需要客户端发起请求。这使得实时推送和服务端推送变得更加容易。

3. 数据格式:

   - HTTP传输的数据通常是基于文本的,比如HTML、XML、JSON等。HTTP有一个明确的数据帧结构,由请求行、头部和主体组成。

   - WebSocket可以传输文本和二进制数据。它没有明确的数据帧结构,可以直接传输原始数据。

4. 信道建立:

   - HTTP是一种无状态协议,每次请求都需要携带会话标识(如Cookie),服务器需要验证身份和状态。

   - WebSocket建立连接时,需要通过一个类似HTTP握手的过程进行协议升级。一旦连接建立,后续通信不需要通过验证。

综上所述,WebSocket与HTTP有着不同的连接方式、通信方式、数据格式和信道建立过程。WebSocket具有实时性和双向通信的特点,适用于实时应用程序,而HTTP则适用于传统的请求-响应模型。

29.解释 RESTful API,以及如何使用它构建 web 应用程序。

RESTful API是一种基于HTTP协议的API设计风格,它使用HTTP方法(GET、POST、PUT、DELETE等)对资源进行操作,以及使用URI(Uniform Resource Identifier)标识资源。该API设计风格具有以下特点:

1. 无状态性:每个请求都是一个独立的请求,不需要保存上一次请求的信息。

2. 独立性:客户端和服务器之间的交互是独立的,客户端应该不需要了解服务器中的数据结构。

3. 缓存性:相同的请求应该返回相同的结果,可以用缓存来提高性能。

4. 客户端-服务器的架构:客户端和服务器之间的交互应该是分离的,这样可以使得每个部分更容易独立地进行扩展和修改。

使用RESTful API构建web应用程序的步骤如下:

1. 定义资源:确定需要操作的资源,如用户、文章等。

2. 设计URI:为每个资源定义URI,一般使用名词来表示资源。

3. 定义HTTP方法:确定需要使用的HTTP方法来执行操作,如GET用来获取资源,POST用来创建新资源等。

4. 设计数据格式:确定数据的格式,通常使用JSON或XML格式。

5. 实现服务端:开发服务器端程序,提供RESTful API接口。

6. 实现客户端:开发客户端程序,使用RESTful API来与服务器端通信,并处理响应结果。

总之,使用RESTful API可以使得web应用程序更加灵活、可扩展和可维护,同时也提高了应用程序的性能和安全性。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要准备Java后端面试,你可以按照以下路线进行复习: 1. 熟悉Java基础知识,包括面向对象编程的概念、Java语法、集合框架等。这是面试的基础,需要掌握Java的核心概念和常用语法。 2. 深入理解Java的多线程和并发编程。这是Java后端开发中常见的需求,需要了解线程的生命周期、线程间的通信方式、锁机制等。同时,掌握并发编程中的常见问题和解决方案,比如如何避免死锁、线程安全等。 3. 学习常见的Java框架和技术,如Spring、Spring Boot、MyBatis等。这些框架在后端开发中非常常见,需要了解它们的原理、用法和常见的应用场景。 4. 掌握数据库相关的知识,包括SQL语法、数据库设计和优化等。在面试中,你可能会被问到如何编写高效的SQL查询语句,如何设计关系型数据库的表结构等。 5. 熟悉常用的网络协议和Web开发技术,如HTTP、TCP/IP、RESTful API等。这些知识对于后端开发至关重要,需要了解它们的基本原理和使用方法。 6. 学习常见的系统设计和架构模式,如分布式系统、微服务架构等。在面试中,你可能需要设计一个可扩展、高可用性的系统,并对其进行优化和调优。 除了上述的通用性复习路线,你还可以根据自己所面试岗位的具体要求来进行有针对性的复习。查看面试岗位的JD,了解公司对于Java后端开发的需求和要求,然后重点复习相关的知识和技能。 尽管求职环境有些困难,但是只要你做好充分的准备,提前了解岗位要求并有针对性地复习,相信你能够应对好Java后端面试的挑战。加油!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Java后端面试该复习什么?只需一张图](https://blog.csdn.net/weixin_70730532/article/details/126725468)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Java后端面试该复习什么?只需一张图|原创](https://blog.csdn.net/sinat_32873711/article/details/126535341)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值