最新Java面试

1.==和equals有什么区别?

==可以比较基本数据类型和引用数据类型,两端如果是基本数据类型就是判断值是否相同,两端是引用数据类型就是比较内存地址是否相同。

equals()比较引用数据类型,equals在重写之后,判断两个对象的属性值是否相同,如果不重写,其实就是==

2.说一下integer的缓存?

Java的Integer类内部实现了一个静态缓存池,用于存储特定范围内的整数值对应的Integer对象。默认情况下,这个范围是-128-127.当通过Integer.valueOf(int)方法创建一个这个范围内的整数对象时,并不会每次都生成新的对象实例,而是复用缓存中的现有对象,会直接从内存中取出,不需要创建一个新的对象。

3.数组和集合的区别,用过哪些?

①数组是固定长度的数据结构,一旦创建长度就无法改变;而集合是动态长度的数据结构,可以根据需要动态增加或减少元素。

②数组可以包含基本数据类型和对象,而集合只能包含对象。

③数组可以直接访问元素,而集合需要通过迭代器和或其它方法访问元素。

4.接口和抽象类有什么区别?

当注重代码的扩展性和可维护性时,应当优先采用接口:

①接口与实现它的类之间不存在任何层次关系,接口可以实现毫不相关的类的相同行为,比抽象类更加的灵活方便。

②接口只关心对象之间的交互方法,而不关心对象所对应的具体类。接口是程序之间的一个协议,比抽象类更加安全。

使用抽象类:

 ①当2个或多个类中有重复部分的时候,我们可以抽象出来一个基类,如果希望这个基类不能被实例化,就可以把这个基类设计成抽象类。

 ②当需要为一些类提供公共的实现代码时,应优先考虑抽象类 。因为抽象类中的非抽象方法可以被子类继承下来,使实现功能的代码更简单。

 ③抽象类只能是单继承的,不能多继承。

 总结:使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。
抽象类适合用来定义某个领域的固有属性,也就是本质,接口适合用来定义某个领域的扩展功能。                      

4.String StringBuilder StringBuffer有什么区别,这几者之间,什么场景下使用哪个,支持并发吗?

String是不可变的(String类中有一个byte[]数组,这个byte[]数组采用了final修饰,因为数组一旦创建长度不可变。并且被final修饰的引用一旦指向某个对象之后,不可再指向其它对象,所以String是不可变的。),StringBuilder/StringBuffer是可变的(StringBuilder/StringBuffer内部实际上是一个byte[]数组,这个byte[]数组没有被final修饰,StringBuilder/StringBuffer的初始化容量我记得应该是16,当存满之后会进行扩容。底层调用了数组拷贝的方法System.arraycopy()…是这样扩容的。所以StringBuilder/StringBuffer适合于使用字符串的频繁拼接操作。)StringBuffer 是线程安全的,支持并发操作,但是效率低。StringBuild 是非线程安全的,不支持并发操作,但是效率高。StringBuffer类是可以通过Append()来修改值。

5.你用过哪些map集合,HashMap和ConcurrentHashMap两者有什么区别?

  • 底层数据结构:

    • jdk7之前的ConcurrentHashMap底层采用的是分段的数组+链表实现,jdk8之后采用的是数组+链表/红黑树;

    • HashTable采用的是数组+链表,数组是主体,链表是解决hash冲突存在的。

  • 实现线程安全的方式:

    • jdk8以前,ConcurrentHashMap采用分段锁,对整个数组进行了分段分割,每一把锁只锁容器里的一部分数据,多线程访问不同数据段里的数据,就不会存在锁竞争,提高了并发访问;jdk8以后,直接采用数组+链表/红黑树,并发控制使用CAS和synchronized操作,更加提高了速度。

    • HashTable:所有的方法都加了锁来保证线程安全,但是效率非常的低下,当一个线程访问同步方法,另一个线程也访问的时候,就会陷入阻塞或者轮询的状态。

