JAVA 面试题真题解析(3)AGREE TECH

JAVA 面试题真题解析(3)AGREE TECH

北京赞同科技 AGREE TECHNOLOGY 面试题分析

简答题

一、Spring MVC 执行流程

  • 用户发送请求至前端控制器 DispatcherServlet。
  • DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。
  • 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
  • DispatcherServlet调用HandlerAdapter处理器适配器。
  • HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
  • Controller执行完成返回ModelAndView。
  • HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
  • DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  • ViewReslover解析后返回具体View。
  • DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  • DispatcherServlet响应用户。

请求 -> Controller 接收 -> 调用 Model 处理 -> Controller 接收处理结果 -> 交给 View 视图渲染 -> 响应给用户

二、解释 Spring MVC 常用注解的作用

  1. @Controller 注解
  2. @RequestMapping 注解
  3. @RequestParam 注解
  4. @RequestBody 注解
  5. @PathVariable 注解 (真题字都打错了,gg)
  6. @RequestHeader 注解
  7. @CookieValue 注解
  8. @SessionAttributes 注解
  9. @ModelAttribute 注解(可恶,真题少打个d,还以为这是什么吊词)

答案参考:

  • @Controller – 用在类上面,用于申明该类是一个 Controller对象,即控制器 Bean。
  • @RequestMapping – 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
  • @RequestParam – 将请求参数绑定到你控制器的方法参数上(是springmvc中接收普通参数的注解)
  • @RequestBody – 用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的),所以只能发送POST请求。一个请求,只有一个RequestBody。
  • @PathVariable – 是用来赋予请求url中的动态参数。即:将请求URL中的模板变量映射到接口方法的参数上。
  • @RequestHeader – 该注解方便我们获取请求头信息。
  • @CookieValue – 该注解主要是将请求的 Cookie 数据映射到功能处理方法的参数上。
  • @SessionAttributes – 可以通过属性名指定需要放到会话中的属性,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中。
  • @ModelAttribute – 注释的方法会在此 controller 每个方法执行前被执行。

三、列举常用 java 代码编辑器有哪些?并简要说明各个编译器的优势。

  • Idea 目前最常用的开发软件,拥有强大的整合能力:比如 Git、Maven、Spring 等。并且拥有强大的代码检查功能,功能提示的范围广,速度快。完全支持 JSP、XML、JUnit、EJB等。精准搜索强大。自动保存。
  • Eclipse 开源,免费,有中文版,上手较快,软件本体占用资源小,有可无限扩展的强大插件功能。从编写、查错、编译、帮助等方面非常适合 JAVA 开发。
  • Notepad++ 性能强,功能多,轻便随时可用。
  • VSCode 性能好,占用资源少,功能可以无限拓展,有代码追踪功能,界面美观。

四、两张表:A表,B表,A 表和 B 表两张表所有属性和数据相同,实现

  1. A 表主键 A_id,B 表主键 B_id。
  2. A 表变化时同步 B表,当 B 表没有 A 表数据时插入反之更新。

五、常见异常有哪些、如何解决?

  • NullPointerException(空指针异常):

    所谓指针是指 Java 中对象的引用,空指针即为对象的内容为空。空指针异常就是该对象为空,还要去操作它,这个时候会报异常。解决方法,可以根据报错信息找到发生错误的行,检查其中有可能发生错误的变量,输出打桩检查变量的值。

  • ClassNotFoundException(指定类不存在异常)

  • IndexOutOfBoundsException(数组下标越界异常)

  • IllegalArgumentException(方法的参数异常)

  • ClassCastException(数据类型转换异常)

  • FileNotFoundException(文件无法找到异常)

  • NoSuchElementException(缺少方法异常)

  • ArithmeticException(数学运算异常)

  • NoClassDefFoundError(未找到类定义错误)

  • 异常处理,不要丢弃异常,可以用 try-catch 捕获异常,然后对异常进行处理,在 catch 语句中应该指定具体的异常类型,并在 finally 里面释放资源。

六、NoClassDefFoundError 和 ClassNotFoundException 的区别。

