Java面试题--自用

每天进步一点点

一个字节 = 8位二位数

1.对象在内存中的存储布局是什么样子?

答:如果类中生成了String对象,padding仍然要补4个字节,因为生成的String对象的字符串并不存在内存里,存在内存里的是指针。

对象在内存中划分为四部分,markword、classpointer、instance data、padding;

在64位的虚拟机中markword都占8个字节,class pointer默认压缩占4个字节,不压缩占8个字节,此处没有实例数据,因此instance data为0字节,加起来是12字节,12不可被8整除,因此padding补上4个字节,总共为16个字节。

2.Object o = new Object();在内存中占用多少字节?

答:总共占用16个字节;

对象在内存中划分为四部分,markword、classpointer、instance data、padding;

在64位的虚拟机中markword都占8个字节,class pointer默认压缩占4个字节,不压缩占8个字节,此处没有实例数据,因此instance data为0字节,加起来是12字节,12不可被8整除,因此padding补上4个字节,总共为16个字节。

3.对象头具体包括什么?

答:对象头包括markwork与class pointer。

markword主要包括三大信息:锁信息,hashcode,GC(垃圾回收)信息(颜色)。

GC垃圾回收为三色标记法,对象的颜色就保存在markword中。

4.请解释一下对象的创建过程?(半初始化)

第一步,申请空间,设默认值;

第二步,调用构造方法,设初始值;

第三步,建立关联。

5.ArrayList和LinkedList的区别

答:arraylist是基于数组来实现的,linkedlist是基于链表来实现的。linkedlist比arraylist更占内存,因为linkedlist为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

由于arraylist基于数组实现,数据是一整块的放在一起的,当进行插入删除操作时需要将插入或删除位置后面的所有数据进行移动,所以时间复杂度要高一些,为O(n),而linkedlist进行插入删除的时间复杂度为O(1)。

相对于arraylist,linkedlist插入更快,因为linkedlist不像arraylist一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组。

更适用linkedlist的场景:

应用不会随机访问数据,读取数据少,插入删除多。

6.JDK1.8的新特性有哪些?

答: ①接口的默认方法
②Lambda表达式
③函数式接口

7.java接口与抽象类的区别

答:相同:都不能实例化;可以将抽象类和接口类型作为引用类型;一个类如果继承了某个抽象类或者实现了某个接口,都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。

不同:抽象类中可以定义构造器,可以有抽象方法和具体方法,接口中的成员全都是public的,抽象类中可以定义成员变量,由抽象方法的嘞必须被声明为抽象类,而抽象类未必要有抽象方法,抽象类中可以包含静态方法,一个类只能继承一个抽象类。接口中不能定义构造器,方法全部都是抽象方法,抽象类中的成员可以是private、默认、protected、public,接口中定义的成员变量实际上都是常量,接口中不能有静态方法,一个类可以实现多个接口。

除了在语法上,还有语义上的区别。

抽象类更重要的是描述的一个抽象的概念,是我们能描述得出来的,比如动物、哺乳动物、植物、食物;接口描述的是某些共同事物所拥有的共同特征

8.hashcode与equals怎样使用?

答:hashcode的底层是通过hashmap实现的,hashmap是一对一对的存放数据,通过一个哈希算法对key值进行计算得到。hashmap通过hashcode对元素进行存放,存放在散列表里,哈希值重复了就接一个链表下去,hashcode方法就是通过哈希值确定是否相同的,而equals是通过对比具体元素是否相等。

9.==和equals有哪些区别?

答:都是用来判断比较的两个对象是否相等。==一般比较的是基本数据类型,如果比较的是基本数据类型,则比较数值是否相等,如果比较的是引用数据类型,则比较的是对象的地址值是否相等。equals()不能用于基本数据类型的变量,如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址。总的来说,和equals都是判断比较对象的地址值是否相等,但equals重写后比较的是内容是否相等,而判断基本数据类型的时候比较的是对象值是否相等。

10.java中的异常处理机制是什么?

答:throw,try,catch,finally,throws

11.重写和重载有哪些区别?

答:重载要求方法名相同,参数列表一定不同,重载与方法的返回值无关,可以抛出不同的异常,可以有不同的修饰符;重写参数列表,返回类型必须与被重写的方法完全一致,访问权限不能比父类被重写的方法更低,不能抛出父类没有的异常。

12.String、StringBuffer、StringBuilder的区别及使用场景?

答:String是只读字符串,也就是说String引用的字符串内容是不能被改变的。不可改变的意思是String指向的对象是无法改变的,如果str=“abc” -> “bcd”,不是“abc”这个字符串改变了而是str的指向改变了,因此说String字符串不可变。

