热门面试题

Transactional失效场景

  • 没有将使用该注解的类交给Spring管理,也就是该对象不是bean对象。
  • @Transactional 应用在非 public 修饰的方法上
  • 同一个类中方法之间的调用,导致 @Transactional 失效 原因:spring的事务是通过aop实现的。
  • 异常在方法内部使用 catch 捕捉了,而catch语句块没有throw new RuntimeExecption异常 导致 @Transactional 失效
  • 数据库引擎不支持事务

哪些集合类是线程安全的?

Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非线程安全的,不过在 JDK 1.5 之后随着 Java. util. concurrent 并发包的出现,

它们也有了自己对应的线程安全类,比如 HashMap 对应的线程安全类就是 ConcurrentHashMap。

线程和进程的区别?

1个程序下至少有一个进程,一个进程下至少有一个线程,一个进程下也可以有多个线程来增加程序的执行速度。

说一下你熟悉的设计模式?

  • 单例模式:保证被创建一次,节省系统开销。
  • 工厂模式(简单工厂、抽象工厂):解耦代码。
  • 观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。
  • 外观模式:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。
  • 模版方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。
  • 状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

spring 有哪些主要模块?

  • spring core:框架的最基础部分,提供 ioc 和依赖注入特性。
  • spring context:构建于 core 封装包基础上的 context 封装包,提供了一种框架式的对象访问方法。
  • spring dao:Data Access Object 提供了JDBC的抽象层。
  • spring aop:提供了面向切面的编程实现,让你可以自定义拦截器、切点等。
  • spring Web:提供了针对 Web 开发的集成特性,例如文件上传,利用 servlet listeners 进行 ioc 容器初始化和针对 Web 的 ApplicationContext。
  • spring Web mvc:spring 中的 mvc 封装包提供了 Web 应用的 Model-View-Controller(MVC)的实现。

spring 常用的注入方式有哪些?

  • setter 属性注入
  • 构造方法注入
  • 注解方式注入

spring 支持几种 bean 的作用域?

  • singleton:spring ioc 容器中只存在一个 bean 实例,bean 以单例模式存在,是系统默认值;
  • prototype:每次从容器调用 bean 时都会创建一个新的示例,既每次 getBean()相当于执行 new Bean()操作;
  • request:每次 http 请求都会创建一个 bean;
  • session:同一个 http session 共享一个 bean 实例;
  • global-session:用于 portlet 容器,因为每个 portlet 有单独的 session,globalsession 提供一个全局性的 http session。

spring 自动装配 bean 有哪些方式?

  • no:默认值,表示没有自动装配,应使用显式 bean 引用进行装配。
  • byName:它根据 bean 的名称注入对象依赖项。
  • byType:它根据类型注入对象依赖项。
  • 构造函数:通过构造函数来注入依赖项,需要设置大量的参数。
  • autodetect:容器首先通过构造函数使用 autowire 装配,如果不能,则通过 byType 自动装配。

spring 事务实现方式有哪些?

  • 声明式事务:声明式事务也有两种实现方式,基于 xml 配置文件的方式和注解方式(在类上添加 @Transaction 注解)。
  • 编码方式:提供编码的形式管理和维护事务。

Java 容器都有哪些?

Java 容器分为 Collection 和 Map 两大类,其下又有很多子类,如下所示:

Collection

  • List
    • ArrayList
    • LinkedList
    • Vector
    • Stack
  • Set
    • HashSet
    • LinkedHashSet
    • TreeSet

Map

  • HashMap
    • LinkedHashMap
  • TreeMap
  • ConcurrentHashMap
  • Hashtable

java基础类型?

4类8种:

  • 1、整型
    byte 、short 、int 、long
  • 2、浮点型
    float 、 double
  • 3、字符型
    char
  • 4、布尔型
    boolean

final、finally、finalize 有什么区别?

  • final:是修饰符,如果修饰类,此类不能被继承;如果修饰方法和变量,则表示此方法和此变量不能在被改变,只能使用。
  • finally:是 try{} catch{} finally{} 最后一部分,表示不论发生任何情况都会执行,finally 部分可以省略,但如果 finally 部分存在,则一定会执行 finally 里面的代码。
  • finalize:是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。

try-catch-finally 中哪个部分可以省略?

try-catch-finally 其中 catch 和 finally 都可以被省略,但是不能同时省略,也就是说有 try 的时候,必须后面跟一个 catch 或者 finally。

try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

