2023-4-13美团测开二面

1. 自我介绍#

2. 写项目的背景是什么#

3. 为什么使用SpringCloud,主要适用于哪些功能#

4. 为什么用MongoDB#

5. MongoDB和Redis哪个更快#

6. 拷贝数组有几种方式,哪种方式效率更高#

效率从高到低: System.arraycopy 、 clone 、 (Arrays.copyOf、Arrays.copyOfRange) 、 for循环。

7. Integer t1 = 128; Integer t2 = 128; sout(t1==t2)#

Integer的值为-128-127之间的时候就会自动的从Integer的缓存(IntegerCache)中去取,如果超过这个范围就会新建一个Integer的对象。

  所以a==b(a=10,b=10)为true,c==d(c=150,d=150)为false。

nteger的值为-128-127的时候用==会返回true 不再这个区间要用equals才会返回true

8. Java8中最大化减少空指针的产生?#

Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。
Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在 则isPresent()方法会返回true,调用get()方法会返回该对象。

创建Optional类对象的方法:

Optional.of(T t) : 创建一个 Optional 实例,t必须非空;
Optional.empty() : 创建一个空的 Optional 实例
Optional.ofNullable(T t):t可以为null

判断Optional容器中是否包含对象:

boolean isPresent() : 判断是否包含对象
void ifPresent(Consumer consumer) :如果有值,就执行Consumer 接口的实现代码,并且该值会作为参数传给它。
获取Optional容器的对象:

T get(): 如果调用对象包含值,返回该值,否则抛异常
T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。
T orElseGet(Supplier other) :如果有值则将其返回,否则返回由 Supplier接口实现提供的对象。
T orElseThrow(Supplier exceptionSupplier) :如果有值则将其返 回,否则抛出由Supplier接口实现提供的异常。

Copy Highlighter-hljs
public class OptionalTest { @Test public void test() { //创建 Optional Girl girl = new Girl(); Optional<Girl> girl1 = Optional.of(girl); } @Test public void test2() { //创建 Optional Girl girl = new Girl(); girl = null; Optional<Girl> girl1 = Optional.ofNullable(girl); //如果当前这个 Optional内部封装的t是非空的,则返回内部的t //如果内部的t是空的,则返回prElse 方法的参数t1 Girl girl2 = girl1.orElse(new Girl("赵丽颖")); System.out.println(girl2); } public String getGirlName(Boy boy) { return boy.getGirl().getName(); } public String newGetGirlName(Boy boy) { Optional<Boy> boyOptional = Optional.ofNullable(boy); //此时的 boy1 一定非空 Boy boy1 = boyOptional.orElse(new Boy(new Girl("乃林"))); Girl girl = boy1.getGirl(); Optional<Girl> girl1 = Optional.ofNullable(girl); //此时的 girl2 一定非空 Girl girl2 = girl1.orElse(new Girl("嘉然")); return girl2.getName(); } public String oldGetGirlName(Boy boy) { if (boy != null) { Girl girl = boy.getGirl(); if (girl != null) { return girl.getName(); } } return null; } @Test public void test3() { Boy boy = new Boy(); String girlName = getGirlName(boy); System.out.println(girlName); } @Test public void test4() { Boy boy = new Boy(); boy = null; String girlName = oldGetGirlName(boy); System.out.println(girlName); } @Test public void test5() { // boy 为null 返回乃琳 // boy的参数 girl为null 返回嘉然 //如果正常 就返回 正常参数 Boy boy = new Boy(new Girl("林志玲")); //boy = null; String girlName = newGetGirlName(boy); System.out.println(girlName); } }

9. 反射的应用场景#