StringBuilder:当声明一个StringBuilder对象的时候,它实际上指向堆中的一块空间,这个堆中的这块空间里有两个具体的属性,一个是value属性,一个是count属性,value属性底层对应的就是一个数组,这个数组里存储的就是一个个一个的字符,对StringBuilder进行拼接的时候就是在这个数组里放字符,count属性里面保存的就是value属性数组被占用的长度,当数组放不下的时候,底层就会进行数组扩容,它就会开辟一个新的长度更长的数组,将value从旧的数组改为指向新的数组,并将之前数组里的内容复制到新的数组中。StringBuffer与StirngBuilder的底层基本相同,不一样的是StringBuffer是线程安全的,而StringBuilder不是线程安全的,StringBuffer是JDK1.0开始的,而StringBulider是JDK1.5开始的,相较于StringBuffer,StringBuilder效率更高。

13.怎样声明一个类不会被继承,什么情况需要这么做?

答:被final修饰的类无法被继承,当一个类的所有方法都不需要被重写就可以用final修饰,比如Math类。

14.自定义异常在生产中如何应用?

①系统中有些错误符合java语法,但不符合业务逻辑;②在分层的软件结构中,通常是在表现层统一对系统其他层次的异常进行捕获处理。

15.事务的四大特征是什么?是靠什么保证的?

事务的四大特征:原子性、一致性、隔离性和持久性(ACID); 原子性由undolog日志来保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql,一致性是由其他三大特性保证,程序代码要保证业务上的一致性,隔离性是由MVCC来保证,持久性由redolog来保证,mysql修改数据的时候会在redolog中记录一份日志数据,就算数据没有保存成功,只要日志保存成功了,数据仍然不会丢失。
16.BeanFactory和ApplicationContext有什么区别?

答:

相同点:

spring提供了两种不同的IOC容器,一个是BeanFactory,另外一个是AoolicationContext,它们都是javainterface(接口),ApplicationContext继承于BeanFactory,是BeanFactory的子接口;它们都可以用来配置XML属性,也支持属性的自动注入;两者都提供了一种方式,使用grtBean(“bean name”)获取bean。

不同:

当调用getBean()方法时,BeanFactory进实例化bean,而ApplicationContext在启动容器的时候实例化单例bean,不会等待调用getBean()方法时再实例化;BeanFactory不支持国际化,即i18n,但ApplicationContext提供了对它的支持;BeanFactory支持监听器,ApplicationContext不支持;BeanFactory的一个核心实现时XMLBeanFactory而AoolicationContext的一个核心实现是ClassPathXmlApplicationContext,Web容器的环境我们使用WebApplicationContext并且增加了getServletContext方法;如果使用自动注入并使用BeanFactory,则需要使用API注册AutoWriedBeanPostProcessor,如果使用ApplicationContext,则可以使用XML进行配置;简而言之BeanFactory提供基本的IOC和DI功能,而ApplicationContext提供高级功能,BeanFactory可用于测试和非生产使用,但ApplicationContext是功能更丰富的容器实现,应该优于BeanFactory。

17.HashMap和HashTable的区别是什么?

①HashTable线程同步,HashMap非线程同步。

②HashTable不允许<键值>有空值,HashMap允许<键,值>有空值。

③HashTable使用Enumeration, HashMap使用lterator,

④HashTable中hash数组的默认大小是11,增加方式的old*2+1,HashMap中hash数组的默认大小是16, 增长方式是2的指数倍。

⑤hashtable继承与Dictionary类, hashmap继承自AbstractMap类

18.hashmap有哪些线程安全的方式?

答:

方法一:

通过Collections.synchronizedMap(返回一个新的Map,这个新的map就是线程安全的。返回的并不是HashMap,而是一一个Map的实现。

方法二:

重新改写了HashMap,具体的可以查看java.util.concurrent.ConcurrentHashMap。这个方法比方法一有了很大的改进。

方法一特点:

通过Collections.synchronizedMap()来封装所有不安全的HashMap的方法,就连toString, hashCode都进行了封装.封装的关键点有2处,1)使用了经典的synchronized来进行互斥, 2)使用了代理模式new了一个新的类,这个类同样实现了Map接口。在Hashmap上面,synchronized锁住的是对象,所以第一个申请的得到锁,其他线程将进入阻塞,等待唤醒。优点:代码实现十分简单,一看就懂。缺点:从锁的角度来看,方法一直接使用了锁住方法基本上是锁住了尽可能大的代码块。性能会比较差。

方法二特点:

重新写了HashMap,比较大的改变有如下几点:使用了新的锁机制,把HashMap进行了拆分,拆分成了多个独立的块,这样在高并发的情况下减少了锁冲突的可能,使用的是NonfairSync。这个特性调用CAS指令来确保原子性与互斥性。当如果多个线程恰好操作到同一个segment上面,那么只会有一个线程得到运行。优点:需要互斥的代码段比较少,性能会比较好。ConcurrentHashMap把整个Map切分成了多个块,发生锁碰撞的几率大大降低性能会比较好。缺点:代码繁琐。

19.MVCC(多版本并发控制)解决的问题是什么?

答:

