Java面试题总结(乱序版,2020-08-20)

目录

一、String 属于基础的数据类型吗?

二、java 中操作字符串都有哪些类?它们之间有什么区别?

三、String str="i"与 String str=new String(“i”)一样吗?

四、说一下 HashMap 的实现原理?

五、set有哪些实现类?

六、说一下 HashSet 的实现原理?

七、请谈谈 volatile 有什么特点,为什么它能保证变量对所有线程的可见性?

八、为什么说 Synchronized 是一个悲观锁?乐观锁的实现原理又是什么?什么是 CAS,它有什么特性?

九、乐观锁一定就是好的吗?

十、说一下 jsp 的 4 种作用域?

十一、forward 和 redirect 的区别?

十二、Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式

十三、Spring 有几种配置方式?

十四、Spring Boot 中的监视器是什么?

十五、hibernate 中如何在控制台查看打印的 sql 语句?

十六、说一下 mybatis 的一级缓存和二级缓存?

十七、RabbitMQ中 vhost 的作用是什么?

十八、如何获取当前数据库版本?

十九、Redis和 memecache 有什么区别?

二十、怎么判断对象是否可以被回收?

二十一、java 中都有哪些引用类型?


一、String 属于基础的数据类型吗?

不属于。

八种基本数据类型:byte、short、char、int、long、double、float、boolean。

二、java 中操作字符串都有哪些类?它们之间有什么区别?

1、String

String是不可变对象,每次对String类型的改变时都会生成一个新的对象。

2、StringBuilder

线程不安全,效率高,多用于单线程。

3、StringBuffer

线程安全,由于加锁的原因,效率不如StringBuilder,多用于多线程。

不频繁的字符串操作使用String,操作频繁的情况不建议使用String。

StringBuilder > StringBuffer > String。

三、String str="i"与 String str=new String(“i”)一样吗?

String str="i"会将起分配到常量池中,常量池中没有重复的元素,如果常量池中存中i,就将i的地址赋给变量,如果没有就创建一个再赋给变量。

String str=new String(“i”)会将对象分配到堆中,即使内存一样,还是会重新创建一个新的对象。

四、说一下 HashMap 的实现原理?

1、简介

HashMap基于map接口,元素以键值对方式存储,允许有null值,HashMap是线程不安全的。

2、基本属性

  • 初始化大小,默认16,2倍扩容;
  • 负载因子0.75;
  • 初始化的默认数组;
  • size
  • threshold。判断是否需要调整hashmap容量

3、HashMap的存储结构

JDK1.7中采用数组+链表的存储形式。

HashMap采取Entry数组来存储key-value,每一个键值对组成了一个Entry实体,Entry类时机上是一个单向的链表结构,它具有next指针,指向下一个Entry实体,以此来解决Hash冲突的问题。

HashMap实现一个内部类Entry,重要的属性有hash、key、value、next。

Java面试题总结(乱序版,2020-08-20)_第1张图片

JDK1.8中采用数据+链表+红黑树的存储形式。当链表长度超过阈值(8)时,将链表转换为红黑树。在性能上进一步得到提升。

Java面试题总结(乱序版,2020-08-20)_第2张图片

五、set有哪些实现类?

1、HashSet

  • HashSet是set接口的实现类,set下面最主要的实现类就是HashSet(也就是用的最多的),此外还有LinkedHashSet和TreeSet。
  • HashSet是无序的、不可重复的。通过对象的hashCode和equals方法保证对象的唯一性。
  • HashSet内部的存储结构是哈希表,是线程不安全的。

2、TreeSet

TreeSet对元素进行排序的方式:

  • 元素自身具备比较功能,需要实现Comparable接口,并覆盖compareTo方法。
  • 元素自身不具备比较功能,需要实现Comparator接口,并覆盖compare方法。

3、LinkedHashSet

LinkedHashSet是一种有序的Set集合,即其元素的存入和输出的顺序是相同的。

六、说一下 HashSet 的实现原理?

HashSet实际上是一个HashMap实例,数据存储结构都是数组+链表。

HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value都是一个统一的对象PRESENT。

private static final Object PRESENT = new Object();

HashSet中add方法调用的是底层HashMap中的put方法,put方法要判断插入值是否存在,而HashSet的add方法,首先判断元素是否存在,如果存在则插入,如果不存在则不插入,这样就保证了HashSet中不存在重复值。

 通过对象的hashCode和equals方法保证对象的唯一性。