finally 一定会执行,即使是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完之后,才会执行。

常见的集合?

常用的三大类集合:Set、List、Map

  • Set 接口、实现类:Set,SortedSet接口。HashSet,TreeSet,LinkedHashSet实现类
  • List 接口、实现类:List接口。ArrayList,LinkedList,Vector实现类
  • Map 接口、实现类:Map接口。HashMap,LinkedHashMap,TreeMap,Hashtable,ConcurrentHashMap

线程安全的集合?

ConcurrentHashMap,CopyOnWriteArrayList,CopyOnWriteArraySet,Vector,HashTable

throw 和 throws 的区别?

  • throw:是真实抛出一个异常。
  • throws:是声明可能会抛出一个异常。

常见的异常类有哪些?

  • NullPointerException 空指针异常
  • ClassNotFoundException 指定类不存在
  • NumberFormatException 字符串转换为数字异常
  • IndexOutOfBoundsException 数组下标越界异常
  • ClassCastException 数据类型转换异常
  • FileNotFoundException 文件未找到异常
  • NoSuchMethodException 方法不存在异常
  • IOException IO 异常
  • SocketException Socket 异常

启动线程的几种方式?

  • 一、启动线程的第一种方法:继承Thread类,重写run()方法,new对象调用start方法启动线程
java 复制代码
public class Thread01  {
    public static void main(String[] args) {
        //创建线程对象
        MyThread myThread = new MyThread();
        //启动线程
        myThread.start();

        //主线程
        for (int i = 0; i <100 ; i++) {
            System.out.println("main主线程--->" + i);
        }

    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println("分支线程---->"+ i);
        }
    }
}
  • 二、启动线程的第二种方式:实现Runnable接口,重写run()方法,创建线程对象,调用start方法启动线程
java 复制代码
public class Thread02 {
    public static void main(String[] args) {
        //创建线程对象
        Thread thread = new Thread(new MyRunnable());
        //启动线程
        thread.start();

        //主线程
        for (int i = 0; i <100 ; i++) {
            System.out.println("main主线程--->" + i);
        }
    }
}
class MyRunnable implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println("分支线程---->"+ i);
        }
    }
}
  • 三、启动线程的第三种方式:实现Callable接口,重写call()方法,创建线程对象,调用start方法启动线程
java 复制代码
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/***
 * 启动线程的第三种方法:实现Callable接口,重写call()方法
 */
public class ThreadTest04 {
    public static void main(String[] args) {
        //创建一个"未来任务类"对象
        FutureTask futureTask = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception { //call()方法相当与run()方法,比run方法好,有返回值
                System.out.println("call mothed begin!");
                Thread.sleep(1000 * 10);
                System.out.println("call mothed over!");

                int x = 100;
                int y = 200;

                return x + y;//自动装箱
            }
        });

        //创建线程对象
        Thread t = new Thread(futureTask);

        //启动线程
        t.start();

        Object obj = null;
        //获得分支线程返回值
        try {
            //get()方法的执行会导致主线程的阻塞
            obj = futureTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        System.out.println("获得分支线程的返回值:" + obj );

        //如下的代码会等到分支线程执行结束后,才回到主线程中继续执行
        System.out.println("Hello CSDN");
    }
}

一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 id 是几?

表类型如果是 MyISAM ,那 id 就是 8。

表类型如果是 InnoDB,那 id 就是 6。

InnoDB 表只会把自增主键的最大 id 记录在内存中,所以重启之后会导致最大 id 丢失。

左外连接和内连接?

使用内连接时,不符合连接条件的数据,(不管是左表中的还是右表中的)都不会被组织到结果集中

使用左外连接时,对于不符合连接条件的数据,左表中的内容依然会被组织到结果集中,结果集中该条数据对应的右表部分为 null

怎么确定索引是否被用到?

MySQL的Explain关键字查看是否使用索引,简单的看type类型就可以。如果它是all,那说明这条查询语句遍历了所有的行,并没有使用到索引。

Spring常用的注解?

  • 1、@Controller

对应表现层的Bean,也就是Action,将标注了此注解的类纳入进spring容器中管理

  • 2、@RequestMapping

RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

  • 3、@Resource和@Autowired

@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。

  • 4、@ModelAttribute和 @SessionAttributes

代表的是:该Controller的所有方法在调用前,先执行此@ModelAttribute方法,可用于注解和方法参数中,可以把这个@ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行@ModelAttribute方法。@SessionAttributes即将值放到session作用域中,写在class上面。

  • 5、@PathVariable

