• Java面试题练习第一套(包含参考答案)


    注意:答案并不是标准答案,这个答案是基于我本人自己对相关知识点多理解,仅供参考!如果有错误,欢迎各位小伙伴指正。本篇博客是用于记录个人的学习的。

    目录

    写SQL

    Java容器

    线程池

    spring

    单例模式

    web

    数据库中的varchae char text

    并发相关的知识

    问题+答案

    写SQL

    Java容器

    线程池

    spring

    单例模式

    web

    数据库中的varchae char text

    并发相关的知识

     

    问题:

    写SQL

    1.创建一张User表,字段为Id(自增主键),name(不能为空),createTime(创建时间),sex(性别),idCard(身份证,唯一),age(年龄),score(分数)

    2.插入一张用户名为小明,性别为男,身份证为123465789012345678,年龄18,分数88,创建时间为服务器当前时间的数据

    3.查询性别为男同时年龄大于18,根据id降序排序的第5到第10条记录(包含第五条和第十条)。

    4.查询各个年龄的男生所获得的分大于80的人数,若其中某一性别所有人分数低于80则需要显示该年龄性别人数为0。

    Java容器

    1.描述你所了解的容器集合,它们的特性是什么?(例如,HashMap,是否线程安全,是否允许数据为NUll,是否允许数据重复,数据是否有序等等)

    线程池

    2.创建一个线程池需要传递哪些参数,各个参数的意义是什么?线程池的运行机制是怎样的?

    spring

    3.Spring框架的特性与功能有哪些?

    单例模式

    4.写出两种线程安全的单例模式。

    web

    1.Controller层、Service层Dao层各自的作用,数据在从页面到数据库这个过程中的传递流程。

    2.分层领域模型里,DO 、AO、VO 各自存储了哪些东西,或者说分层的规则是什么?

    3.讲一下拦截器和监听器

    数据库中的varchae char text

    1.Varchar和char和text的区别

    2.Varchar(20) 与text(20)的区别

    并发相关的知识

    1.ConcurrentHashMap底层的锁机制

    2.Synchronized的运行机理

    3.Synchronized和Lock的区别

    4.JVM底层字符编码是什么?

     

    问题+答案

    写SQL

    1.创建一张User表,字段为Id(自增主键),name(不能为空),createTime(创建时间),sex(性别),idCard(身份证,唯一),age(年龄),score(分数)

    1. create table User
    2. (id int primary key auto_increment,-- 这个约束条件有两种书写方式,这里使用的是直接在字段后面进行约束
    3. name varchar(20) not null , -- 注意这里没有is 不是 is not
    4. createTime datetime, -- 时间的格式要注意一下啊,你至少要知道MySQL中有哪些时间类型吧
    5. sex varchar(1),
    6. idCard varchar(30) unique, -- 创建表中的字段,是先写字段的名称 再写字段的数据类型,然后再写约束!!
    7. age int,
    8. score int -- 字段间使用逗号隔开,最后结尾的字段不需要再使用逗号了
    9. )

    补充:

    ddd2b0c6aa8741b1bf5e84f951fb3c65.png

     

    2.插入一张用户名为小明,性别为男,身份证为123465789012345678,年龄18,分数88,创建时间为服务器当前时间的数据

    insert into user (name,sex,idCard,age,score,createTime) values ('小明','男','123465789012345678',18,88,now());   -- 注意:插入当地的系统时间使用的now() 函数!!!

    补充:在数据库中所有的字符串类型,必须使用单引号

    插入数据SQL语法:insert into 表名称 values (值1,值2,······)

    修改SQL语句的语法:UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值

    例子:update Student set name = 'lisi',sex='男' where id=1

     

    3.查询性别为男同时年龄大于18,根据id降序排序的第5到第10条记录(包含第五条和第十条)。

    1. select * from user where age > 18 and sex = '男' order by id desc limit 4,9
    2. -- 注意:这个limit后面的分页【是不加括号的】!!!

    4.查询各个年龄的男生所获得的分大于80的人数,若其中某一性别所有人分数低于80则需要显示该年龄性别人数为0。

    1. select sum(if(sex = '男',1,0)) from user where sex = '男' and score > 80
    2. -- 这里主要考察MYSQL中的if函数的使用 用到了sum求和,if函数的判断

    Java容器

    1.描述你所了解的容器集合,它们的特性是什么?(例如,HashMap,是否线程安全,是否允许数据为NUll,是否允许数据重复,数据是否有序等等)

    本人做答:

    arrayList ,linkedList ,vector, hashMap ,hashSet,hashtable 等

    上面只有vector,hashtable是线程安全的,其他都是线程不安全的,通过观察源码,发现 Vector 类中的大部分方法都是由 synchronized 关键字来修饰的,hashTable也是用synchronized关键字保证线程安全,对所有的读写操作都进行了锁保护,所以也是线程安全的;

    arrayList 允许数据重复,数据都是有序的(arraylist底层是数组,数组存储是连续的,所以存储的是‘有序的’);

    linkedList:有序且可重复;底层是链表,它的数组遍历速度慢,但增删速度很快

    hashmap中是无序的,也是不能重复的,key和value可以为null ;

    (HashMap在put的时候会调用hash()方法来计算key的hashcode值,可以从hash算法中看出当key==null时返回的值为0。因此key为null时,hash算法返回值为0,不会调用key的hashcode方法。)

    hashset不允许数据重复,并且数据是无序的;(hashset的底层维护的就是一个hashMap)

    hashTable的key和value都不可以为null;

    (源码显示:Hashtable存入的value为null时,抛出NullPointerException异常。如果value不为null,而key为空,在执行到int hash = key.hashCode()时同样会抛出NullPointerException异常)

    补充:

    b48519eca0784fabb27e93070dc47183.png

    如上图所示,集合分为两大类(Collection与Map),其中List接口与Set接口是Collection众多子接口中的 两个。也可以说JAVA集合分为三大类---List、Set、Map。但是这几个接口各有特点:

    • Collection接口储存的数据无序且数据可重复

    • List接口存储的数据有序且数据可重复

    • Set接口储存的数据无序但数据不可重复

    • Map接口可以存储一组键值对象,提供key到value的映射。key唯一(不可重复)无序,value不唯一(可重复)无序

     

    线程池

    2.创建一个线程池需要传递哪些参数,各个参数的意义是什么?线程池的运行机制是怎样的?

    如果是选择最多构造参数的构造方法来创建线程池的话,那么需要到的参数有:

    最大线程数:就是线程池中允许存在的最大线程数量(为核心线程数加救急线程数);

    核心线程数:正常工作的线程数;

    救急线程的存活时间:救急线程产生后,阻塞队列的任务被执行得差不多了,此时不再需要救急线程也可以处理请求任务,那么这个救急线程的活跃存活时间就是这个参数,核心线程是没有这个参数的;

    时间的单位:救急线程保持活跃时间的时间单位;

    线程工厂:线程工厂,线程池中的线程的来源

    阻塞队列:当核心线程的处理力度达到了最大,此时再来任务请求使用线程,那么此时这些请求任务就需要被阻塞在一个队列中,这个就是定义这个阻塞队列

    拒绝策略:阻塞队列也满了,此时不再接受请求的任务,这个参数是提供了一个拒绝的策略;

    ddc00ed3bff6443bb4785d2036c693c7.png

     

    spring

    3.Spring框架的特性与功能有哪些?

    spring的两大特性是:IOC,AOP

    IOC:Inversion of Control,也叫控制反转,是把创建对象的控制权交给spring 容器来完成,开发人员只需要把要创建的对象的信息给配置好就行(以前是经常使用xml来配置bean的元信息,现在一般是通过注解加Java编程的形式来配置),这样做的好处是可以减少同一个类的对象大量存在内存中,可以减少内存开销;

    IOC常见的方式是:依赖注入(DI), 就是 容器动态的将某种依赖关系注入到组件中;常见的两种方式是ByType 和ByName, 一般都是使用注解@autowire来实现自动注入的(这个是bytype)

     

    AOP:是面向切面编程,是ioc的一种增强,是通过动态代理对功能进行增强;

    AOP 主要用来解决:在不改变原有业务逻辑的情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。

    应用场景:

    • 记录日志

    • 自定义注解配合实现基础属性数据的初始化(比如:创建时间,修改时间等)

    • 权限控制(类比一下spring security)

    • 缓存优化 (第一次调用查询数据库,将查询结果放入【内存】对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 )

    • 事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 )

    补充:

    IoC(Inverse of Control:控制反转)是一种设计思想 或者说是某种模式,IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。

    单例模式

    4.写出两种线程安全的单例模式。

    1.双重检索

    1. public class Singleton {
    2. public static volatile Singleton singleton;
    3. public Singleton (){
    4. }
    5. public static Singleton getSingleton (){
    6. if(singleton==null){
    7. synchornized(Singleton.class){
    8. if(singleton==null){
    9. return new Singleton();
    10. }
    11. }
    12. }
    13. return singleton;
    14. }
    15. }

    理解:在创建第一个对象时候,可能会有线程1,线程2两个线程进入getInstance()方法,这时对象还未被创建,所以都通过第一层check。接下来的synchronized锁只有一个线程可以进入,假设线程1进入,线程2等待。线程1进入后,由于对象还未被创建,所以通过第二层check并创建好对象,由于对象singleton是被volatile修饰的,所以在对singleton修改后会立即将singleton的值从其工作内存刷回到主内存以保证其它线程的可见性。线程1结束后线程2进入synchronized代码块,由于线程1已经创建好对象并将对象值刷回到主内存,所以这时线程2看到的singleton对象不再为空,因此通过第二层check,最后获取到对象。这里volatile的作用是保证可见性,同时也禁止指令重排序;

    2.使用静态内部类:

    1. public class Singleton {
    2. private Singleton() {
    3. }
    4. public static Singleton getInstance() {
    5. return SingletonFactory.instance;
    6. }
    7. private static class SingletonFactory {
    8. private static Singleton instance = new Singleton();
    9. }

    静态内部类只有被主动调用的时候,JVM才会去加载这个静态内部类。外部类初次加载,会初始化静态变量、静态代码块、静态方法,但不会加载内部类和静态内部类。

    静态内部类可能还存在反射攻击和反序列化攻击。

     

    web

    1.Controller层、Service层Dao层各自的作用,数据在从页面到数据库这个过程中的传递流程。

    ①Controller层:业务控制层,负责接收(接受前端传过来的数据)返回(把从数据库查询和经过service处理的数据返回给前端)数据和请求(可以通过url映射接受到浏览器的请求),并且调用Service层实现这个业务逻辑。

    ②Service层:又叫服务层或业务层,封装Dao层的操作,使一个方法对外表现为实现一种功能,例如:网购生成订单时,不仅要插入订单信息记录,还要查询商品库存是否充足,购买是否超过限制等等。

    ③Dao层:负责与数据库打交道具体到对某个表、某个实体的增删改查

    个人理解的过程:

    浏览器在地址栏发送携带数据的请求或者是单纯的查询请求,此时通过MVC的URL映射可以在controller层接受到相关的请求,controller会对传递过来的数据在service层进行业务上的加工,service对数据的操作由是基于dao层,dao负责对数据库中的数据进行增删改查;

     

    2.分层领域模型里,DO 、AO、VO 各自存储了哪些东西,或者说分层的规则是什么?

    DO:(Data Object)阿里巴巴开发规范中对此介绍,此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。

    AO:(ApplicationObject)应用对象,在Web层与Service层之间抽象的复用对象模型, 极为贴近展示层;

    VO:(Value Object)值对象,VO就是展示用的数据,不管展示方式是网页,还是客户端,还是APP,只要是这个东西是让人看到的,这就叫VO,VO主要的存在形式就是js里面的对象(也可以简单理解成json)

    想要了解更多可以查看此博客参考:阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义_mildness丶的博客-CSDN博客_vo和po的区别

     

    3.讲一下拦截器和监听器

    拦截器是spring提供的一个组件,只有在spring项目中才可以使用拦截器,拦截器它是链式调用,一个应用中可以同时存在多个拦截器Interceptor, 一个请求也可以触发多个拦截器 ,而每个拦截器的调用会依据它的声明顺序依次执行。要使用拦截器,首先编写一个简单的拦截器处理类,请求的拦截是通过HandlerInterceptor 来实现,HandlerInterceptor 接口中也定义了三个方法:

    • preHandle() :这个方法将在请求处理之前进行调用。注意:如果该方法的返回值为false,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。

    • postHandle():只有在 preHandle()方法返回值为true 时才会执行会在Controller 中的方法调用之【后】,DispatcherServlet 返回渲染视图之前被调用。

    • afterCompletion():只有在 preHandle()方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。

    监听器的作用是监听一些事件的发生从而进行一些操作比如监听ServletContext,HttpSession的创建,销毁,从而执行一些初始化加载配置文件的操作,当Web容器启动后,Spring的监听器会启动监听,监听是否创建ServletContext的对象,如果发生了创建ServletContext对象这个事件(当web容器启动后一定会生成一个ServletContext对象,所以监听事件一定会发生),ContextLoaderListener类会实例化并且执行初始化方法,将spring的配置文件中配置的bean注册到Spring容器中;

     

    数据库中的varchae char text

    1.Varchar和char和text的区别

    varchar(n) 是可变长度;

    varchar(n)类型用于存储【可变长】的,长度最大为n个字符的可变长度字符数据。比如varchar(10), 然后输入abc三个字符,那么实际存储大小为3个字节。

    char(n) 是定长度,最大为255 ;

    char类型是【定长】的类型,即当定义的是char(10),输入的是"abc"这三个字符时,它们占的空间一样是10个字符,包括7个空字节

    text也是可变长度,但是text不能设置默认值,varchar可以;

    2.Varchar(20) 与text(20)的区别

    相同点都是可变字符;

    不同点:不太知道。。。。

     

    并发相关的知识

    1.ConcurrentHashMap底层的锁机制

    jdk1.7及之前:

    • 对数据加了volatile关键字使所有数据在内存中都是可见的。

    • 使用了分段锁结合重入锁ReentrantLock来保证线程安全, 数据结构:数组+链表(链表的遍历速度是o(n))。

    会出现的问题:当并发执行扩容操作会出现环形链表和数据丢失的情况(因为此版本的hash表使用的是头插法);

    即Segment(段)+HashEntry+ReentrantLock

    09463a3aa1cb41218d4cde55ee40da9a.png

    jdk1.8及之后:

    • 对数据加了volatile关键字使所有数据在内存中都是可见的。

    • 主要利用Unsafe中的CAS操作和synchronized关键字来保证线程安全, 数据结构变成了数组+链表+红黑树(可以提高查询的速度,查询速度变成了olog(n))。

    即Node(首节点) + CAS + Synchronized

    f7638d9fa45a46e7bc3dc18970a04e52.png 注意:

    JDK1.8实现降低了锁的粒度,JDK1.7版本锁粒度是基于segment,segment下包含多个hashentry的,而JDK1.8的锁的粒度是HashEntry(首节点);

     

    2.Synchronized的运行机理

    synchronized,是使用c语言写的一个Java关键字,俗称的【对象锁】,它采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】,其它线程再想获取这个【对象锁】时就会阻塞住。这样就能保证拥有锁的线程可以安全的执行临界区内的代码,不用担心线程上下文切换。

    synchronized的三个作用:

    原子性:确保线程互斥的访问同步代码 可见性:保证共享变量的修改能够及时刷回主存 有序性:有效解决指令重排序问题

    Synchronized在jdk1.6后完成优化后,使用Synchronized加锁jdk并不会一开始就直接使用重量级锁,而是拥有了锁膨胀的过程,根据具体的并发环境来完成锁膨胀,轻量级锁 , 偏向锁,重量级锁;锁的粒度更加细了;

    想要更加深入学习,可以参考博客:Java并发编程(中上篇)从入门到深入 超详细笔记_未来很长,别只看眼前的博客-CSDN博客

     

    3.Synchronized和Lock的区别

    • Synchronized是基于c语言开发的Java本地关键字,Lock是api层面的加锁;

    • Synchronized会在线程使用完锁后才会释放锁,或者是执行过程发生了异常,这个时候JVM会帮我们释放锁;

    lock锁的释放是需要开发人员手动释放的(lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。),一般是在finally中释放,否则容易发生死锁;

    • Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)

    • lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断;

    • Lock可以通过trylock来知道有没有获取锁,而synchronized不能;

    • Synchronized和lock都是可重入,但是Synchronized只有非公平锁,lock实现了公平和非公平(默认是非公平锁);

    • 在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized;这是因为:

      • synchronized采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。

      • 而Lock用的是乐观锁方式。乐观锁实现的机制是CAS操作(Compare and Swap)。进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。

    4.JVM底层字符编码是什么?

    暂时没学过...........

     

     

  • 相关阅读:
    Vue驾校-从项目学Vue-6
    OpenGL概述(核心模式与立即模式、扩展、OpenGL中的对象)
    HTTPS加密过程详解
    JavaScript-Object.is()和‘===’ ‘==’比较运算符的区别
    2022-08-16 数据库先验性记录
    数据结构与算法之LeetCode-515. 在每个树行中找最大值(DFS,BFS)
    SWT/ANR问题--Native方法执行时间过长导致SWT
    二叉树经典oj面试题
    高性能API云原生网关 APISIX安装与配置指南
    87、Redis 的 value 所支持的数据类型(String、List、Set、Zset、Hash)---->List相关命令
  • 原文地址:https://blog.csdn.net/weixin_53142722/article/details/125287034