四、Java高级部分
1.红黑树的实现原理和应用场景;
1.(1)每个节点或者是黑色,或者是红色。 (2)根节点是黑色。 (3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!] (4)如果一个节点是红色的,则它的子节点必须是黑色的。 (5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。 注意: (01) 特性(3)中的叶子节点,是只为空(NIL或null)的节点。 (02) 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接*衡的二叉树。 2.红黑树的应用比较广泛,主要是用它来存储有序的数据,它的时间复杂度是O(lgn),效率非常之高。 例如,Java集合中的TreeSet和TreeMap,C++ STL中的set、map,以及Linux虚拟内存的管理,都是通过红黑树去实现的。
参考链接:https://www.cnblogs.com/skywang12345/p/3245399.html
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
2.NIO是什么?适用于何种场景?
1.NIO是为了弥补IO操作的不足而诞生的网络通信模型,NIO的一些新特性有:非阻塞I/O,选择器,缓冲以及管道。管道(Channel),缓冲(Buffer) ,选择器( Selector)是其主要特征。 2.服务器需要支持超大量的长时间连接。比如10000个连接以上,并且每个客户端并不会频繁地发送太多数据。例如总公司的一个中心服务器需要收集全国便利店各个收银机的交易信息,只需要少量线程按需处理维护的大量长期连接。 Jetty、Mina、Netty、ZooKeeper等都是基于NIO方式实现。 参考链接:https://www.jianshu.com/p/59f610d8f97d
3.Java9比Java8改进了什么;
1. Java 平台级模块系统。模块化的 JAR 文件都包含一个额外的模块描述器。在这个模块描述器中, 对其它模块的依赖是通过 “requires” 来表示的。另外, “exports” 语句控制着哪些包是可以被其它模块访问到的。所有不被导出的包默认都封装在模块的里面。 2.Linking, jlink 工具实现创建针对应用程序进行优化的最小运行时映像而不需要使用完全加载 JDK 安装版本。 3.Javadoc 现在支持在 API 文档中的进行搜索。另外,Javadoc 的输出现在符合兼容 HTML5 标准。 4.集合工厂方法添加了Set<Integer> ints = Set.of(1, 2, 3); List<String> strings = List.of("first", "second");些方法也可以避免您选择特定的集合实现 5.从控制台启动 jshell ,并直接启动输入和执行 Java 代码。 jshell 的即时反馈使它成为探索 API 和尝试语言特性的好工具。 6.Stream 接口中添加了 4 个新的方法:dropWhile, takeWhile, ofNullable。还有个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代: 7.接口的默认方法 8.新的方式来处理 HTTP 调用。这个迟到的特性用于代替老旧的 `HttpURLConnection` API,并提供对 WebSocket 和 HTTP/2 的支持。 9.多版本兼容 JAR 功能能让你创建仅在特定版本的 Java 环境中运行库程序时选择使用的 class 版本
参考链接:http://www.importnew.com/24528.html
4.HashMap内部的数据结构是什么?底层是怎么实现的?(还可能会延伸考察ConcurrentHashMap与HashMap、HashTable等,考察对技术细节的深入了解程度);
HashMap的底层实现都是数组+链表结构实现,添加、删除、获取元素时都是先计算hash,根据hash和table.length计算index也就是table数组的下标,然后进行相应操作.
参考链接:https://blog.csdn.net/u011202334/article/details/51496381
5.说说反射的用途及实现,反射是不是很慢,我们在项目中是否要避免使用反射;
反射机制是Java语言中一个非常重要的特性,它允许程序在运行时进行自我检查,同时也允许对其内部成员进行操作。反射机制提供的功能主要有:得到一个对象所属的类;获取一个类的所有成员变量和方法;在运行时创建对象;在运行时调用对象的方法,很多框架(比如 Spring)都是配置化的(比如通过 XML文件配置JavaBean,Action之类的),为了保证框架的通用性,他们可能根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射——运行时动态加载需要加载的对象。 参考链接:https://blog.csdn.net/SongYuxinIT/article/details/81872066
6.说说自定义注解的场景及实现;
使用场景:①类属性自动赋值。②验证对象属性完整性。③代替配置文件功能,像spring基于注解的配置。④可以生成文档,像java代码注释中的@see,@param等 参考链接:https://blog.csdn.net/bluuusea/article/details/79996572
7.List 和 Map 区别,Arraylist 与 LinkedList 区别,ArrayList 与 Vector 区别;
1.List是有顺序的 可重复的,Map是通过键值对进行取值的 key和value是一一对应的 2.①ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (LinkedList是双向链表,有next也有previous) ②对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 ③对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 3.①Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。 ②当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。
五、Spring相关
8.Spring AOP的实现原理和场景?
AOP(Aspect Oriented Programming,面向切面编程),将程序运行过程分解为一个个的切面,对特定的切面(某个步骤或者阶段)进行提取,达到解耦各种不同逻辑代码。OOP是在程序分块层面上进行考虑,而AOP则是在程序运行的切面上进行考虑。
AOP主要分为两大类:
一是采用动态代理,对被代理对象和特定处理进行修饰和封装,得到代理对象,从使得被代理对象中不需切入任何的代码,如图:
简单的代理:实现不入侵原始对象而切入各种通用的业务逻辑(eg: 参数验证、日志记录方法等)
二是采用静态织入,如AspectJ,使用其特定的语法创建切面,在编译期间将切面织入代码中。又如,通过AspectJ编译出来的class文件与普通编译出来的有很大区别,这块没有了解,不再赘述。
应用场景:权限控制、异常处理、缓存、事务管理、日志记录、数据校验等等
9.Spring bean的作用域和生命周期;
1.Spring 3中为Bean定义了5中作用域,分别为singleton(单例)、prototype(原型)、request、session和global session,5种作用域说明如下: ①singleton:单例模式,Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象。Singleton作用域是Spring中的缺省作用域,也可以显示的将Bean定义为singleton模式,配置为:<bean id="userDao" class="com.ioc.UserDaoImpl" scope="singleton"/> ②prototype:原型模式,每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态,而singleton全局只有一个对象。根据经验,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。 ③request:在一次Http请求中,容器会返回该Bean的同一实例。而对不同的Http请求则会产生新的Bean,而且该bean仅在当前Http Request内有效。<bean id="loginAction" class="com.cnblogs.Login" scope="request"/>,针对每一次Http请求,Spring容器根据该bean的定义创建一个全新的实例,且该实例仅在当前Http请求内有效,而其它请求无法看到当前请求中状态的变化,当当前Http请求结束,该bean实例也将会被销毁。 ④session:在一次Http Session中,容器会返回该Bean的同一实例。而对不同的Session请求则会创建新的实例,该bean实例仅在当前Session内有效。<bean id="userPreference" class="com.ioc.UserPreference" scope="session"/>,同Http请求相同,每一次session请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的session请求内有效,请求结束,则实例将被销毁。 ⑤global Session:在一个全局的Http Session中,容器会返回该Bean的同一个实例,仅在使用portlet context时有效。 2.Bean的生命周期: Spring容器可以管理singleton作用域下Bean的生命周期,在此作用下,Spring能够精确地知道Bean何时被创建,何时初始化完成,以及何时被销毁。而对于prototype作用域的Bean,Spring只负责创建,当容器创建了Bean的实例后,Bean的实例就交给了客户端的代码管理,Spring容器将不再跟踪其生命周期,并且不会管理那些被配置成prototype作用域的Bean的生命周期。Spring中Bean的生命周期的执行是一个很复杂的过程,读者可以利用Spring提供的方法来定制Bean的创建过程。
参考链接:https://www.cnblogs.com/zhanglei93/p/6231882.html
10.Spring Boot比Spring做了哪些改进? Spring 5比Spring4做了哪些改进;
1.①使用Java或Groovy开发基于Spring的应用程序非常容易。 ②减少了大量的开发时间并提高了生产力。 ③避免了编写大量的样板代码,注释和XML配置。 ④Spring Boot应用程序与其Spring生态系统(如Spring JDBC,Spring ORM,Spring Data,Spring Security等)集成非常容易。 ⑤遵循“自用默认配置”方法,以减少开发工作量。 ⑥提供嵌入式HTTP服务器,如Tomcat,Jetty等,以开发和测试Web应用程序非常容易。 ⑦提供CLI(命令行界面)工具从命令提示符,非常容易和快速地开发和测试Spring Boot(Java或Groovy)应用程序。 ⑧提供了许多插件来开发和测试Spring启动应用程序非常容易使用构建工具,如Maven和Gradle。 ⑨提供了许多插件,以便与嵌入式和内存数据库工作非常容易。 2.JDK8的增强: 访问Resuouce时提供getFile或和isFile防御式抽象 有效的方法参数访问基于java 8反射增强 在Spring核心接口中增加了声明default方法的支持一贯使用JDK7 Charset和StandardCharsets的增强 兼容JDK9 Spring 5.0框架自带了通用的日志封装 持续实例化via构造函数(修改了异常处理) Spring 5.0框架自带了通用的日志封装 spring-jcl替代了通用的日志,仍然支持可重写 自动检测log4j 2.x, SLF4J, JUL(java.util.Logging)而不是其他的支持 访问Resuouce时提供getFile或和isFile防御式抽象 基于NIO的readableChannel也提供了这个新特性
核心容器: 支持候选组件索引(也可以支持环境变量扫描) 支持@Nullable注解 函数式风格GenericApplicationContext/AnnotationConfigApplicationContext 基本支持bean API注册 在接口层面使用CGLIB动态代理的时候,提供事物,缓存,异步注解检测 XML配置作用域流式 Spring WebMVC 全部的Servlet 3.1 签名支持在Spring-provied Filter实现 在Spring MVC Controller方法里支持Servlet4.0 PushBuilder参数 多个不可变对象的数据绑定(Kotlin/Lombok/@ConstructorPorties) 支持jackson2.9 支持JSON绑定API 支持protobuf3 支持Reactor3.1 Flux和Mono
SpringWebFlux: 新的spring-webflux模块,一个基于reactive的spring-webmvc,完全的异步非阻塞,旨在使用enent-loop执行模型和传统的线程池模型。 Reactive说明在spring-core比如编码和解码 spring-core相关的基础设施,比如Encode 和Decoder可以用来编码和解码数据流;DataBuffer 可以使用java ByteBuffer或者Netty ByteBuf;ReactiveAdapterRegistry可以对相关的库提供传输层支持。 在spring-web包里包含HttpMessageReade和HttpMessageWrite
测试方面的改进:
完成了对JUnit 5’s Juptier编程和拓展模块在Spring TestContext框架 SpringExtension:是JUnit多个可拓展API的一个实现,提供了对现存Spring TestContext Framework的支持,使用@ExtendWith(SpringExtension.class)注解引用。 @SpringJunitConfig:一个复合注解 @ExtendWith(SpringExtension.class) 来源于Junit Jupit @ContextConfiguration 来源于Srping TestContext框架 @DisabledIf 如果提供的该属性值为true的表达或占位符,信号:注解的测试类或测试方法被禁用 在Spring TestContext框架中支持并行测试 具体细节查看Test 章节 通过SpringRunner在Sring TestContext框架中支持TestNG, Junit5,新的执行之前和之后测试回调。 在testexecutionlistener API和testcontextmanager新beforetestexecution()和aftertestexecution()回调。MockHttpServletRequest新增了getContentAsByteArray()和getContentAsString()方法来访问请求体 如果字符编码被设置为mock请求,在print()和log()方法中可以打印Spring MVC Test的redirectedUrl()和forwardedUrl()方法支持带变量表达式URL模板。 XMLUnit 升级到了2.3版本。
11.Spring IOC是什么?优点是什么?
1.控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统(IOC容器),将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。 2.优点:因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单(一般这样的对象都是现实于某种接口的),只要修改XML就可以了,这样我们甚至可以实现对象的热插拨(有点象USB接口和SCIS硬盘了)。 缺点:(1)生成一个对象的步骤变复杂了(其实上操作上还是挺简单的),对于不习惯这种方式的人,会觉得有些别扭和不直观。(2)对象 生成因为是使用反射编程,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。(3) 缺少IDE重构操作的支持,如果在Eclipse要对类改名,那么你还需要去XML文件里手工去改了,这似乎是所有XML方式的缺憾所在。
参考链接:https://www.cnblogs.com/xdp-gacl/p/4249939.html
12.动态代理、反射、事务隔离级别;
1.代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 2.JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 3.①Read uncommitted(读未提交):最低级别,任何情况都会发生。 ②Read Committed(读已提交):可避免脏读的发生。 ③Repeatable read(可重复读):可避免脏读、不可重复读的发生。 ④Serializable(串行化):避免脏读、不可重复读,幻读的发生。