• 9月13日扒面经


    文章目录

    2)char可以存放汉字吗

    可以,一个汉字在Java中通常需要占用两个char类型的存储空间,即一个汉字需要两个char来表示

    3)list,map,set区别是什么

    list和set同属collection接口,list是有序的集合,可以包含重复元素,实现类有:ArrayList、LinkedList、Vector

    set:无序的集合,不包含重复元素,实现类有 HashSet,TreeSet,

    map无序不重复,key不可重复,value可以。它是以键值对方式存储的,具体实现类有Hashmap,treemap,hashtable

    4)讲一下反射

    反射也称类的自省,在运行状态,任何一个类都可以动态获取它的所有属性和方法,任何属性都可以调用它的所有方法和属性。

    主要应用:动态加载类和创建对象

    ​ 动态调用方法和访问属性

    ​ 获取类结构信息

    ​ 编写通用框架

    缺点:

    ​ 性能较差: 因为是运行时获取类信息

    ​ 安全性较差: 涉及到获取私有成员变量等

    ​ 可读性和维护性差: 反射获取的代码比较复杂

    5)实现反射的类
    1. Class类:代表一个类或接口,在运行时可以通过该类获取类的信息,如类的名称、方法、字段等。可以使用Class.forName()方法获取一个类的Class对象。
    2. Constructor类:代表一个构造方法,可以使用Class.getConstructors()方法获取一个类的所有公共构造方法,或使用Class.getDeclaredConstructors()方法获取一个类的所有构造方法,包括私有构造方法。
    3. Method类:代表一个方法,可以使用Class.getMethods()方法获取一个类的所有公共方法,或使用Class.getDeclaredMethods()方法获取一个类的所有方法,包括私有方法。
    4. Field类:代表一个字段,可以使用Class.getFields()方法获取一个类的所有公共字段,或使用Class.getDeclaredFields()方法获取一个类的所有字段,包括私有字段。
    5. Modifier类:提供了一些静态方法,用于获取和操作成员的修饰符,如isPublic()isPrivate()isStatic()等。
    6)重载和重写区别

    重载是在一个类中,具有相同的方法名,但是它的参数列表必须不同,与返回值类型无关

    重写是子类继承父类去重写父类的方法,相同的方法名,相同的参数列表,访问权限必须比父类更好。

    7)类加载过程

    加载,将.class字节码文件加载到JVM虚拟机中

    验证,验证被加载的类的字节码文件的正确性和安全性。

    准备,为静态变量分配内存并设置默认的初始值

    解析,将符号引用解析为直接引用

    初始化,执行类的初始化代码,包括静态变量的赋值和静态代码块的执行。

    8)什么时候会内存泄漏
    9)子父类加载顺序

    父类静态,子类静态,父类方法,子类方法。

    10)String,StringBuilderStringBuffer区别,哪些是线程安全的,哪一个快一些

    String 是不可变的,由final修饰

    StringBuffer是线程安全的

    StringBuilder效率最快,但他线程不安全

    11)线程创建方式,你常用的是哪个,为什么

    Runable,callable,Thread,线程池

    callable,可以捕获受检查的异常,并且可以有返回值

    1.java异常处理的throws有什么弊端嘛,每一个方法都要throws一下的话?

    ​ throws抛出的异常 要求调用者必须处理或者继续抛出会导致代码存在过多的异常抛出和处理逻辑增加冗余

    ​ 异常处理繁琐:当每个方法都需要使用throws声明异常时,调用栈上的每个方法都需要添加异常的处理逻辑,这样会导致异常处理的代码变得冗长和繁琐,降低代码的可读性和可维护性。

    解决方案

    对于可以预想到的异常,try-catch捕获处理

    用全局异常处理?所有的异常统一使用一个类来处理

    2.catch里面怎么处理的,如果是一个io notfound的异常

    日志记录

    错误提示

    异常处理和回复

    抛出新的异常

    3.Maven的classpath
    1. src/main/java:用于存放主要的Java源代码文件。
    2. src/main/resources:用于存放主要的资源文件,如配置文件、属性文件等。
    3. src/test/java:用于存放测试相关的Java源代码文件
    1.你是怎么理解泛型的?

    泛型是Java中的一种编程机制,它允许在定义类、接口或方法时使用类型参数,以便在使用该类、接口或方法时指定具体的类型。泛型的主要目的是增加代码的类型安全性和重用性。

    通过使用泛型,我们可以在编译时检查类型的一致性,避免了在运行时出现类型转换错误的可能性。泛型还可以提高代码的可读性和可维护性,因为代码中的类型信息更加明确。

    3.线程池有核心线程数,当我们核心线程数满了,再来任务的话我们是怎么处理的?

    七大参数:核心线程数,最大线程使用数,最大线程使用时间单位,线程工厂,拒绝策略。

    当线程池的核心线程数已满,并且任务队列也已经满时,线程池会根据配置的拒绝策略来处理新提交的人

    Java中的线程池使用ThreadPoolExecutor类来实现,ThreadPoolExecutor提供了几种预定义的拒绝策略:

    1. AbortPolicy(默认):线程池默认的拒绝策略,当线程池无法处理新任务时,会抛出RejectedExecutionException异常。
    2. CallerRunsPolicy:当线程池无法处理新任务时,会将任务返回给提交任务的线程执行。这样做的效果是,提交任务的线程自己执行任务,可以降低新任务的提交速度,但可能会影响整体性能。
    3. DiscardPolicy:当线程池无法处理新任务时,会直接丢弃该任务,不会抛出异常。
    4. DiscardOldestPolicy:当线程池无法处理新任务时,会丢弃任务队列中最旧的任务,然后尝试重新提交新任务。
    5.我一次请求过来,我为了加快这个请求的响应,我把这个请求拆成多个线程去执行,比如说三个,执行完后我在拼接,对这个场景的话我们的队列长度怎么设置?
    6.你常用的拒绝策略是哪个?

    默认:当线程池无法处理新任务时,会抛出RejectedExecutionException异常。

    8.volatile 这个关键字你是怎么理解的?

    一个修饰符 用于修饰变量 保证可见性和有序性, 不能保证原子性

    被修饰的的变量会有两个特性

    • 可见性
      • 对一个变量的修改会立刻被其他线程可见,因为volatile修饰的变量写操作会立刻刷新到内存,每次读都是从内存中读取
    • 有序性
      • 禁止指令重排序实现的有序性
    适合什么场景
    1. 适合当多线程共享一个变量时.其中一个修改需要被其他线程所知的场景

    2. 只读场景

    10.java 哪些地方用到了 volatile?

    AQS内部有volatile修饰的变量state

    标记状态

    ​ 多线程用volatile修饰状态标记变量,用于状态标记被修改时,其他线程立刻可见

    线程通信

    ​ 可以使用 “volatile” 修饰共享变量。通过修改共享变量的值,一个线程可以通知其他线程进行相应的操作,保证线程之间的可见性

    11.垃圾回收器用的啥?
    12.mybatis 里的占位符$和#区别

    替换符 : 它将占位符直接替换为参数的值,相当于字符串拼接, :它将占位符直接替换为参数的值,相当于字符串拼接, :它将占位符直接替换为参数的值,相当于字符串拼接,不会对参数进行预编译或者转义,存在sql注入的风险。

    占位符#:它会将占位符替换为参数的占位符,并且会对参数进行预编译和转义,以防止SQL注入的风险。

    13.统一的 token 验证除了使用拦截器以外还会使用哪些方式?
    1. 过滤器(Filter):
      • 过滤器是基于 Servlet 规范的一种组件,位于请求链的前后,可以对请求和响应进行预处理和后处理。
      • 过滤器可以通过配置拦截特定的 URL 模式或请求路径,对请求进行处理、修改或拦截。例如,可以在过滤器中实现请求参数的解析、字符编码的统一处理、跨域请求的处理等。
      • 过滤器的配置通过在 web.xml 文件中进行配置,可以通过设置过滤器的顺序来控制多个过滤器的执行顺序。
    2. 拦截器(Interceptor):
      • 拦截器是基于框架的一种组件,不依赖于 Servlet 规范,比如在 Spring、Struts 等框架中使用。
      • 拦截器在请求链的前后、控制器方法的前后等切点进行处理,可以对请求进行拦截、预处理和后处理。
      • 拦截器可以拦截请求和响应,也可以拦截控制器方法的调用,可以验证用户身份、记录日志、处理异常等功能。
      • 拦截器的配置一般通过在配置文件中配置拦截器的类和拦截的路径匹配规则来实现。
    14.过滤器和拦截器,servlet 过滤器啥的。
    1. spring aop

    面向切面编程,

    1. 用户注册的时候,一个手机号只能注册一个人,避免重复提交连续点了两次? (1."换一个,高并发情况”2换一个"3.”换一个,多ip“…问我的是dds攻击吗? 我是大彩笔,想不出来了。以前无聊看过,忘了怎么处理了,啊啊啊啊啊,不就是个表单重复提交吗,我咋忘了)
    2. MySQL的主从复制设计哪三个线程?

    主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。

    binlog 线程 :负责将主服务器上的数据更改写入二进制日志(Binary log)中。

    I/O 线程 :负责从主服务器上读取二进制日志,并写入从服务器的重放日志(Relay log)中。

    SQL 线程 :负责读取重放日志并重放其中的 SQL 语句。

    1. Redis 如何实现分布式锁的?

    获取锁:当一个进程需要获取锁时,它会向Redis发送一个SET命令,将一个特定的键作为锁的标识,并设置一个唯一的值作为锁的持有者标识,同时设置一个过期时间,以防止锁被永久持有。

    SET lock_key unique_value NX PX expiration_time
    NX表示只有在键不存在时才设置成功,确保只有一个进程能够成功获取锁。

    释放锁:当一个进程完成任务后,它会向Redis发送一个DEL命令,删除锁的键,释放锁。

    DEL lock_key
    使用分布式锁时需要注意以下几点:

    锁的标识应该是唯一的,可以使用进程ID或者UUID等唯一标识符。
    设置适当的过期时间,确保即使持有锁的进程崩溃或异常退出,锁也能够自动释放,避免死锁。
    获取锁和释放锁的操作应该是原子的,可以使用Redis的SETNX和DEL命令组合实现原子性操作。
    锁的持有时间应该尽量短,以免阻塞其他进程的执行。
    需要注意的是,分布式锁并不能完全解决并发控制的问题,仍然可能存在竞态条件和死锁等问题。因此,在使用分布式锁时,需要根据具体情况仔细设计和测试,以确保并发控制的正确性和性能。

  • 相关阅读:
    react组件通信
    SpringBoot--配置Redisson的方法
    前端面试题(四)
    【GNN】采样算法总结
    对数线性模型用于序列标注
    双指针法 ( 三数之和 )
    Linux电源管理
    Makefile三个版本的编写
    skywalking源码本地编译运行经验总结
    java 循环结构语句
  • 原文地址:https://blog.csdn.net/m0_61943950/article/details/132857843