数据库并发场景有三种,分别为:

读读:不存在任何问题,也不需要并发控制;

读写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读、幻读、不可重复读;

写写:有线程安全问题,可能存在更新丢失问题;

MVCC是一种用来解决读写冲突的无锁并发控制,也就是为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照,所以MVCC可以为数据库解决以下问题:

①在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能;

②解决脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失问题。

20.MVCC实现原理是什么?

答:mvcc的实现原理主要依赖于记录中的三个隐藏字段,undolog,read view来实现。

21.mybatis的优缺点有哪些?

答:1、Mybait的优点:

(1)简单易学,容易上手(相比于Hibernate) 基于SQL编程;

(2) JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;

(3)很好的与各种数据库兼容(因为MyBatis使用DBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持,而JDBC提供了可扩展性,所以只要这个数据库有针对Java的jar包就可以就可以与MyBatis兼容),开发人员不需要考虑数据库的差异性。(4)提供了很多第三方插件(分页插件/逆向工程) ;(5)能够与Spring很好的集成;(6) MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,解除sq|与程序代码的耦合,便于统一管理和优化,并可重用。

(7)提供XML标签,支持编写动态SQL语句。

(8)提供映射标签,支持对象与数据库的ORM字段关系映射。

(9)提供对象关系映射标签,支持对象关系组建维护。

2、MyBatis框架的缺点:

(1) SQL语句的编写工作量较大,尤其是字段多关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。

(2) SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

22.mybatis中#{}和${}的区别是什么?

答:一个是预编译处理,一个是字符串替换;

#{}会将其替换为?,调用PreparedStatement的set()方法来赋值,而mybatis在处理${}的时候会将其替换成变量的值,也就是说此处可以传入很多东西,容易出现sql注入。

23.MySQL的隔离级别有哪些?

答:读未提交(易出现脏读);读已提交(大多数数据库系统默认隔离级别,但存在不可重复读问题);可重复读(MySQL数据库的默认隔离级别,会出现幻读问题,通过MVCC可以解决);可串行化。

24.索引的基本原理是什么?

答:索引在MySQL中也叫是一种"键", 是存储引擎用于快速找到记录的一-种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。索引优化应该是对查询性能优化最有效的手段了。索弓|能够轻易将查询性能提高好几个数量级。索弓相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。

25.有关Redis的雪崩问题、穿透问题、击穿问题。

答:

雪崩问题:Redis中大量的key在同一时间失效,导致大量的请求打到数据库中,使数据库崩溃。

解决方案:设置不同的失效时间,在缓存设置的时候随机初始化失效时间,这样就不会同时有大量key同时失效;Redis一般是集群部署,把这些热点的key分布到不同的Redis节点上去;不设置失效时间,这样就不会存在雪崩问题了;给缓存设置定时任务,假设缓存失效时间是三小时,那就设置定时任务在缓存失效之前重新把缓存跑进来,刷新缓存失效时间。

穿透问题:用户使用Redis中没有的数据进行访问,以为Redis中不存在这样的数据,请求就会到达数据库,这就是穿透问题。

解决方案:将数据库查询所得到的数据返回给Redis,无论是结果为空还是其他值,这样可以避免大量重复的Redis中不存在的数据请求导致穿透问题,但这样无法避免更改请求数据的问题;还可以直接禁用恶意用户的ip,但这样仍然可以通过更换ip做到缓存穿透;对参数的合法性进行校验,在判断这个参数不合法的时候就直接return掉;使用布隆过滤器。

击穿问题:大量的请求同时请求一个热点key,但此时热点key突然失效,导致大量的请求打到数据库,致使数据库崩溃。

解决方案:设置缓存永不失效;使用分布式锁,如果是单体应用就可以使用互斥锁,在请求数据库之前加锁,使得同时只有一个线程访问数据库,抢到锁的线程进行访问,得到结果后数据库将此结果返回给Redis,这样其他没有抢到锁的线程就可以直接访问Redis得到结果了。

布隆过滤器:

底层实现原理是一个二进制数组,将要存储的数据经过多次哈希计算得到哈希值,然后将哈希值分别存在这个二进制数组里面。例如“你好”经过三个不同的哈希函数计算得到三个哈希值:3,5,7。得到哈希值之后就将对应数组下标里的值从0改为1。当检查一个数据存不存在的时候就可以用布隆过滤器来检查,但是会存在误判率,可以通过增加哈希函数来减小误判率。

26.线程池中execute()和submit()有什么区别?
答:可以传入的参数类型不同,execute继承Executor类,只有一个实现,需要传入Runnable类型的参数,而submit()继承的是ExecutorService类,有三种重载,可以传入Runnable类型和Callable类型的数据;返回值不同,execute()没有返回值,返回类型为void,submit()返回类型为future;处理异常的方式不同,execute()遇到异常的时候会显式的打印异常信息,而submit不会。

你可能感兴趣的:(java,jvm,面试)