用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。

  • 6、@requestParam

@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter("name"),它有三个常用参数:defaultValue = "0", required = false, value = "isApp";defaultValue 表示设置默认值,required 铜过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。

  • 7、@ResponseBody

作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

  • 8、@RequestBody

接收前端传过来的json对象

  • 9、@Component

相当于通用的注解,当不知道一些类归到哪个层时使用,但是不建议。

  • 10、@Repository

用于注解dao层,在daoImpl类上面注解。

  • 11、@RequestHeader

获取请求头信息

Spring的事务配置?

  • 1.基于XML的事务配置。
  • 2.基于注解方式的事务配置。

Linux常用命令?

  • ls:列出您想要的目录的内容
  • pwd:输出您所在目录的绝对路径。
  • cd:切换到您试图访问的目录。
  • cp:复制
  • rm:删除
  • mv:移动
  • mkdir:创建文件夹
  • touch:创建文件
  • exit:结束会话
  • cat:查看文件
  • ping:测试网络连接
  • kill:杀进程
  • vim:编辑文件

mysql的索引?

  • 索引原理:索引的存储原理大致可以概括为一句话:以空间换时间。

  • 索引的分类:主键索引,唯一索引,复合索引,全文索引,空间索引,前缀索引

  • 索引的优缺点:

    • 优点:
      大大提高数据查询速度。
    • 缺点:
      索引会占据磁盘空间。
  • 索引的数据结构:

    MySQL索引使用的数据结构主要有BTree索引和hash索引。

对于hash索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景建议选择BTree索引。

说一下springboot常用注解?

  • 1、@SpringBootApplication

替代 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan

  • 2、@ImportAutoConfiguration

导入配置类,一般做测试的时候使用,正常优先使用@EnableAutoConfiguration

  • 3、@SpringBootConfiguration

替代@Configuration

  • 4、@ImportResource

将资源导入容器

  • 5、@PropertySource

导入properties文件

  • 6、PropertySources

@PropertySource 的集合

  • 7、@Role

bean角色定义为ROLE_APPLICATION(默认值)、ROLE_SUPPORT(辅助角色)、ROLE_INFRASTRUCTURE(后台角色,用户无感)

  • 8、@Scope

指定bean的作用域,默认singleton,其它包括prototype、request、session、globalSession

  • 9、@Lazy

使bean懒加载,取消bean预初始化。

  • 10、@Primary

自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否者将抛出异常。

  • 11、@Profile

指定Bean在哪个环境下被激活

  • 12、@DependsOn

依赖的bean注册完成,才注册当前类,依赖bean不存在会报错。用于控制bean加载顺序

  • 13、@PostConstruct

bean的属性都注入完毕后,执行注解标注的方式进行初始化工作

  • 14、@Autowired

默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。

  • 15、@Lookup

根据方法返回的类型,去容器中捞出对应

  • 16、@Qualifier

申明bean名字,且可以按bean名字加载bean

  • 17、@Required

检查bean的属性setXXX()方法,要求属性砸死配置阶段必须已配置

  • 18、@Description

添加bean的文字描述

  • 19、@EnableAspectConfiguration

启动AspectJ自动配置

  • 20、EnableLoadTimeWeaving

启动类加载器动态增强功能,使用instrumentation实现

  • 21、@AutoConfigurationPackage

包含该注解的package会被AutoConfigurationPackages注册

  • 22、@AutoConfigureBefore

在指定配置类初始化前加载

  • 23、@AutoConfigureAfter

在指定配置类初始化后加载

  • 24、@AutoConfigureOrder

指定配置类初始化顺序,越小初始化越早

restcontroller与controller的区别?

  • @RestController加在类上面的注解,使得类里面的每个方法都将json/xml返回数据加返回到前台页面中。
  • @Controller加在类上面的注解,使得类里面的每个方法都返回一个视图页面。
  • @RestController注解相当于@ResponseBody + @Controller合在一起的作用。

HTTP的三次握手和四次挥手?