七、请谈谈 volatile 有什么特点,为什么它能保证变量对所有线程的可见性?

volatile只能作用于变量,保证了操作可见性和有序性,不保证原子性。

在Java的内存模型中分为主内存和工作内存,Java内存模型规定所有的变量存储在主内存中,每条线程都有自己的工作内存。

主内存和工作内存之间的交互分为8个原子操作:

  1. lock
  2. unlock
  3. read
  4. load
  5. assign
  6. use
  7. store
  8. write

volatile修饰的变量,只有对volatile进行assign操作,才可以load,只有load才可以use,,这样就保证了在工作内存操作volatile变量,都会同步到主内存中。

八、为什么说 Synchronized 是一个悲观锁?乐观锁的实现原理又是什么?什么是 CAS,它有什么特性?

Synchronized的并发策略是悲观的,不管是否产生竞争,任何数据的操作都必须加锁。

乐观锁的核心是CAS,CAS包括内存值、预期值、新值,只有当内存值等于预期值时,才会将内存值修改为新值。

九、乐观锁一定就是好的吗?

乐观锁认为对一个对象的操作不会引发冲突,所以每次操作都不进行加锁,只是在最后提交更改时验证是否发生冲突,如果冲突则再试一遍,直至成功为止,这个尝试的过程称为自旋。

  1. 乐观锁没有加锁,但乐观锁引入了ABA问题,此时一般采用版本号进行控制;
  2. 也可能产生自旋次数过多问题,此时并不能提高效率,反而不如直接加锁的效率高;
  3. 只能保证一个对象的原子性,可以封装成对象,再进行CAS操作;

十、说一下 jsp 的 4 种作用域?

application、session、request、page。

十一、forward 和 redirect 的区别?

  1. forward是直接请求转发;redirect是间接请求转发,又叫重定向。
  2. forward,客户端和浏览器执行一次请求;redirect,客户端和浏览器执行两次请求。
  3. forward,经典的MVC模式就是forward;redirect,用于避免用户的非正常访问。(例如用户非正常访问,servlet就可以将HTTP请求重定向到登录页面)。
  4. forward,地址不变;redirect,地址改变。
  5. forward常用方法:RequestDispatcher类的forward()方法;redirect常用方法:HttpServletRequest类的sendRedirect()方法。

十二、Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式

保证程序只有一个对象的实例,叫做单例模式;

内部类的方式实现单例模式,是线程安全的;

双重验证方式实现单例模式也是线程安全的;

【源码分析设计模式 1】JDK中的单例模式

十三、Spring 有几种配置方式?

1、xml配置文件




    
        
        
        
     

    
        
        
        
    

2、基于注解的方式

项目越来越大,基于xml配置太麻烦,Spring 2.x时代提供了声明bean的注解。

(1)Bean的定义

@Component、@Controller、@Service、@Repository。

(2)Bean的注入

@Autowire

3、基于Java的方式

Spring 3.x以后,可以通过Java代码装配Bean。

@Configuration
public class DemoConfig {
    @Bean
    public User jackma(){
        return new User();
    }
    @Bean
    public Dog dog(){
        return  new Dog();
    }
    @Bean  //两个狗
    public Dog haqi(){
        return new Dog();
    }
}
@Component("jackma")
public class User {
    private String name;
    private int age;
    private Dog dog;

  //get,set方法略
}

 原来就是配置类啊,通过@Bean、@Component、getBean方式进行Bean的注册和发现。

十四、Spring Boot 中的监视器是什么?

监听器也叫listener,是servlet的监听器,可以用于监听web应用程序中某些对象的创建、销毁、增加、修改、删除等动作的发生,然后做出相应的响应处理。当范围对象的状态发生变化时,服务器自动调用监听器对象中的方法,常用于系统加载时进行信息初始化,统计在线人数和在线用户,统计网站的访问量。

配置监听器的方法:

  • 通过@Component把监听器加入Spring容器中管理;
  • 在application.properties中添加context.listener.classes配置;
  • 在方法上加@EventListener注解;

十五、hibernate 中如何在控制台查看打印的 sql 语句?

spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true

十六、说一下 mybatis 的一级缓存和二级缓存?

一级缓存是session级别的缓存,默认开启,当查询一次数据库时,对查询结果进行缓存,如果之后的查询在一级缓存中存在,则无需再访问数据库;