6.ArrayList和LinkedList的区别?

  • 底层数据结构:ArrayList使用数组作为底层数据结构,而LinkedList使用双向链表作为底层数据结构

  • 随机访问性能:ArrayList支持通过索引直接访问元素,因为底层数组的连续存储特性,所以时间复杂度为O(1)。而LinkedList需要从头或尾部开始遍历链表,时间复杂度为O(n)。

  • 插入和删除操作:ArrayList在尾部插入和删除元素的时间复杂度为O(1),因为它只需要调整数组的长度即可。但在中间或头部插入和删除元素时,需要将后续元素进行移动,时间复杂度为O(n)。而LinkedList在任意位置插入和删除元素的时间复杂度为O(1),因为只需要调整节点的指针即可。

  • 内存占用:ArrayList在每个元素中都存储了实际的数据,而LinkedList在每个节点中存储了数据和前后节点的指针。因此,相同数量的元素情况下,LinkedList通常比ArrayList占用更多的内存空间。

7.线程和进程的区别?

  • 进程是操作系统中进行资源分配和调度的基本单位,它拥有自己的独立内存空间和系统资源。每个进程都有独立的堆和栈,不与其他进程共享。进程间通信需要通过特定的机制,如管道、消息队列、信号量等。由于进程拥有独立的内存空间,因此其稳定性和安全性相对较高,但同时上下文切换的开销也较大,因为需要保存和恢复整个进程的状态。

  • 线程是进程内的一个执行单元,也是CPU调度和分派的基本单位。与进程不同,线程共享进程的内存空间,包括堆和全局变量。线程之间通信更加高效,因为它们可以直接读写共享内存。线程的上下文切换开销较小,因为只需要保存和恢复线程的上下文,而不是整个进程的状态。然而,由于多个线程共享内存空间,因此存在数据竞争和线程安全的问题,需要通过同步和互斥机制来解决。

8.多线程中的sleep和wait有什么区别?

sleep是线程被调用时,占着cpu休眠,其他线程不能占用cpu,os认为该线程正在工作,不会让出系统资源,wait是进入等待池等待,让出系统资源,其他线程可以占用cpu。

sleep()和wait()方法的区别可从两个角度阐述:
1.cpu的抢占权;2.锁旗标是否释放
两者都会释放cpu的抢占权;
wait()方法执行完即可释放锁旗标,进入线程的等待队列;
sleep()执行完,不会释放,进入等待队列;

9.run方法和start方法有什么区别?

①二者方法种类不同:

run()方法是Thread类中的一个普通方法,它是线程中实际执行的代码,线程的代码逻辑就是在run()方法中实现的;

start()方法是Thread类中的一个启动方法,它会启动一个新的线程,并在新的线程中调用方法。

②二者的执行方式不同:

直接调用run()方法,会像普通方法一样,在当前线程中顺序执行run()方法的内容,这并不会启动一个新的线程;

调用start()方法会创建一个新的线程,并在新的线程中执行run()方法的内容。

③线程状态不同。

当我们调用start()方法启动一个新线程时,该线程会进入就绪状态,等待JVM调度它和其他线程的执行顺序;

当我们直接调度run()方法时,则会在当前线程中执行,不会产生新的线程。

所以在多线程编程中,我们在使用start()启动线程,而不是调用run方法。

10.什么叫做反射?

Java反射指的是在Java程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法;对于给定的一个对象,都能够调用它的任意一个属性和方法。这种动态获取类的内容以及动态调用对象的方法称为反射机制。反射的核心是在运行期才动态加载类或调用方法访问属性。

反射常见的应用场景这里介绍3个:

Spring 实例化对象:当程序启动时,Spring 会读取配置文件applicationContext.xml并解析出里面所有的标签实例化到IOC容器中。

反射 + 工厂模式:通过反射消除工厂中的多个分支,如果需要生产新的类,无需关注工厂类,工厂类可以应对各种新增的类,反射可以使得程序更加健壮。

JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动。

优点

  • 增加程序的灵活性:面对需求变更时,可以灵活地实例化不同对象。

缺点

  • 破坏类的封装性:可以强制访问 private 修饰的信息;
  • 性能损耗:反射相比直接实例化对象、调用方法、访问变量,中间需要非常多的检查步骤和解析步骤,JVM无法对它们优化。

11.什么叫做序列化?

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

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

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

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

12.spring、springboot的核心注解有哪些?

spring核心注解:

@Required
此注解用于bean的setter方法上。表示此属性是必须的,必须在配置阶段注入,否则会抛出BeanInitializationExcepion。

@Autowired
此注解用于bean的field、setter方法以及构造方法上,显式地声明依赖。根据type来autowiring。

当在field上使用此注解,并且使用属性来传递值时,Spring会自动把值赋给此field。也可以将此注解用于私有属性(不推荐),如下。

最经常的用法是将此注解用于settter上,这样可以在setter方法中添加自定义代码。如下:

当在构造方法上使用此注解的时候,需要注意的一点就是一个类中只允许有一个构造方法使用此注解。此外,在Spring4.3后,如果一个类仅仅只有一个构造方法,那么即使不使用此注解,那么Spring也会自动注入相关的bean。如下:

@Qualifier
此注解是和@Autowired一起使用的。使用此注解可以让你对注入的过程有更多的控制。

@Qualifier可以被用在单个构造器或者方法的参数上。当上下文有几个相同类型的bean, 使用@Autowired则无法区分要绑定的bean,此时可以使用@Qualifier来指定名称。

@Configuration
此注解用在class上来定义bean。其作用和xml配置文件相同,表示此bean是一个Spring配置。此外,此类可以使用@Bean注解来初始化定义bean。

@ComponentScan
此注解一般和@Configuration注解一起使用,指定Spring扫描注解的package。如果没有指定包,那么默认会扫描此配置类所在的package。

@Lazy
此注解使用在Spring的组件类上。默认的,Spring中Bean的依赖一开始就被创建和配置。如果想要延迟初始化一个bean,那么可以在此类上使用Lazy注解,表示此bean只有在第一次被使用的时候才会被创建和初始化。此注解也可以使用在被@Configuration注解的类上,表示其中所有被@Bean注解的方法都会延迟初始化。

@Value
此注解使用在字段、构造器参数和方法参数上。@Value可以指定属性取值的表达式,支持通过#{}使用SpringEL来取值,也支持使用${}来将属性来源中(Properties文件、本地环境变量、系统属性等)的值注入到bean的属性中。此注解值的注入发生在AutowiredAnnotationBeanPostProcessor类中。

Spring Boot 的核心注解是 @SpringBootApplication。这个注解用于声明一个 Spring Boot 应用,它包含了启动应用所需要的所有配置和组件。

@SpringBootApplication 主要有以下几个注解组成:

@Configuration:这个注解用于声明一个配置类,Spring Boot 会自动将此类识别为 Spring 配置类。
@EnableAutoConfiguration:这个注解用于启用 Spring Boot 的自动配置功能。这是启动应用的一个基本要求,因为 Spring Boot 的核心思想就是通过自动配置来简化应用的搭建过程。
@ComponentScan:这个注解用于告诉 Spring Boot 扫描哪些包中的组件。如果没有这个注解,Spring Boot 会默认扫描当前包以及其子包中的组件。
此外,Spring Boot 还提供了许多其他的注解,如 @Service、@Repository、@Controller、@RestController 等,用于标记 Spring 组件,如服务、数据访问对象(DAO)、控制器等。这些注解可以帮助 Spring Boot 更好地组织代码,提高代码的可读性和可维护性。

总的来说,@SpringBootApplication 注解是 Spring Boot 的核心,它包含了启动应用所需要的所有配置和组件,并启用了 Spring Boot 的自动配置功能。通过使用这些注解,可以简化应用的搭建过程,提高代码的可读性和可维护性。