三次握手:

  • 第一次握手:客户端向服务器发送连接请求包,标志位SYN(同步序号)置为1,序号为X=0
  • 第二次握手: 服务器收到客户端发过来报文,由SYN=1知道客户端要求建立联机。向客户端发送一个SYN和ACK都置为1的TCP报文,设置初始序号Y=0,将确认序号(Acknowledgement Number)设置为客户的序列号加1,即X+1 = 0+1=1
  • 第三次握手: 客户端收到服务器发来的包后检查确认序号(Acknowledgement Number)是否正确,即第一次发送的序号加1(X+1=1)。以及标志位ACK是否为1。若正确,客户端再次发送确认包,ACK标志位为1,SYN标志位为0。确认序号(Acknowledgement Number)=Y+1=0+1=1,发送序号为X+1=1。服务器收到后确认序号值与ACK=1则连接建立成功,可以传送数据了。

TCP四次挥手:

  • 第一次挥手: 客户端给服务器发送TCP包,用来关闭客户端到服务器的数据传送。将标志位FIN和ACK置为1,序号为X=1,确认序号为Z=1。
  • 第二次挥手:服务器收到FIN后,发回一个ACK(标志位ACK=1),确认序号为收到的序号加1,即X=X+1=2。序号为收到的确认序号=Z。
  • 第三次挥手:服务器关闭与客户端的连接,发送一个FIN。标志位FIN和ACK置为1,序号为Y=1,确认序号为X=2。
  • 第四次挥手:客户端收到服务器发送的FIN之后,发回ACK确认(标志位ACK=1),确认序号为收到的序号加1,即Y+1=2。序号为收到的确认序号X=2。

collection和collections的作用?

  • 1、Collection 是一个集合接口

    Collection,提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。

  • 2、Collections 是一个包装类

    Collections,是一个工具类,它包含了很多静态方法,不能被实例化,比如排序方法: Collections. sort(list)等。

覆盖索引?

如果select语句中的查询列,都是索引列,那么这些列被称为覆盖索引。

索引失效的场景?

  • 不满足最左匹配原则
  • 使用了select *
  • 索引列上有计算
  • 索引列用了函数
  • 字段类型不同
  • 使用不等于(!=或者<>)
  • like左边包含%
  • 列对比
  • 使用or关键字(注意:如果使用了or关键字,那么它前面和后面的字段都要加索引,不然所有的索引都会失效,这是一个大坑2)
  • not in和not exists
  • is null ,is not null也无法使用索引
  • 字符串不加单引号索引失效

简单描述一下数据库的四种隔离级别以及对应的三种相关问题?

四种隔离级别:

  • Read Uncommitted(读取未提交内容)-》导致脏读
  • Read Committed(读取提交内容)-》导致不可重复读,解决脏读
  • Repeatable Read(可重读)-》导致幻读,解决脏读,不可重复读
  • Serializable(串行化)-》都可以解决。(为每个读取操作加一个共享锁)

三种数据不一致现象:

  • 脏读(Drity Read)
    一个事务可以读取到另一个事务未提交的数据。
  • 不可重复读(Non-repeatable read)
    一个事务因为读取到另一个事务已提交的修改数据,导致在当前事务的不同时间读取同一条数据获取的结果不一致。
  • 幻读(Phantom Read)
    一个事务因为读取到另一个事务已提交的删除或者新增数据,导致在当前事务的不同时间获取到的数据数量不一致。

Object 类你了解哪些方法?

  • getClass方法
  • clone方法
  • toString方法
  • hashCode方法
  • equals方法
  • finalize方法
  • wait方法
  • notify,notifyAll 方法

线程与进程的区别?

线程是进程的子集,一个线程只能属于一个进程,一个进程可以有多个线程

请你说说多线程?

线程是程序执行的最小单元,一个线程执行一个任务;各个线程共享程序的内存空间;多线程的好处在于减少程序响应时间,提高效率,数据共享率高。

说说怎么保证线程安全?

保证线程安全的有三种方式:原子类、volatile、锁。

  • 1、原子类:遵循CAS即"比较和替换"规则,比较要更新的值是否等于期望值,如果是则更新,如果不是则失败(单共享变量)
  • 2、volatile关键字:轻量级的synchronized,在多处理器开发中保证了共享变量的"可见性",从而可以保证单个变量读写时的线程安全(单共享变量)
  • 3、synchronized,java中常用的锁有两种:synchronized+juc包下的lock锁。支持响应中断、支持超时机制、支持以非阻塞的方式获取锁、支持多个条件变量

说说你对MVC的理解?

M(Model)模型,V(View)视图,C(Controller),将代码分为三个模块,模型、视图和控制器进行管理,能够提高代码的维护性,降低代码的耦合性

详细的说说Redis的数据类型?

