2020大部分知名公司Java面试题答案(一)
个人资源与分享网站:http://xiaocaoshare.com/
1.&不管前面条件的是否正确,后面的都会执行
&& 只有当前面条件正确的时候后面才会执行,效率更好
2.#{}是参数的占位符(sql预编译)
${}是字符串替换(sql拼接)
3.throws 用在方法上,声明异常,后面紧跟异常类名
throw用在方法内部,抛一个具体的异常,后面紧跟异常对象
4.HashMap实现了Map接口,Map接口对键值对进行映射。Map接口的两个基本实现类是HashMap和TreeMap。TreeMap保证了对象的排列次序,而HashMap是无序的。HashMap的键和值可以赋值为null。HashMap是非synchronized的,可以通过Collections工具类的synchronizedMap方法使得HashMap是同步的。同步之后只允许一个线程访问对象。
5.HashMap是基于hash原理的。通过put()和get()方法获得和存储对象。当进行put()方法时,先通过key的hashCode()方法计算出hashCode,通过indexFor(hashCode,length)方法得到对象存储于table中的下标位置,也就是找到bucked的位置用来存储Entry。
6.首先通过key的hashCode()方法的hashCode,通过hashCode找到对应的bucked的位置。通过keys.equals()方法找到正确的键值对,返回value的值。
7.jdk7中使用的是:数组+链表 jdk8中使用的是:数组+链表+红黑树,在链表长度大于8的时候转成红黑树
数组的优点:易查询,不易添加修改操作(通过下标来查找)
链表的优点:易添加修改,不易查询(通过遍历查找)
8.HashSet是Set接口的实现类,同样通过计算hashCode存储对象集合,它不允许集合中有重复的值。当我们使用HashSet存储对象时,首先要确保对象重写的equals()和hashCode()以免在集合中出现重复的对象。如果没有重写这两个方法,则使用默认的函数。HashSet通过add方法进行对象的添加。
9.HashMap存储的是键值对,实现了Map接口,使用put()方法存储键值对,使用key来计算hashcode
HashSet存储的是对象,实现了Set接口,使用add()方法存储对象,使用成员对象来计算hashcode,当hashcode相同时通过equals()比较两个对象是否相等
10.sort():排序
binarySearch():查找指定集合中的元素,返回所查找元素的索引
reverse(): 反转集合中元素的顺序
copy() :拷贝
11.-client 设置jvm使用client模式
-server 设置jvm使server模式
-agentlib:libname[=options] 用于装载本地lib包
-agentpath:pathname[=options] 按全路径装载本地库,不再搜索PATH中的路径
-classpath classpath -cp classpath 告知jvm搜索目录名、jar文档名、zip文档名,之间用分号
-Dproperty=value 设置系统属性名/值对
-enableassertions[:<package name>"..." | :<class name> ] -ea[:<package name>"..." | :<class name> ] 设置jvm是否启动断言机制(从JDK 1.4开始支持),缺省时jvm关闭断言机制
-disableassertions[:<package name>"..." | :<class ; ] 设置jvm关闭断言处理,packagename和classname的使用方法和-ea相同,jvm默认就是关闭状态
-da[:<package name>"..." | :<class name> ]
-version 输出java的版本信息,比如jdk版本、vendor、model。
12.@Controller @Component @Service @Repository @RequestMapping @ResponseBody @RequestBody @RequestParam @PathVariable
13.application/x-www-form-urlencoded multipart/form-data application/json text/xml binary
14.(1)浏览器先web服务器发送了一条http请求,web服务器对http请求进行解析,解析后的url地址如果匹配了DispatcherServlet的映射路径(web.xml配置的servlet-mapper),则交给DispatcherServlet处理
(2) DispatcherServlet对url进行解析,得到请求资源标识符(URI),然后调用相应的方法得到haddleMapping对象,根据URI,获取haddler对象以及对应的拦截器
(3) DispatcherServlet根据得到的haddler对象,选择一个合适的HaddleAdapter,创建其实例对象,执行拦截器的preHaddler()方法
(4)在拦截器方法中,获取请求中的参数,填充Haddler入参,开始执行Haddler
(5)Haddler执行完返回一个ModelAndView对象会交给DispatcherServlet
(6) DispatcherServlet通过ViewResolver视图解析器将逻辑视图解析成正常的视图
(7) DispatcherServlet通过ModelAndView中的数据用于渲染视图,最后通过http响应返回给浏览器
15.6379
16.mkdir -p 文件夹名称
17.select * from user where username in(select username from user group by username having count(username)>1)
18.左连接:连接查询的数据,以左边的表为主,左边的表必有,右边的可以有也可以没有
SELECT * from user u LEFT JOIN product p on u.id=p.user_id
右连接:连接查询的数据,已右边的表为主,右边表的数据必有
SELECT * from user u RIGHT JOIN product p on u.id=p.user_id
19.笔者认为主要是聚合函数用的比较多,现介绍用的比较多的聚合函数:
avg(col)返回指定列的平均值
count(col)返回指定列中非null值的个数
min(col)返回指定列的最小值
max(col)返回指定列的最大值
sum(col)返回指定列的所有值之和
group_concat(col) 返回由属于一组的列值连接组合而成的结果
20.瞬时状态:对象通过new关键字创建对象后,此时的状态为瞬时状态
持久状态:当对象被session关联,被session管理时,他就处于持久状态
游离状态:处于持久状态的对象,脱离session的管理,就变成了游离状态
21.主要使用动态sql标签,常用的有:if where choose when otherwise set trim foreach等标签
22.线程安全:当多线程访问时,采用了加锁的机制,就是说当一个线程访问某个类的某个数据是,其他线程不能再访问这个类的这个数据了,直到这个线程结束后才能被其他线程使用,否则会出现数据不一致和脏数据问题
线程安全的类有:Vector HashTable StringBuff
非线程安全的集合对象:ArrayList LinkedList HashSet HashMap TreeMap TreeSet StringBulider
23.前后端分离。前端拿到数据只负责展示和渲染,不对数据做任何处理。后端处理数据并以JSON格式传输出去,定义这样一套统一的接口,在web,ios,android三端都可以用相同的接口
24.(1)springboot是约定大于配置,可以简化spring的配置流程;springmvc是基于servlet的mvc框架,个人感觉少了model中的映射
(2)以前web应用要使用到tomat服务器启动,而springboot内置服务器容器,通过@SpringBootApplication中注解类中main函数启动即可
25.@Component 没有明确角色的组件
@Service 在业务逻辑层(Service层)使用
@Repositpry 在数据访问层(dao层)使用
@Controller 用于标注控制层组件
@RestController
26.(1)singleton (默认的)在每个Spring IOC容器中,一个bean定义对应只会有唯一的一个bean实例
(2)prototype 一个bean定义可以有多个bean实例
(3)request 一个bean定义对应于单个http请求的生命周期。每个http请求都有一个bean实例,且该实例仅在这个HTTP请求的生命周期内有效,该作用域仅适用于WebApplicationContext
(4)session 一个bean定义对应单个HTTP Session的生命周期。每个HTTP Session都有一个bean实例,且该实例仅在这个HTTP Session的生命周期内有效,该作用域仅适用于WebApplicationContext
(5)application 一个bean定义对应于单个ServletContext生命周期,该作用域仅适用于WebApplicationContext
(6)websocket 一个bean定义对应于单个websocket生命周期,该作用域仅适用于WebApplicationContext
27.@ControllerAdvice:它定义在一个类上,和@Component类似,它使得@ExceptionHandler、@InitBindler、@ModelAttribute注解可以作用在所有@RequestMapping注解上。
@ExceptionHandler:它定义在Controller的方法上,作用是捕获指定的异常,然后进行统一处理并返回最后的结果。
28.
@Override
public void addCorsMappings(CorsRegistry registry) {
String mapping = "/**"; // 所有请求,也可配置成特定请求,如/api/**
String origins = "*"; // 所有来源,也可以配置成特定的来源才允许跨域,如http://www.xxxx.com
String methods = "*"; // 所有方法,GET、POST、PUT等
registry.addMapping(mapping).allowedOrigins(origins).allowedMethods(methods);
}
29.事务的7种传播行为
使用场景:当事务方法A调用事务方法B时,会将A的事务传播给B,B对于事务的处理方式就是事务的传播行为。因此,必须在被调用者B方法中指定事务的传播行为
(1)required 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择(默认事务)
(2)supports 支持当前事务,如果当前没有事务,就以非事务方式执行。
(3)mandatory 使用当前的事务,如果当前没有事务,就抛出异常。
(4)Required_new 新建事务,如果当前存在事务,把当前事务挂起。
(5)not_supported 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
(6)never 以非事务方式执行,如果当前存在事务,则抛出异常。
(7)Nested 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与required 类似的操作。
30.(1)xml添加mybatis依赖
(2)继承通用的mapper
(3)在配置文件中配置dao路径
xml的标签id跟dao中的方法名一一对应
31.(1)数组在创建时需要指定数组大小,ArrayList不需要
(2)数组在存放对象时需要指明位置,ArrayList在存放对象是需要使用add()方法
ArrayList具有动态扩容的机制,每次在添加元素时,都会判断容量是否够用,如果不够用,则需要扩容。
JDK1.8中,ArrayList的初始容量为0,第一次添加元素时,会将容量设置为10,如果容量不够,则每次会扩大50%
32.
1.抽象类中可以有普通成员变量,接口中没有普通成员变量
2.抽象类可以有构造方法,接口中不能有构造方法
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4.抽象类中可以包含静态方法,接口中不能包含静态方法
5.抽象类中的抽象方法的访问类型可以是 public,protected ,但接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型
6.一个类可以实现多个接口,但只能继承一个抽象类
7.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只是public static final 类型,并且默认即为 public static final 类型。
33.(1)字符串String 应用场景:统计网站访问数量,当前在线人数等
(2)列表list 应用场景:最新消息、排行榜、消息队列
(3)集合set 应用场景:利用唯一性,可以统计访问网站的所有独立IP
(4)散列hash 应用场景:存储、读取、修改用户属性
(5)有序集合zset(sorted set) 应用场景:可以用于一个大型在线游戏的积分排行榜
34.
1、缓存数据
2、消息队列
3、计数器
4、电商网站信息 大型电商平台初始化页面数据的缓存。比如去哪儿网购买机票的时候首页的价格和你点进去的价格会有差异。
5、热点数据 比如新闻网站实时热点、微博热搜等,需要频繁更新。总数据量比较大的时候直接从数据库查询会影响性能
35.Redis是单线程模型,指的是执行Redis命令的核心模块是单线程的,而不是整个Redis实例就一个线程,Redis其他模块还有各自的线程的
36.SpringBoot自动配置主要是通过@EnableAutoConfiguration,@Conditional,@EnableConfigProperties,@ConfigurationProperties等注解实现的。当我们写好一个启动类后,我们会在启动类上加一个@SpringBootApplication,我们可以点开这个注解可以看到它内部有一个@EnableAutoConfiguation的注解,我们继续进入这个注解可以看到一个@Import的注解,这个注解引入了一个AutoConfigurationImportSelector的类。我们继续打开这个类可以看到它有一个selectorImport的方法,这个方法又调用了一个getCandidateConfigurations方法,这个方法内部通过SpringFactoriesLoader.loadFactoryNames最终调用loadSpringFactories加载到一个META-INF下的spring.factories文件。打开这个文件可以看到是一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔。当我们通过springApplication.run启动的时候内部就会执行selectImports方法从而找到配置类对应的class。然后将所有自动配置类加载到Spring容器中,进而实现自动配置。
37. spring的事务是通过“声明式事务”的方式对事务进行管理,即在配置文件中进行声明,通过AOP将事务切面切入程序。最大的好处是大大减少了代码量
扩充知识:
1.事务的四大特性:
原子性(Atomicity):事务中的所有数据库操作要么都执行成功,要么都执行失败。
一致性(Consistency):事务执行前后,数据都是正确的。数据库状态与业务规则保持一致。
隔离性(Isolation):多个事务并发执行时,事务间互不干扰。
持久性(Durability):已提交的事务对数据库数据的修改,应永久保存在数据库。
2.Spring事务管理
(1)编程式 使用原生JDBC API进行事务管理,在核心业务代码中嵌入事务管理代码,容易造成代码冗余,增加代码间的耦合度。
(2)声明式 把事务管理代码从业务代码中分离,借助spring aop,在不同的事务管理api中抽象出一套事务管理机制,实现声明式事务管理。
(3)事务管理器
3.怎么进行事务控制?
(1)xml方式
示例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 1、配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--此处省略具体配置-->
</bean>
<!-- 2、配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 3、配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
</tx:attributes>
</tx:advice>
<!-- 4、配置aop-->
<aop:config>
<aop:pointcut id="pt1" expression="execution(* com.demo.service.impl.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>
</beans>
(2)全注解方式
38.事务的隔离级别
1.事务并发问题
(1)脏读
指一条数据中的字段
① Transaction01将某条记录的AGE值从20修改为30。
② Transaction02读取了Transaction01更新后的值:30。
③ Transaction01回滚,AGE值恢复到了20。
④ Transaction02读取到的30就是一个无效的值。
(2)不可重复读
指一条数据中的字段
①Transaction01读取了AGE值为20。
②Transaction02将AGE值修改为30。
③Transaction01再次读取AGE值为30,和第一次读取不一致。
(3)幻读
指一张表的行数据
①Transaction01读取了STUDENT表中的一部分数据。
②Transaction02向STUDENT表中插入了新的行。
③Transaction01读取了STUDENT表时,多出了一些行。
2.四种隔离级别
数据库系统必须具备隔离并发运行各个事务的能力,事务间的隔离程度就称为隔离级别。级别越高,数据一致性越好,但并发性越弱。
3.隔离级别解决并发问题能力表
脏读 |
不可重复读 |
幻读 |
|
READ UNCOMMITTED |
有 |
有 |
有 |
READ COMMITTED |
无 |
有 |
有 |
REPEATABLE READ |
无 |
无 |
有 |
SERIALIZABLE |
无 |
无 |
4.数据库产品对隔离级别支持程度
Oracle |
MySQL |
|
READ UNCOMMITTED |
× |
√ |
READ COMMITTED |
√(默认) |
√ |
REPEATABLE READ |
× |
√(默认) |
SERIALIZABLE |
√ |
√ |
39.三个核心概念:
1.原子性
即一个操作(有可能包含有多个子操作)要么全部执行(生效),要么全部都不执行(都不生效)
使用场景:银行转账问题,比如A和B同时向C转账10万元。如果转账操作不具有原子性,A在向C转账时,读取了C的余额为20万,然后加上转账的10万,计算出此时应该有30万,但还未来及将30万写回C的账户,此时B的转账请求过来了,B发现C的余额为20万,然后将其加10万并写回。然后A的转账操作继续——将30万写回C的余额。这种情况下C的最终余额为30万,而非预期的40万。
2.可见性
指当多个线程并发访问共享变量时,一个线程对共享变量的修改,其它线程能够立即看到
CPU从主内存中读数据的效率相对来说不高,现在主流的计算机中,都有几级缓存。每个线程读取共享变量时,都会将该变量加载进其对应CPU的高速缓存里,修改该变量后,CPU会立即更新该缓存,但并不一定会立即将其写回主内存(实际上写回主内存的时间不可预期)。此时其它线程(尤其是不在同一个CPU上执行的线程)访问该变量时,从主内存中读到的就是旧的数据,而非第一个线程更新后的数据。
3.顺序性
指程序执行的顺序按照代码的先后顺序执行
如何保证原子性?
常用的保证Java操作原子性的工具是锁和同步方法(或者同步代码块)。
使用锁,可以保证同一时间只有一个线程能拿到锁,也就保证了同一时间只有一个线程能执行申请锁和释放锁之间的代码。
与锁类似的是同步方法或者同步代码块。使用非静态同步方法时,锁住的是当前实例;使用静态同步方法时,锁住的是该类的Class对象;使用静态代码块时,锁住的是synchronized
关键字后面括号内的对象。
如何保证可见性?
Java提供了volatile
关键字来保证可见性。当使用volatile修饰某个变量时,它会保证对该变量的修改会立即被更新到内存中,并且将其它缓存中对该变量的缓存设置成无效,因此其它线程需要读取该值时必须从主内存中读取,从而得到最新的值。
如何保证顺序性?
Java中可通过volatile
在一定程序上保证顺序性,另外还可以通过synchronized和锁来保证顺序性。
synchronized和锁保证顺序性的原理和保证原子性一样,都是通过保证同一时间只会有一个线程执行目标代码段来实现的。
线程是非独立的,同一个进程里线程是数据共享,当各个线程访问数据资源时会出现竞争的状态即:数据几乎同步会被多个进程占用, 造成数据混乱 ,即所谓的线程不安全
那么怎么解决多线程竞争问题 – 锁
锁的好处:
确保了某段代码(共享数据资源)只能由一个线程从头到尾完整地执行能解决多线程支援竞争下的原子操作问题
缩的坏处:
阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,线程就大大地下降了
锁的 致命问题:死锁
锁 是python 提供的对线程控制的对象。有互斥锁,可重入锁,死锁。
40.
1、线程池实现多线程
ExecutorService threadPool = Executors.newFixedThreadPool(10);for(int i = 0; i < 10; i++){threadPool.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+" is executing");}});}
2.有哪几种线程池?
可缓存线程池newCachedThreadPool(),其中创建的都是非核心线程,创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
单线程newSingleThreadExecutor(),创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
固定线程池newFixedThreadPool(),创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
定时线程池newScheduleThreadPool,创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。
3.
start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,
区别:
当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动;
start()方法才会启动新的线程
知识扩展:
1)线程池有哪些重要的参数?
核心线程数,最大线程数,线程空闲时间,时间单位,阻塞队列大小:queueCapacity,任务拒绝处理器 :rejectedExceptionHandler
2)多线程使用的场景
a.数据库的数据分析(待分析的数据太多),数据迁移
b.servlet多线程
c.FTP下载,多线程操作文件
3)corePoolSize:核心线程数
maximumPoolSize:最大线程数
poolSize:线程池中当前线程的数量
那么poolSize、corePoolSize、maximumPoolSize三者的关系是如何的呢?
当新提交一个任务时:
(1)如果poolSize<corePoolSize,新增加一个线程处理新的任务。
(2)如果poolSize=corePoolSize,新任务会被放入阻塞队列等待。
(3)如果阻塞队列的容量达到上限,且这时poolSize<maximumPoolSize,新增线程来处理任务。
(4)如果阻塞队列满了,且poolSize=maximumPoolSize,那么线程池已经达到极限,会根据饱和策略RejectedExecutionHandler拒绝新的任务
4)死锁:多个线程互相占用对方资源的锁,又相互等待对方释放锁,若无外力干涉,这些线程则一直处于阻塞你的假死状态,形成死锁
活锁:指拿到资源却又相互释放不执行,这个资源在多个线程之间跳动又得不到执行
饥饿:指优先级高的线程一直占着优先级低的资源,导致优先级低的线程无法得到执行,处于长久等待中
41.索引就是数据库目录,比如:字典上面的字母目录 (适用于大数据量)
优点:查询速度快
缺点:增删改慢,因为数据库要同步去维护索引文件,所以速度慢
42.普通索引、唯一索引、主键索引、组合索引
43.在一个或一些字段需要频繁用作查询条件,并且表数据较多的时候
44.通过explain查询sql执行计划,主要是看key使用的是哪个索引
45.(1)ArrayList是数组的数据结构,LinkedList是链表的数据结构
(2)随机访问的时候,ArrayList的效率比较高,因为LinkedList要移动指针,而ArrayList是基于索引(index)的数据结构,可以直接映射到
(3)插入、删除数据时,LinkedList的效率比较高,因为ArrayList要移动数据
(4)LinkedList比ArrayList开销更大,因为LinkedList的节点除了存储数据,还需要存储引用
46.(1)List 以索引来存取元素,有序的,元素是允许重复的,可以插入多个null
(2)Set 不能存放重复元素,无序的,只允许一个null
(3)Map 保存键值对映射,映射关系可以一对一、多对一
(4)List 有基于数组、链表实现两种方式
(5)Set、Map 容器有基于哈希存储和红黑树两种方式实现
(6)Set 基于 Map 实现,Set 里的元素值就是 Map的键值
47.(1)组合索引,不是使用第一列索引,索引就会失效
(2)like以%开头,索引无效
(3)or语句前后没有同时使用索引。当or左右查询字段只有一个是索引,该索引失效;当or左右查询字段均为索引时,才会生效
(4)数据类型出现隐式转化。如varchar不加单引号会自动转化为int型,使索引无效,产生全表查询
(5)在索引列上使用is null 或is not null 。索引是不索引空值的
(6)在索引字段上使用not,!=。不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 优化方法: key<>0 改为 key>0 or key<0。
(7)索引字段进行计算操作
(8)在索引字段上使用函数
48.(1)查询语句中不要使用*
(2)
尽量减少子查询,使用关联查询(left join, right join, inner join)代替
(3)减少使用IN或者NOT IN,使用exists,not exists或者关联查询语句代替
(4)对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差
(5)合理的增加冗余的字段(减少表的关联查询)
(6)增加中间表进行优化(这个主要是在统计报表的场景,后台开定时任务将数据先统计好,尽量不要在查询的时候去统计)
(7)建表的时候能使用数字类型的字段就使用数字类型(type,status…),数字类型的字段作为条件查询比字符串快。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了
(8)那些可以过滤掉最大数量记录的条件必须写在where字句的最末尾
(9)索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要
(10)尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些
(11)对查询进行优化,应尽量避免全表扫描,首先应考虑在where以及order by涉及的列上建立索引
49.redis有两种持久化机制:RDB(默认)、AOF
rdb持久化:Redis为我们提供了一个rdb的持久化方式具体每隔一定时间,或者当key的改变达到一定的数量的时候,就会自动往磁盘保存一次
aof持久化:Redis还为我们提供了一个aof的持久化方式,这种方式是通过记录用户的操作过程(用户每执行一次命令,就会被Redis记录在XXX.aof文件里,如果突然断电了,Redis的数据就会通过重新读取并执行XXX.aof里的命令记录来恢复数据)来恢复数据
持久化:就是把内存中的数据保存到磁盘
1) Redis为什么要有持久化?
由于Redis是一个基于内存的数据库,因此数据容易丢失,为了解决数据丢失的问题,于是Redis就设计了持久化
50.JVM内存结构包括PC寄存器、Java虚拟栈、本地方法栈、Java堆、方法区
PC寄存器:当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有
Java虚拟栈:存放基本数据类型、对象的引用、方法出口等,线程私有
本地方法栈:和虚拟栈相似,只不过它服务于Native方法,线程私有
Java堆:java内存最大的一块,所有对象实例、数组都存放在java堆,GC回收的地方,线程共享
方法区:存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。(即永久带),回收目标主要是常量池的回收和类型的卸载,各线程共享
51.(1)from
(2)on
(3)join
(4)where
(5)group by
(6)avg,sum
(7)having
(8)select
(9)distinct
(10)order by
52.Spring是一个轻量级的IoC和AOP容器框架
IOC : 控制反转,也有人叫自动注入.通过Spring bean factory工厂生产对象,降低耦合,将对象创建,销毁统统交给Spring来做,让我们有更多时间去关注业务
AOP : 面向切面编程,通过切面可以轻松实现拦截请求,初始化参数,销毁对象等操作
53.(1)为什么会有线程安全问题?
当多个线程同时共享同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读的操作不会发生线程安全问题。
(2)如何解决多线程之间线程安全问题?
使用多线程之间同步synchronized或使用锁(lock),将可能会发生数据冲突问题(线程不安全问题),只能让当前一个线程进行执行。代码执行完成后释放锁,然后才能让其他线程进行执行。这样的话,就可以解决线程不安全问题
(3)什么是多线程之间同步?
当多个线程共享同一个资源,不会受到其他线程干扰
(4)多线程死锁?
同步中嵌套同步,导致锁无法释放
54.
第一种,解决setter对象的依赖,就是说在A类需要设置B类,B类需要设置C类,C类需要设置A类,这时就出现一个死循环,
spring的解决方案是,初始化A类时把A类的初始化Bean放到缓存中,然后set B类,再把B类的初始化Bean放到缓存中,
然后set C类,初始化C类需要A类和B类的Bean,这时不需要初始化,只需要从缓存中取出即可.
该种仅对single作用的Bean起作用,因为prototype作用的Bean,Spring不对其做缓存
第二种,解决构造器中对其它类的依赖,创建A类需要构造器中初始化B类,创建B类需要构造器中初始化C类,创建C类需要构造器中又要初始化A类,因而形成一个死循环,Spring的解决方案是,把创建中的Bean放入到一个“当前创建Bean池”中,在初始化类的过程中,如果发现Bean类已存在,就抛出一个“BeanCurrentInCreationException”的异常
55.在Spring使用中,本地接口和实现都是在一个jvm实例中来启动并且进行bean注入的。dubbo就是透明化地把接口和实现分别部署到不同的jvm上。但是对于客户端来说,dubbo底层使用动态代理来给接口注入代理bean,然后客户端在调用过程中就像调用本地实现一样来使用。这个过程,其实dubbo通过代理进行了远程通信来跟另外一个jvm上面的实现来进行方法调用。
56.
57.(1)Git是分布式的,而SVN不是分布式的
(2)Git把内容按元数据方式存储,而SVN是按文件
(3)Git没有一个全局版本号,SVN有
(4)Git的内容的完整性要优于SVN: GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏
(5)Git下载下来后,在OffLine状态下可以看到所有的Log,SVN不可以
58.缓存处理流程:接收到查询数据请求时,优先从缓存中查询,若缓存中有数据,则直接返回,若缓存中查不到则从DB中查询,将查询的结果更新到缓存中,并返回查询结果,若DB中查不到,则返回空数据
击穿:高并发条件下,单个key在缓存中查不到,去数据库查询,如果数据库数据量比较大或并发量比较大就容易造成数据库 压力过大而崩溃
解决方案:1)通过synchronized+双重检查机制:某个key只让一个线程查询,阻塞其它线程
2)设置value永不过期
3)使用互斥锁
穿透:当缓存跟数据库都不存在该条数据时,由于数据库查询不到数据就不会写入到缓存中,如果用户不断恶意发起请求,就会导致每次请求查询数据库,请求量大的时候,数据库压力过大而挂掉
解决方案:1)当查询返回一个空数据时,直接将这个空数据存到缓存中,过期时间不宜设置过长,建议不超过5分钟
2)采用布隆过滤器:将所有可能存在数据,分别通过多个哈希函数生成多个哈希值,然后将这些哈希值存到一个足够大的bitmap中,此时一个一定不存在的数据就会被这个bitmap拦截,从而减少了数据库的查询压力
雪崩:在高并发条件下,多个key查询,缓存中失效或查不到,就会去数据库查询,导致数据库压力过大而崩溃
解决方案:1)设置热点数据永不过期
2)缓存数据的过期时间设置随机,可以在原有的过期时间上加上一个随机值,比如1-3min,防止同一时间大量缓存数据集体失效,导致数据库压力过大
3)如果是分布式部署缓存数据库,可将热点数据分别存放到不同的缓存数据库中,避免某一点由于压力过大而down掉
简单互斥锁的例子:
/*** redis实现分布式事务锁 尝试获取锁* * @param lockName 锁* @param expireTime 过期时间* @return*/public Boolean tryLock(String lockName, long expireTime) {//RedisCallback redis事务管理,将redis操作命令放到事务中处理,保证执行的原子性String result = stringRedisTemplate.opsForValue().getOperations().execute(new RedisCallback<String>() {/*** @param key 使用key来当锁,因为key是唯一的。* @param value 请求标识,可通过UUID.randomUUID().toString()生成,解锁时通value参数可识别出是哪个请求添加的锁* @param nx 表示SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作* @param ex 表示过期时间的单位是秒* @param time 表示过期时间*/@Overridepublic String doInRedis(RedisConnection connection) throws DataAccessException {return jedis.set(lockName, UUID.randomUUID().toString(), "NX", "EX", expireTime);}});if ("OK".equals(result)) {return true;}return false;}public String getValueFromDB() {return "";}
59.1)get参数通过url传递,post放在request body中
2)get请求在url中传递的参数是有长度限制的,而post没有
3)get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息
4)get请求只能进行url编码,而post支持多种编码方式
5)get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留
60.1)请求转发是1次请求;重定向是2次请求;
2)请求转发地址栏不变;重定向地址栏改变
3)请求转发是request的方法;重定向是response的方法
4)请求转发的时候可以使用request域对象;而重定向不能使用
5)请求转发的路径是内部路径;重定向的路径是绝对路径
6)若访问站外资源,需要使用重定向
61.默认引擎是innodb,最大的优点就是支持事务
MyISAM存储引擎
62.1)单例模式:配置在Spring容器中的Bean几乎都是单例,比如Controller、Service、Facade、Dao这些无状态的Bean。
public class Singleton {
private Singleton() {
}
private static Singleton instance = new Singleton();
public Singleton getInstance() {
return instance;
}
}
2)代理模式
1、利用注解AOP解决后台管理系统用户操作日志记录;
接口请求响应参数打印、参数校验、统一异常处理
2、利用Mybatis的Interceptor接口,来实现读写分离
3)享元模式
项目配置:常量池的String对象、缓存、数据库连接池、线程池
利用Mybatis的Interceptor接口,来实现读写分离的时候,将某个语句对应某个库缓存到ConcurrentHashMap中,如果存在则直接取,不存在则保存
2020大部分知名公司Java面试题答案(一)相关推荐
- 2020大部分知名公司Java面试题(一)
个人资源与分享网站:http://xiaocaoshare.com/ 1.&与&&的区别 2.mybatis中#{}和${}的区别 3.throws和throw区别 4.什么是 ...
- 用友公司Java面试题(含答案)
为什么80%的码农都做不了架构师?>>> 用友公司Java面试题(含答案) 1.Hashtable和HashMap有什么区别? a.Hashtable是继承自陈旧的Dict ...
- BAJT 中高级 Java 面试题答案
1.请问你做过哪些JVM优化?使用什么方法达到什么效果??? vm调优主要也就是内存空间的分配 最终策略:提高系统性能 主要策略有 1.增加eden空间,让更多的对象留在年轻代. 2.大对象直接放到老 ...
- java面试题答案大全超详细(持续更新)
java面试题答案大全超详细 第01章 java语言面试题 项目经理(作者):张明星 JVM 运行时数据区是什么? 程序计数器是什么? 程序计数器(线程私有) Java 虚拟机栈的作用? 本地方法栈的 ...
- 东软信息学院java试题,东软Java笔试题答案
东软Java笔试题答案 Java面向对象程序设计考试卷班级:姓名:时间:90分钟一.选择题(没有注明多选,则为单选)1. 下列变量定义错误的是A. int a; B. double b=4.5; C. ...
- 2014 java面试题_2014 java面试题 (答案)
2014 java面试题 (答案) 题目 一.选择题 1. 如下代码: class Super { public Integer getLenght() { return new Integer(4) ...
- 太赞了!2020年全网最新Java面试题(附答案)免费下载!超全!!
读者朋友们,2020 年全网最新最全 Java 面试题,带完整目录和答案的,已经新鲜出炉!目录如下(点击图片可拉大),非常齐全: 火速领取!我 2 小时后就删! 领取方式如下: 1. 扫描下方二维码关 ...
- 300页!2020年全网最新Java面试题(附答案)开放下载!超全!!
读者朋友们,2020 年全网最新最全 Java 面试题,带完整目录和答案的,已经新鲜出炉!目录如下(点击图片可拉大),非常齐全: 火速领取!我 2 小时后就删! 领取方式如下: 1. 扫描下方二维码关 ...
- 2020年1-6月份Java面试题总结,20多类1100道面试题含答案解析
很多程序员都会担心35岁的职业危机,而数据也显示,40岁以上的程序员几乎不存在,大都转了管理岗,余下的只能被迫离职或者转行.然而,太久待在舒适区,可能连小公司的面试,都很难通过了. 程序员是最需要将终 ...
最新文章
- 重磅!李飞飞入选美国国家医学科学院,她用AI改变了医疗
- 3年工作必备 装饰器模式
- 如何看服务器java_如何查看Windows服务器运行了多长时间
- C++知识点43——解引用运算符和箭头运算符的重载及智能指针类的实现
- 平衡二叉树,AVL树之图解篇
- Hands-on Lab (15) - 使用Prometheus Operator监控应用
- Spring 解耦工厂模式
- YUY2转RGB 的各种版本
- 电脑里的视频被误删了可以用EasyRecovery恢复吗?
- JAVA-JVM调优标志
- java web/Maven项目结构分析
- 关于MPMoviePlayerController类播放视频时,外放没有声音的问题(ios)
- 【简约美女win7主题】_8.4
- python 对 文件内容 搜索_python实现搜索文本文件内容脚本
- whisper客服源码_开源在线客服系统whisper
- 使用scrapy爬取前程无忧51job网站
- 从业20年的“老司机”跟你聊聊:超融合技术哪家强?!
- oul可以用作c语言常量吗,2016春北交《C语言程序设计(专) 》在线作业二
- 企业级实战大数据课程(十)-尹成-专题视频课程
- Sophos XG Firewall SFOS 18.0 下载 百度网盘