  • 反射实现驱动加载 Class.forName("com.mysql.cj.jdbc.Driver");
  • 反射实现配置文件加载
  • 反射实现工厂模式
  • 反射实现静态代理
  • 反射实现动态代理

创建一个要调用的接口实现,获取接口实现的Class。

实现InvocationHandler接口并重写invoke方法,实例化InvocationHandler对象,用来处理 Proxy 的方法调用。

通过Proxy.newProxyInstance(classLoader, interfaces, proxyHandler);实例化一个 proxy 对象。

10. 代码中一个方法使用了很多try-catch、如何优雅的减少try-catch的个数#

@ControllerAdvice可以把异常处理器应用到所有控制器,而不是单个控制器。借助该注解,我们可以实现:在独立的某个地方,比如单独一个类,定义一套对各种异常的处理机制,然后在类的签名加上注解@ControllerAdvice,统一对 不同阶段的、不同异常 进行处理。这就是统一异常处理的原理。

减少 try catch ,可以这样干_异常处理_03

11. springboot中如何获取Service实例#

使用ApplicationContextAware

此方法直接实现了ApplicationContextAware接口,调用Spring提供的applicationContext,将所有在Spring中有注解的类,均可通过getBean方式获取到.

12. 拦截器和过滤器的区别#

1、过滤器 (Filter)#

过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。

  • init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。
  • doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。
  • destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次

2、拦截器 (Interceptor)#

拦截器它是链式调用,一个应用中可以同时存在多个拦截器Interceptor, 一个请求也可以触发多个拦截器 ,而每个拦截器的调用会依据它的声明顺序依次执行。

首先编写一个简单的拦截器处理类,请求的拦截是通过HandlerInterceptor 来实现,看到HandlerInterceptor 接口中也定义了三个方法。

  • preHandle() :这个方法将在请求处理之前进行调用。注意:如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。
  • postHandle():只有在 preHandle() 方法返回值为true 时才会执行。会在Controller 中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用。 有意思的是:postHandle() 方法被调用的顺序跟 preHandle() 是相反的,先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。
  • afterCompletion():只有在 preHandle() 方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。
  • 将自定义好的拦截器处理类进行注册,并通过addPathPatterns、excludePathPatterns等属性设置需要拦截或需要排除的 URL。
Copy Highlighter-hljs
@Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**"); } }

不同#

  • 过滤器和拦截器 底层实现方式大不相同过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。

  • 使用范围不同 我们看到过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。而拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于Application、Swing等程序中。

  • 触发时机不同过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。

    拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。

    img

  • 拦截的请求范围不同 执行顺序 :Filter 处理中 -> Interceptor 前置 -> 我是controller -> Interceptor 处理中 -> Interceptor 处理后。过滤器Filter执行了两次,拦截器Interceptor只执行了一次。这是因为过滤器几乎可以对所有进入容器的请求起作用,而拦截器只会对Controller中请求或访问static目录下的资源请求起作用。

13. 双亲委派是为了解决什么问题#

双亲委派机制是 Java 类加载器的一种实现方式,其核心思想是在类加载器之间建立一种父子关系,父类加载器加载的类能够被子类加载器使用,而子类加载器加载的类不能被父类加载器所使用。具体来说,当一个类需要被加载时,先由当前类的加载器去搜索类,如果没找到,就会委托给父类加载器去搜索,依次往上,直到达到顶层的启动类加载器,如果还没有找到就会抛出 ClassNotFoundException 异常。
双亲委派机制的好处主要有以下几点:

  1. 避免类的重复加载:在 JVM 中,每个类都由一个唯一的全限定名和一个对应的类加载器确定,类加载器根据全限定名和类路径来确定类的位置。因此,在一个 JVM 实例中,如果有两个类加载器分别加载了同一个类,JVM 会认为这两个类是不同的,从而导致类型转换异常等问题。通过双亲委派机制,父类加载器在加载类之前会先委托给自己的父类加载器去加载,从而保证一个类在 JVM 中只会有一份,并且由其父类加载器所加载。
  2. 安全性考虑:Java 核心类库(如 java.lang 包下的类)都是由启动类加载器加载的,其他的类都是由其它类加载器加载的。这样,我们就可以保证 Java 核心类库的安全性,因为不同的应用程序无法改变这些类的实现。另外,也可以在类加载过程中做一些安全性检查。
  3. 模块化开发:在实际应用中,我们经常需要在一个程序中使用多个第三方库,这些库可能会存在同名类。如果使用了双亲委派机制,就可以保证不同的类加载器只会加载自己的类,从而避免了类名冲突的问题。
posted @   Firewooood  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示
CONTENTS