redis中常用的五种数据结构:string、list、set、zset、hash

请你说说乐观锁和悲观锁?

  • 乐观锁:乐观锁总是假设最好的情况,每次去拿数据的时候默认别人不会修改,所以不会上锁,只有当更新的时候会判断一下在此期间有没有人更新了这个数据。适用于多读,可以使用版本号机制进行控制
  • 悲观锁:悲观锁总是假设最坏的情况,每次去拿数据是都认为别人会修改,所以每次在拿数据时都会上锁,这样别人想拿这个数据时会阻塞直到拿到锁。mysql数据库的共享锁和排他锁都是悲观锁的实现。

设计模式了解么?

常用的设计模式有单例模式、工厂模式、代理模式、适配器模式、装饰器模式、模板方法模式等等。像sping中的定义的bean默认为单例模式,spring中的BeanFactory用来创建对象的实例,他是工厂模式的体现。AOP面向切面编程时代理模式的体现,它的底层就是基于动态代理实现的。适配器模式在spring中有体现,它的处理器适配器会根据处理器规则适配相应的处理器执行,模板方法模式用来解决代码重复的问题等

说说Redis的持久化策略?

redis提供两种持久化机制:RDB和AOF。

  • RDB:redis的默认持久化方式是RDB。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。
    • RDB优点:rdb只有一个dump.rdb文件,方便持久化
    • RDB缺点:如果持久化之间redis发生故障,会发生数据丢失
  • AOF:AOF将redis执行的所有写命令记录到日志文件中。
    • AOF优点:aof数据比较完整
    • AOF缺点:一直追加占用资源

请你讲讲单例模式、请你手写一下单例模式?

  • 单例模式:一个类对外只提供一个实例。java的RunTime就是饿汉式单例模式
  • 单例模式实现:私有构造方法,暴露对外的实例化方法,私有静态变量
  • 饿汉式单例模式:
java 复制代码
//饿汉式:静态常量2
public class SingleTon {
    private static final SingleTon singleTon = new SingleTon();

    private SingleTon(){

    }

	public static SingleTon getSingleTon(){
		return singleTon;
	}
}
  • 懒汉式单例模式:
java 复制代码
//懒汉式:双重检查
public class SingleTon {
    private static volatile SingleTon singleTon;

    private SingleTon(){

    }

    public static SingleTon getSingleTon(){
        if (singleTon == null){
            synchronized (SingleTon.class){
                if (singleTon == null)
                    singleTon = new SingleTon();
            }
        }
        return singleTon;
    }
}

请你说说虚拟内存和物理内存的区别?

物理内存:计算机中真实拥有的内存。物理内存是有限的,容易产生内存不足问题。虚拟内存是一种抽象的逻辑概念,拥有连续的内存地址。

说说你对IoC的理解?

ioc是spring的基本特性之一,意思是控制反转,将原本由人完成的类的实例化等操作交给容器去完成,可以降低对象之间的耦合度,实现方式为di:依赖注入。有三种注入方式:构造器、setter、接口注入

说说你对AOP的理解?

AOP面向切面编程。是spring两大核心之一,它是一种编程思想,是对OOP的一种补充。它可以对业务逻辑的各个部分进行隔离,降低耦合,提高代码的可重用性。它的底层是通过动态代理实现的。它的应用场景有事务、日志管理等。

如何利用Redis实现一个分布式锁?

SET EX NX + 校验唯一随机值,再释放锁

请说说你对反射的了解?

反射就是在程序运行期间动态的获取对象的属性和方法的功能叫做反射。

它能够在程序运行期间,对于任意一个类,都能知道它所有的方法和属性,对于任意一个对象,都能知道他的属性和方法。

获取Class对象的三种方式:

  • getClass();
  • xx.class;
  • Class.forName("xxx");

反射的优缺点:

  • 优点:运行期间能够动态的获取类,提高代码的灵活性。
  • 缺点:性能比直接的Java代码要慢很多。

应用场景:spring的xml配置模式,以及动态代理模式都用到了反射。

请你说说ArrayList和LinkedList的区别?

  • ArrayList底层是数组实现的,读取快(使用索引),插入删除慢(需要重新计算大小或是更新索引)
  • LinkedList底层基于双向链表,读取慢,插入删除快;

请你讲讲工厂模式?

不暴露创建对象的具体逻辑,将具体逻辑封装到函数中,这个函数可以视作一个工厂

请你说说ConcurrentHashMap?