二级缓存是sessionFactory级别的缓存,需要配置才会开启。当进行sql语句查询时,先查看一级缓存,如果不存在,访问二级缓存,降低数据库访问压力。

十七、RabbitMQ中 vhost 的作用是什么?

vhost可以理解为mini版的RabbitMQ,其内部均含有独立的交换机、绑定、队列,最重要的是拥有独立的权限系统,可以做到vhost范围内的用户控制。从RabbitMQ全局考虑,不同的应用可以跑在不同的vhost上,作为不同权限隔离的手段。

十八、如何获取当前数据库版本?

//MySQL,,mysql -v
select version();
//Oracle 
select * from v$version;

十九、Redis和 memecache 有什么区别?

1、Redis相比memecache,拥有更多的数据结构和支持更丰富的数据操作。

(1)Redis支持key-value,常用的数据类型主要有String、Hash、List、Set、Sorted Set。

(2)memecache只支持key-value。

2、内存使用率对比,Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于memecache。

3、性能对比:Redis只使用单核,memecache使用多核。

4、Redis支持磁盘持久化,memecache不支持。

Redis可以将一些很久没用到的value通过swap方法交换到磁盘。

5、Redis支持分布式集群,memecache不支持。

二十、怎么判断对象是否可以被回收?

1、引用计数算法

(1)判断对象的引用数量

  • 通过判断对象的引用数量来决定对象是否可以被回收;
  • 每个对象实例都有一个引用计数器,被引用+1,完成引用-1;
  • 任何引用计数为0的对象实例可以被当做垃圾回收;

(2)优缺点

  • 优点:执行效率高,程序受影响较小;
  • 无法检测出循环引用的情况,导致内存泄漏;

2、可达性分析算法

通过判断对象的引用链是否可达来决定对象是否可以被回收。

如果程序无法再引用该对象,那么这个对象肯定可以被回收,这个状态称为不可达。

那么不可达状态如何判断呢?

答案是GC roots,也就是根对象,如果一个对象无法到达根对象的路径,或者说从根对象无法引用到该对象,该对象就是不可达的。

以下三种对象在JVM中被称为GC roots,来判断一个对象是否可以被回收。

(1)虚拟机栈的栈帧

每个方法在执行的时候,JVM都会创建一个相应的栈帧(操作数栈、局部变量表、运行时常量池的引用),当方法执行完,该栈帧就从栈中弹出,这样一来,方法中临时创建的独享就不存在了,或者说没有任何GC roots指向这些临时对象,这些对象在下一次GC的时候便会被回收。

(2)方法区中的静态属性

静态属性数据类属性,不属于任何实例,因此该属性自然会作为GC roots。这要这个class在,该引用指向的对象就一直存在,class也由被回收的时候。

class何时会被回收?

  • 堆中不存在该类的任何实例
  • 加载该类的classLoader已经被回收
  • 该类的java.lang.class对象没有在任何地方被引用,也就是说无法通过反射访问该类的信息

(3)本地方法栈引用的对象

二十一、java 中都有哪些引用类型?

1、强引用

Java中默认声明的就是强引用,比如:

Object obj = new Object();
obj = null;

只要强引用存在,垃圾回收器将永远不会回收被引用的对象。如果想被回收,可以将对象置为null; 

2、软引用(SoftReference)

在内存足够的时候,软引用不会被回收,只有在内存不足时,系统才会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会跑出内存溢出异常。

byte[] buff = new byte[1024 * 1024];
SoftReference sr = new SoftReference<>(buff);

3、弱引用(WeakReference)

进行垃圾回收时,弱引用就会被回收。

4、虚引用(PhantomReference)

5、引用队列(ReferenceQueue)

引用队列可以与软引用、弱引用、虚引用一起配合使用。

当垃圾回收器准备回收一个对象时,如果发现它还有引用,就会在回收对象之前,把这个引用加入到引用队列中。

程序可以通过判断引用队列中是否加入了引用,来判断被引用的对象是否将要被垃圾回收,这样可以在对象被回收之前采取一些必要的措施。

 

上一篇:Java面试题总结(乱序版,2020-08-18)

下一篇:Java面试题总结(绝对经典)

 

Java面试题总结(乱序版,2020-08-20)_第3张图片

 

你可能感兴趣的:(高频面试题)