首先,ClassNotFoundException 是一个继承自 Exception 的检查异常,而 NoClassDefFoundError 是一个继承自 Error 的错误,父类不同。

其次,ClassNotFoundException 是一个可检测异常,NoClassDefFoundError 是一个致命错误。

ClassNotFoundException 强调运行时无法匹配到指定参数名称的类,NoClassDefFoundError 强调编译时没问题,运行时却无法实例化一个类。

七、列举能够导致数据库慢查询的情况,并说明如何避免。

  1. 应用的问题
    • 数据库表设计不合理,该加索引的没加索引。---- 根据需求添加索引减少查询压力。
    • SQL 语句编写不合理。---- 改进 SQL 语句,避免不必要的查询。
    • JOIN 的表过多。---- 可尝试分批查询或者添加索引减少 JOIN 的表数量。
    • 数据库中的表单的数据量过大。---- 可以考虑分库分表的方式来解决。
    • 程序异常导致大量数据库连接不能释放,一直被占用。---- 查看占用情况,及时释放不必要的连接。
  2. 数据库的问题
    • 连接池资源不够用了。---- 优化参数,增加连接池资源分担查询压力。
    • 硬件资源不足,内存占用过大,磁盘性能不足的等。---- 提升硬件资源,若有和其他进程共享的情况导致资源不够的情况可以考虑做资源隔离。
    • 网络资源存在波动,延迟较高。---- 检查网络波动,及时与运营商沟通修复。
  3. 请求量过大
    • 用户请求激增,导致查询变慢。---- 考虑在系统上增加限流功能缓解数据库访问压力。
    • 数据量过于庞大,分库分表仍不能解决。---- 增加缓存模块,例如将热点数据在 redis 做缓存。

八、Linux 常用命令有哪些?

目录切换:cd 目录

帮助命令:–help

目录查看:ls /ls -a /ls -l /ls /dir

创建目录:mkdir xxx

删除目录或文件:rm -f xxx

全部删除:rm -rf *

查看当前路径:pwd

修改文件名:mv aaa bbb

移动文件:mv aaa /user

复制文件:cp aaa test

显示整个文件:cat aaaa

浏览文件:more/less

查看文档开头:head

查看文档结尾:tail

程序名搜索:whereis

改变权限:chmod a+x aaa

显示时间:date

文本全局搜索:grep

九、简单表述数据库中 join 的 left join,inner join,cross join 。

  • left join:左连接,返回左表的所有记录以及右表中连接字段相等的记录。
  • inner join:内连接(等值连接),只返回两个表中连接字段相等的行。
  • cross join:结果是笛卡尔积,两个表内的所有记录,第一个表行数乘以第二个表的行数。

操作题

一、请写出两个线程交替打印出 100 以内的奇数和偶数。

两种方式参考:

    //方式一: synchronized 关键字实现,缺点:效率低private static Object lock = new Object();private static int i = 1;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {while (i < 100) {synchronized (lock) {if ((i & 1) == 1) {System.out.println(i + "是奇数");i++;}}}});Thread t2 = new Thread(() -> {while (i < 100) {synchronized (lock) {if ((i & 1) == 0) {System.out.println(i + "是偶数");i++;}}}});t1.start();;t2.start();}
    //方式二:wait/notify() 阻塞唤醒,奇线程打印完成阻塞自己,偶线程打印完唤醒被阻塞的进程,同时阻塞自己//此方式,效率高。private static Object lock = new Object();private static int i = 1;public static void main(String[] args) {Thread t1 = new Thread(() -> {for (; i <= 100; ) {synchronized (lock) {System.out.println(i++ + ":我是偶数");try {lock.notify();if (i <= 100) {lock.wait();}} catch (InterruptedException e) {e.printStackTrace();}}}});Thread t2 = new Thread(() -> {for (; i <= 100; ) {synchronized (lock) {System.out.println(i++ + ":我是奇数");try {if (i <= 100) {lock.wait();}lock.notify();} catch (InterruptedException e) {e.printStackTrace();}}}});t2.start();t1.start();}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部