ConcurrentHashMap是一个线程安全的集合,它的底层是数组+链表/红黑树构成的。

在1.7的时候采用segment数组+hashEntry的方式实现的,通过ReentrantLock+CAS+分段思想来保证的并发安全的。

在1.8的时候废弃了这种算法,采用Synchronized+CAS+Node来保证并发安全的进行.

说说缓存穿透、击穿、雪崩的区别?

缓存穿透:客户端访问不存在的数据,使得请求直达存储层,导致负载过大,直至宕机。

解决方案:

  • 1.存储层未命中后,返回空值存入缓存层并加上短暂的过期时间,客户端再次访问时,缓存层直接返回空值。
  • 2.将数据存入布隆过滤器,访问缓存之前经过滤器拦截,若请求的数据不存在则直接返回空值。

缓存击穿:一份热点数据,它的访问量非常大,在它缓存失效的瞬间,大量请求直达存储层,导致服务崩溃。

解决方案:

  • 1.永不过期:对热点数据不设置过期时间。
  • 2.加互斥锁,当一个线程访问该数据时,另一个线程只能等待,这个线程访问之后,缓存中的数据将被重建,届时其他线程就可以从缓存中取值。

缓存雪崩:大量数据同时过期、或是redis节点故障导致服务不可用,缓存层无法提供服务,所有的请求直达存储层,造成数据库宕机。

  • 解决方案:
    • 1.避免数据同时过期,设置随机过期时间。
    • 2.启用降级和熔断措施。
    • 3.设置热点数据永不过期。
    • 4.采用redis集群,一个宕机,另外的还能用

Redis如何与数据库保持双写一致性?

先更新数据库再删除缓存,若有错误需要重试

说说你了解的线程同步方式?

java通过加锁的方式实现线程同步,锁有两类,分别是synchronized和Lock。或是使用volatile修饰变量

请你说说innodb和myisam的区别?

InnoDB支持事务,默认的锁行锁。 MyISAM不支持事务,默认的锁表锁。 读写性能:InnoDB增删改性能更优;MyISAM查询性能更优。

String、StringBuffer、Stringbuilder有什么区别?

String 是一个不可变类,StringBuffer和StringBuilder是可变的; StringBuilder不是线程安全的,String和StringBuffer是线程安全的; StringBuilder的效率比StringBuffer的执行效率高

String str="i"与 String str=new String("i")一样吗?

不一样,因为内存的分配方式不一样。String str="i"的方式,Java 虚拟机会将其分配到常量池中;而 String str=new String("i") 则会被分到堆内存中。

如何将字符串反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

集合和数组的区别

  • 数组是固定长度的;集合可变长度的。
  • 数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。

请你说说HashMap底层原理?

在1.8之前,HashMap的底层是数组加链表,在1.8之后是数组+链表+红黑树;

  • 它的put流程是:基于哈希算法的hashcode值来确定元素位置,当我们向集合存入数据时,他会计算传入的key的hashcode值,并利用哈希算法的hashcode值按位与操作(等价于取余)来确定元素的位置,
    如果这个位置已经存在其他元素了,就会发生哈希碰撞,则hashmap就会通过链表将这些元素组织起来,如果链表的长度达到8时,数组长度大于64,就会转化为红黑树,从而提高查询速度。
  • 扩容机制:HashMap中数组的默认初始容量为16,当达到默认负载因子0.75时,会以2的指数倍进行扩容。
    Hashmap时非线程安全的,1.7插入链表是用头插法,1.8用尾插法,所以1.8之后在多线程下不会产生死链,但是仍然有可能产生数据冲突

说说你了解的JVM内存模型?

JVM由4部分组成:类加载子系统、执行引擎、运行时数据区。本地库接口(Native Interface)

JVM运行时数据区域:

  • 线程共享:方法区、堆
  • 线程隔离:程序计数器、虚拟机栈、本地方法栈

JDK7和JDK8的JVM内存模型区别?

  • 1、方法区变化
    1.8同1.7比,最大的差别就是:元空间取代了永久代。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。
  • 2、运行时常量池变化
    1.7放到了堆内存中;1.8之后放到了元空间

