文章目录
1. 前端
我前端平时用vue,html、css和java script、jquery等都会一些,基本上都是现用先查,不太专业,前后端占比的话算是三比七吧,工作内容很多是写后端rest接口。
1.1 js == 和===区别?
a === b 是最简单的。如果 a 和 b 的类型不同,那么一定会返回 false。而 a == b 则要灵活得多。JavaScript 会尝试调整 a 和 b 的类型,例如若 a 为字符串 b 为数字,则将字符串先转化为数字再与 b 比较,等等。
除了判断 x == null,因为即将 x == null 是 x === null || x === undefined 的缩写
简而言之就是 " == " 只要求值相等; " === " 要求值和类型都相等
1.2 es6有什么新特性
- let、const定义变量
- ES6允许按照一定的模式从数组和对象中提取值,对变量进行赋值,称为解构赋值
const arr =['张学友','刘德华','黎明','郭富城'];let[zhang, liu, li, guo]= arr;// 内容中可以直接出现换行符let str =`<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;// 变量拼接 let lovest ='魏翔';let out =`${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
- 模板字符串
ES6 引入新的声明字符串的方式 ``--内容中可以直接出现换行符
变量拼接 ---语法:`${ 内容 }`// 内容中可以直接出现换行符let str =`<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;// 变量拼接 let lovest ='魏翔';let out =`${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
- 简化对象写法 ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
const school ={
name,// name : name, 简化成nameimprove(){// improve: function(){ 简化而来
console.log("我们可以提高你的技能");}}
- 箭头函数 : () => { }
- … 三个点扩展运算符
- 引入了Symbol数据类型 ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型。 Symbol 的值是唯一的,用来解决命名冲突的问题;Symbol 定义的对象属性不能计算和遍历 ,但是可以使用Reflect.ownKeys 来获取对象的所有键名 数据类型共有:undefined、string、symbol、object、null、number、boolean
2. 后端
2.1用的java版本是什么,有什么新特性
具体用的版本不清楚,反正大于java8(查了一下java8已经渐渐被java10/java11给镇压了,因为java11的G1垃圾收集器有更新的默认值和更高的性能)
java8的新特性:
- Java 8 语言中引入的一种新的语法元素和操作符 “->” , 该操作符被称为 Lambda 操作符或箭头操作符。它将 Lambda 分为两个部分: 左侧:指定了 Lambda 表达式需要的参数列表 右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即Lambda 表达式要执行的功能。
- Stream API Stream 和 Collection 集合的区别: Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。 Stream 的操作三个步骤
1- 创建 Stream
一个数据源(如:集合、数组),获取一个流
2- 中间操作
一个中间操作链,对数据源的数据进行处理,如filter() / distinct() / limit() / map()映射 / sorted()排序
3- 终止操作(终端操作)
一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
如allMatch、anyMatch()、findFirst()、count()、max(Comparator c)、forEach() 匹配与查找
reduce() collect()
- Optional 类 Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表 这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不 存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。
- 方法引用和构造器引用 语法 对象::方法名 或者 构造器引用 ClassName::new
- 函数式接口 只包含一个抽象方法的接口,称为函数式接口。 我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。 函数式接口与Lambda表达式的关系:在Java8中,Lambda表达式就是一个函数式接口的实例。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。
2.2JDK8对HashMap做了哪些优化?
- jdk8中添加了红黑树,当链表长度大于等于8的时候链表会变成红黑树
- 链表新节点插入链表的顺序不同(jdk7是插入头结点,jdk8因为要把链表变为红 黑树所以采用插入尾节点)
- hash算法简化 ( jdk8 )
- resize的逻辑修改(jdk7会出现死循环,jdk8不会)
2.3 BigDecimal怎么初始化?
dubbo num = 0.88;
BigDecimal b = new BigDecimal(num); //存在精度确实风险,容易导致业务逻辑异常
优先推荐入参为 String 的构造方法,或使用 BigDecimal 的 valueOf 方法,其实valueOf底层调用的还是toString方法
2.4 spring版本? aop ioc 两个概念怎么解释?
IOC
:控制反转也叫依赖注入,IOC利用java反射机制,AOP利用代理模式。所谓控制反转是指,本来被调用者的实例是由调用者来创建的,这样的缺点是耦合性太强,IOC则是统一交给spring来管理创建,将对象交给容器管理,你只需要在spring配置文件总配置相应的bean,以及设置相关的属性,让spring容器来生成类的实例对象以及管理对象。在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的时候,就把它已经初始化好的那些bean分配给你需要调用这些bean的类。
AOP
:面向切面编程。(Aspect-Oriented Programming)
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码,属于静态代理。
2.5 springBoot项目是怎么 启动的?
第一种启动方式 @EnableAutoConfiguration
@EnableAutoConfiguration 作用是开启自动装配,帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot,并创建对应配置类的Bean,并把该Bean实体交给IoC容器进行管理。
第二种启动方式 @ComponentScan
@ComponentScan() 注解作用:根据定义的扫描路径,将符合规则的类加载到spring容器中,比如在类中加入了以下注解 @Controller、@Service、@Mapper 、@Component、@Configuration 等等;
2.6 如何通过aop进行统一异常处理
我们写的代码难免有些运行错误,通常情况下,我们需要对错误进行包装,不能直接返回异常信息发给前端。
但是我们的前端很容易臃肿,我们可以使用AOP来解决这种问题
(1)环境配置
在pom.xml中添加依赖的包
写一个切换的处理类,加上@Aspect注解,重写before() / Around / AfterReturning 等方法
2.7 事务在service层配置后controller层生效吗?事务失效的情况
事务一般用@Transactional注解加在Service层方法中,如果controller只调用一个service事务,肯定可以回滚,但是如果同时调用两个以上方法就不会回滚
事务失效的情况
- 访问权限问题 @Transactional注解的方法如果要生效必须声明成public类型的
- 方法用final修饰 spring事务底层使用了aop,也就是通过jdk动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,而无法添加事务功能。
注意:如果某个方法是static的,同样无法通过动态代理,变成事务方法
- 方法内部调用 如果在某个Service类的某个方法中,调用另外一个事务方法,即在同一个类中的方法直接内部调用,事务会失效。 看下面代码,大家思考一个问题:当外部直接调用m1的时候,m2方法的事务会生效么?
@Component
publicclassUserService{publicvoidm1(){this.m2();}
@Transactional
publicvoidm2(){//执行db操作}}
显然不会生效,因为m1中通过this的方式调用了m2方法,而this并不是代理对象,this.m2()不会被事务拦截器,所以事务是无效的,如果外部直接调用通过UserService这个bean来调用m2方法,事务是有效的,上面代码可以做一下调整,如下,在UserService中注入了自己(或者在该Service类中使用AopContext.currentProxy()获取代理对象),此时m1中的m2事务是生效的
@Component
publicclassUserService{
@Autowired //这里注入了自己private UserService userService;publicvoidm1(){this.userService.m2();}
@Transactional
publicvoidm2(){//执行db操作}}
- 未被spring容器管理 使用spring事务的前提是:对象要被spring管理,需要创建bean实例。通常情况下,我们通过@Controller、@Service、@Component、@Repository等注解,可以自动实现bean实例化和依赖注入的功能。如果类未被 Spring 管理,事务自然就失效了。
- 多线程调用 如果看过spring事务源码的朋友,可能会知道spring的事务是通过数据库连接来实现的。当前线程中保存了一个map,key是数据源,value是数据库连接。
private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>(“Transactional resources”);
我们说的同一个事务,其实是指同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。如果在不同的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务。
6. 异常类型错误
并不是任何异常情况下,spring都会回滚事务,默认情况下,RuntimeException和Error的情况下,spring事务才会回滚。
通过try catch把异常捕获到处理了也不会回滚。
8.
3. 持久层框架及Linux命令
3.1 hibernate 与mybatis优缺点
1、开发上手难度
Hibernate的真正掌握(封装的功能和特性非常多)要比Mybatis来得难。
在真正产品级应用上要用Hibernate,不仅对开发人员的要求高,hibernate往往还不适合(多表关联查询等)。
2、SQL优化方面
Hibernate使用的是封装好,通用的SQL来应付所有场景,而Mybatis是针对响应的场景设计的SQL。Mybatis的SQL会更灵活、可控性更好、更优化。
3、移植性
Hibernate与具体数据库的关联只需在XML文件中配置即可,所有的HQL语句与具体使用的数据库无关,移植性很好。
MyBatis项目中所有的SQL语句都是依赖所用的数据库的,所以不同数据库类型的支持不好。
4、JDBC
Hibernate是在JDBC上进行了一次封装。
Mybatis是基于原生的JDBC的。Mybatis有运行速度上的优势。
5、功能、特性丰富程度
Hibernate提供了诸多功能和特性。要全掌握很难。
Mybatis 自身功能很有限,但Mybatis支持plugin,可以使用开源的plugin来扩展功能。
6、动态SQL
Mybatis mapper xml 支持动态SQLHibernate不支持
实际项目关于Hibernate和Mybatis的选型:(背下来吧)
1、数据量:有以下情况最好选用Mybatis
如果有超过千万级别的表
如果有单次业务大批量数据提交的需求(百万条及以上的),这个尤其不建议用Hibernate
如果有单次业务大批量读取需求(百万条及以上的)(注,hibernate多表查询比较费劲,用不好很容易造成性能问题)
2、表关联复杂度
如果主要业务表的关联表超过20个(大概值),不建议使用hibernate
3、人员
如果开发成员多数不是多年使用hibernate的情况,建议使用mybatis
4、数据库对于项目的重要程度
如果项目要求对于数据库可控性好,可深度调优,用mybatis
3.2 mybatis框架如何实现一对多查询
3.3 hibernate支持原生sql吗
Hibernate提供了原生的SQL语句的查询,通过createNativeQuery(String)
//查询指定的列
List<Object[]> list = session.createNativeQuery("select actor_id as actorId,first_name as firstName from actor")
.setFirstResult(0)
.setMaxResults(5)
.list();
3.4数据懒加载
3.4linux查看端口号命令
$
telnet 10.4.200.114 8500
(我答错了,答的netstat,感觉要从简历上删掉Linux命令了,都是用的时候查的,接触的少记不住)
netstat -tln 查看端口使用情况,而netstat -tln | grep 8088 则是只查看端口8083的使用情况
3.4查询.log结尾文件
$ find -name “*.log”
4. 非技术话题
英语学习,是否能适应英文办公环境
是否能适应全栈开发,他们公司项目部门由前后端分离,但是基本上还是一人搞定前后端
最近项目比较忙,好像这个面试约的时间不太合适,微信视频面试的,楼下的蚊子太多了 我好像还是很多知识停留在会用阶段说不清楚哪个技术哪个版本做了什么优化,其实工作这么多年了这些已经不够用了,还得多学习啊,这家公司没戏了,等着下次机会吧。
版权归原作者 举杯同庆 所有, 如有侵权,请联系我们删除。