13.有没有做过自定义注解?什么情况下可以用到自定义注解,举例说明?

需要使用@interface修饰,加上三个元注解

  • @Documented:生成API文档使用
  • @Target:决定此注解能加的范围,类、方法、属性上面
  • @Retention:作用域(在什么时候有作用,java–》class–》运行时
@Documented
@Target(ElementType.METHOD)//决定此注解能加的范围,类,方法,属性
@Retention(RetentionPolicy.RUNTIME)//作用域(在什么时候有作用,java--》class--》运行时)
public @interface SysLog {
    String name() default "";
}

 自定义注解使用场景:

① 自定义注解使用AOP做权限校验


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface Authority {

    String authority() default "";
}

②编写切面

 定义切面并编写权限放行的逻辑

 14.#和$的区别?

$和#都可以充当占位符,$符号的底层是由Statement实现的,#底层是由PreparedStatement实现的

#是先编译sql语句,然后在传值,给传入的值都加上双引号 , $是直接拼接字符串,不会给传入的值加上双引号

15.用过哪些微服务组件?

注册中心
Netflix Eureka
Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。

SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。

Zookeeper
Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。

Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。

负载均衡
Netflix ribbon
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。

Loadbalancer
Spring Cloud不仅提供了使用Ribbon进行客户端负载均衡,还提供了Spring Cloud LoadBalancer。相比较于Ribbon,Spring Cloud LoadBalancer不仅能够支持RestTemplate,还支持WebClient。WeClient是Spring Web Flux中提供的功能,可以实现响应式异步请求。

一方面Netflix Ribbon停止更新,Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器,抽象和实现,用来替代Ribbon。

服务调用
Netflix feign
Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。

而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix,可以让我们不再需要显式地使用这两个组件。

Openfeign
OpenFeign是springcloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。另外整合了Ribbon和Eureka,从而使得Feign的使用更加便捷。

熔断降级
Netflix hystrix
hystrix是Netlifx开源的一款容错框架,防雪崩利器,具备服务降级,服务熔断,依赖隔离,监控(Hystrix Dashboard)等功能。

服务网关
Nginx
Nginx是一个高性能的HTTP和反向代理服务器。Nginx一方面可以做反向代理,另外一方面可以做静态资源服务器,接口使用Lua动态语言可以完成灵活的定制功能。

Netflix Zuul/Zuul2
Zuul 是 Netflix 开源的一个API网关组件,它可以和 Eureka、Ribbon、Hystrix 等组件配合使用。社区活跃,融合于 SpringCloud 完整生态,是构建微服务体系前置网关服务的最佳选型之一。

Zuul1 是基于 Servlet 框架构建,采用的是阻塞和多线程方式,即一个线程处理一次连接请求,这种方式在内部延迟严重、设备故障较多情况下会引起存活的连接增多和线程增加的情况发生。

Zuul 的核心是一系列的过滤器,这些过滤器可以完成以下功能:

(1)统一鉴权 + 动态路由 + 负载均衡 + 压力测试

(2)审查与监控:与边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。

(3)多区域弹性:跨越 AWS Region 进行请求路由,旨在实现 ELB(Elastic Load Balancing,弹性负载均衡)使用的多样化,以及让系统的边缘更贴近系统的使用者。

Netflix 发布的 Zuul2 有重大的更新,它运行在异步和无阻塞框架上,每个 CPU 核一个线程,处理所有的请求和响应,请求和响应的生命周期是通过事件和回调来处理的,这种方式减少了线程数量,因此开销较小。

OpenResty
OpenResty是一个流量网关,根据前面对流量网关的介绍就可以知道流量网关的职责。

OpenResty基于 Nginx与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

通过揉和众多设计良好的 Nginx 模块,OpenResty 有效地把 Nginx 服务器转变为一个强大的 Web 应用服务器,基于它开发人员可以使用 Lua 编程语言对 Nginx 核心以及现有的各种 Nginx C 模块进行脚本编程,构建出可以处理一万以上并发请求的极端高性能的 Web 应用。

Gateway
Spring Cloud Gateway 是Spring Cloud的一个全新的API网关项目,目的是为了替换掉Zuul1,它基于Spring5.0 + SpringBoot2.0 + WebFlux(基于⾼性能的Reactor模式响应式通信框架Netty,异步⾮阻塞模型)等技术开发,性能⾼于Zuul,官⽅测试,Spring Cloud GateWay是Zuul的1.6倍,旨在为微服务架构提供⼀种简单有效的统⼀的API路由管理⽅式。

Spring Cloud Gateway可以与Spring Cloud Discovery Client(如Eureka)、Ribbon、Hystrix等组件配合使用,实现路由转发、负载均衡、熔断、鉴权、路径重写、⽇志监控等,并且Gateway还内置了限流过滤器,实现了限流的功能。

配置中心
Spring Cloud Config
Spring Cloud Config 是由 Spring Cloud 团队开发的项目,为微服务架构中各个微服务提供集中化的外部配置支持。Spring Cloud Config 可以将各个微服务的配置文件集中存储在一个外部的存储仓库或系统(例如 Git 、SVN 等)中,对配置的统一管理,以支持各个微服务的运行。

Spring Cloud Config是最早的配置中心,正在逐渐被淘汰。

服务总线
Spring Cloud Bus
Spring Cloud Bus 是 Spring Cloud 体系内的消息总线,用来连接分布式系统的所有节点,配合Spring Cloud Config使用可以实现配置的动态刷新。

Spring Cloud Bus 将分布式的节点用轻量的消息代理(RibbitMQ、Kafka)连接起来。可以通过消息代理广播配置文件的更改,或服务之间的通讯,也可以用于监控。解决了微服务数据变更,及时同步的问题。

链路追踪
sleuth
Sleuth 是 Spring Cloud 中的一个组件,主要功能是在分布式系统中提供服务链路追踪的解决方案。

zipkin
Zipkin是Twitter开源的调用链分析工具,目前基于springcloud sleuth得到了广泛的使用,特点是轻量,使用部署简单。

Skywalking
SkyWalking 是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。

管理监控
Spring Boot Admin
Spring Boot Admin(SBA)是一个开源的社区项目,用于管理和监控 Spring Boot 应用程序。应用程序可以通过 http 的方式,或 Spring Cloud 服务发现机制注册到 SBA 中,然后就可以实现对 Spring Boot 项目的可视化管理和查看了。

Spring Boot Admin 可以监控 Spring Boot 单机或集群项目,它提供详细的健康 (Health)信息、内存信息、JVM 系统和环境属性、垃圾回收信息、日志设置和查看、定时任务查看、Spring Boot 缓存查看和管理等功能。

16.平时自主学习这一块,你会上哪些网站?

CSDN GITHUB B站 LeetCode Java官方文档等

17.比较好的、小的一些中间件可以用到相应的业务场景的,你推荐的话,你这边有吗?

tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML[标准通用标记语言]下的一个应用页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。

​ 当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和[IIS]等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态[HTML]的能力不如Apache服务器。
Tomcat特点:

运行时占用的系统资源小,扩展性好,支持负载均衡与邮件服务等开发应用系统常用的功能
开源的web服务器
小型的轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选
还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式

Jetty 是一个开源的servlet容器,它为基于Java的[web容器],例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。开发人员可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行(stand-alone)的Java应用提供网络和web连接。Jetty 可以作为嵌入式服务器使用,Jetty的运行速度较快,而且是轻量级的,可以在Java中可以从test case中控制其运行。从而可以使[自动化测试]不再依赖外部环境,顺利实现自动化测试。

和tomcat比较: Jetty更轻量级。这是相对Tomcat而言的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值