说说类加载机制?

  • 类加载过程:

    类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用、卸载七个阶段。验证、准备、解析被称为连接

    加载:将class文件加载到虚拟机中

    验证:文件格式的验证,元数据验证,元数据验证,元数据验证

    准备:为类变量分配内存,并将其初始化为默认值。(此时为默认值,在初始化的时候才会给变量赋值)

    解析:解析阶段将类中符号引用转换为直接引用

    初始化:初始化阶段是执行类构造器方法的过程

  • 类加载器:

    启动类加载器(Bootstrap ClassLoader)-》 扩展类加载器(ExtClassLoader)-》 应用类加载器(AppClassLoader)

  • 双亲委派机制:

    所谓双亲委派是指每次收到类加载请求时,先将请求委派给父类加载器完成(所有加载请求最终会委派到顶层的Bootstrap ClassLoader加载器中),如果父类加载器无法完成这个加载(该加载器的

    搜索范围中没有找到对应的类),子类尝试自己加载。

请你说说==与equals()的区别?

== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?

不对,两个对象的 hashCode() 相同,equals() 不一定 true。反之两个对象的equals()相同,hashCode()一定 true

String 类的常用方法都有那些?

  • inexOf():返回指定字符的索引。
  • charAt():返回指定索引处的字符。
  • replace():字符串替换。
  • trim():去除字符串两端空白。
  • split():分割字符串,返回一个分割后的字符串数组。
  • getBytes():返回字符串的 byte 类型数组。
  • length():返回字符串长度。
  • toLowerCase():将字符串转成小写字母。
  • toUpperCase():将字符串转成大写字符。
  • substring():截取字符串。
  • equals():字符串比较。

抽象类必须要有抽象方法吗

不需要,抽象类不一定非要有抽象方法。

普通类和抽象类有哪些区别?

普通类不能包含抽象方法,抽象类可以包含抽象方法。

抽象类不能直接实例化,普通类可以直接实例化。

抽象类能使用 final 修饰吗?

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类,如下图所示,编辑器也会提示错误信息:

接口与抽象类的区别

  • 相同点
    都不能被实例化
  • 不同点
    • 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
    • 构造函数:抽象类可以有构造函数;接口不能有。
    • 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
    • 访问修饰符:接口成员变量默认为public static final,必须赋初值,不能被修改;接口中的方法默认使用 public 修饰;抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法必须为public abstract或者protected abstract等修饰。

Java 中 IO 流分为几种?

  • 按功能来分:输入流(input)、输出流(output)。
  • 按类型来分:字节流和字符流。

BIO、NIO、AIO 有什么区别?

  • BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
  • NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
  • AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

Files的常用方法都有哪些?

  • Files. exists():检测文件路径是否存在。
  • Files. createFile():创建文件。
  • Files. createDirectory():创建文件夹。
  • Files. delete():删除一个文件或目录。
  • Files. copy():复制文件。
  • Files. move():移动文件。
  • Files. size():查看文件个数。
  • Files. read():读取文件。
  • Files. write():写入文件。

说说synchronize的用法及原理?

synchronized可以修饰静态方法、普通方法、代码块。 能够保证同一个时刻只有一个线程执行该段代码,保证线程安全。 在执行完或者出现异常时自动释放锁。 synchronized作用在代码块时,它的底层是通过monitorenter、monitorexit指令来实现的。

说说static修饰符的用法?

static可修饰类,方法,代码块,变量。不可以修饰构造器。

被static修饰的类为静态类,可以在不创建实例的情况下访问它的静态方法或静态成员变量,而其实例方法或实例成员变量只能通过其实例对象来访问。

在静态方法中不能使用this,因为this是随着对象创建而存在。

静态成员变量随着静态类的加载而创建。

说说线程的状态?

创建,就绪,运行,阻塞,死亡

请你说一下final关键字?

final修饰的类是最终类,不可以被继承。 final修饰的方法不可以被重写。 final修饰的变量是常量,常量必须初始化,初始化之后值就不能被修改

请你说说重载和重写的区别,构造方法能不能重写?

重写是父子类中的关系:指的是子类可以重写父类的方法,方法名相同,参数列表相同 重载是一个类中的:方法名相同,参数列表不同

构造方法不能重写,因为构造方法要求方法名与类名相同,而父子类类名不同

请你讲一下Java 8的新特性?

  • Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。

  • 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

  • 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。

  • 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。

  • Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

  • Date Time API − 加强对日期与时间的处理。

  • Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

  • Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

ArrayList 和 LinkedList 的区别是什么?

  • 数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
  • 随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
  • 增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。

说说你对ArrayList的理解?

ArrayList有序可重复,底层是数组,查询快。增删慢,线程是不安全的。

ArrayList的自动扩容,在jdk8之前,ArrayList创建的时候默认容量就为10,每次扩容均为原来的1.5倍。

在jdk8之后,创建的时候没有数组的内存单元,而是在第一次调用add方法的时候提供一个10的容量,并扩容也为原来的1.5倍

说说Spring Boot的自动装配?

靠EnableAutoConfiguration注解,

通过@import的方式导入了@AutoConfigurationImportSelect类,并调用selectImports方法从

spring.factories中寻找有没有AutoConfiguration类满足Conditional注解的生效条件,有的话,就是实例化该AutoConfiguration类,然后加载到spring容器就实现了spring的自动装配

说说@Autowired和@Resource注解的区别?

  • 1.@Autowired由Spring提供,@Resource由JDK提供。
  • 2.@Autowired只能按类型注入,@Resource默认按名称注入,也支持按类型注入。
  • 3.如果@Autowired想使用按名称装配,,可以结合@Qualifier注解一起使用

介绍一下Spring MVC的执行流程?

  • 1、 用户向服务器发送请求,请求被 Spring 前端控制 Servelt DispatcherServlet 捕获(捕获)

  • 2、 DispatcherServlet对请求 URL进行解析,得到请求资源标识符(URI)。然后根据该 URI,调用 HandlerMapping获得该Handler配置的所有相关的对象(包括 Handler对象以及 Handler对象对应的拦截器),最后以 HandlerExecutionChain对象的形式返回;(查找 handler)

  • 3、 DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter。 提取Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller), Handler执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象(执行 handler)

  • 4、DispatcherServlet 根据返回的 ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的 ViewResolver) (选择 ViewResolver)

  • 5、通过 ViewResolver 结合 Model 和 View,来渲染视图,DispatcherServlet 将渲染结果返回给客户端。(渲染返回)

快速记忆技巧:

核心控制器捕获请求、查找Handler、执行Handler、选择ViewResolver,通过ViewResolver渲染视图并返回

spring mvc 有哪些组件?

前置控制器 DispatcherServlet。

映射控制器 HandlerMapping。

处理器 Controller。

模型和视图 ModelAndView。

视图解析器 ViewResolver。

在MyBatis中$和#有什么区别?

#传入的参数在SQL中显示为字符串是sql预编译,KaTeX parse error: Expected 'EOF', got '#' at position 28: ...显示为传入的值是sql拼接. #̲方式能够很大程度防止sql注入...方式无法防止Sql注入;

说说你对面向对象的理解?

面向对象的三大基本特征是:封装,继承,多态 ;

封装:隐藏类的成员变量和实现细节,不允许外部直接访问,

继承:代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性,提高了代码复用,

多态:需有继承关系的存在,需要有方法的重写,需要有父类引用指向子类对象

请介绍一下访问修饰符?

private:只能在当前类中访问。default:当前类和当前包。protected:当前类,当前包和子包。public:可以被当前程序下的所有类访问

说说Java中常用的锁及原理?

synchronized关键字和lock锁接口:synchronized关键字底层采用java对象头来存储锁信息的。lock锁接口是基于AQS实现的。而Lock接口的经典实现是ReentrantLock。

synchronized和Lock有什么区别?

1.lock是一个接口,synchronized是java关键字。 2.lock不会主动释放,需要手动释放锁。 3.lock可以通过tryLock()查看是否加锁成功,而synchronized无法获悉是否加锁成功。

请你说说List与Set的区别?

list跟set都是collection的接口,list是有序可重复,set是无序不可重复,

说说Bean的作用域,以及默认的作用域?

Bean有五种作用域:singleton、prototype、request、session、globalSession 默认是singleton单例

说说BeanFactory和FactoryBean的区别?

beanFactory是spring基本的容器,factoryBean是spring容器内的一种bean

相关推荐
7yewh1 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
钱多多_qdd10 分钟前
spring cache源码解析(四)——从@EnableCaching开始来阅读源码
java·spring boot·spring
waicsdn_haha12 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
_WndProc14 分钟前
C++ 日志输出
开发语言·c++·算法
Q_192849990623 分钟前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端
qq_4335545423 分钟前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
Code_流苏25 分钟前
VSCode搭建Java开发环境 2024保姆级安装教程(Java环境搭建+VSCode安装+运行测试+背景图设置)
java·ide·vscode·搭建·java开发环境
数据小爬虫@42 分钟前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
ZJ_.44 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
Narutolxy1 小时前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin