工作五年来的面试题目总结之-java基础

数据类型

String s = new String("xyz");创建了几个对象?

String对象;“xyz”字符串常量对象,放在字符串池。

基本数据类型,字符串引用都放在栈中;引用对象放在堆中,地址指向栈中的引

反射

什么是反射?

运行状态中,对任意一个类,都能知道这个类的所有属性和方法;任意一个对象都能调用他的任意属性和方法;这种动态获取信息以及动态调用对象的方法的功能在java中被称为反射。

三步

  • 获得CLass对象
  • 实例化对象,获得属性、方法、构造函数
  • 访问属性、调用方法、调用构造函数创建对象

获取Class对象的三种方式

  • 对象的geiClass()方法
  • 数据类型的静态属性.class方法
  • Class.forName(类的全路径)

哪里用到反射

  • JDBC加载数据库驱动
  • Web服务器反射调用Sevlet的方法
  • Spring中Autowired依赖注入

Class.forName和ClassLoader的区别?

Class.forName除了将类的.class文件加载到JVM中,还会对类进行解释,执行类中static方法

ClassLoader只会干一件事,将.class文件加载到JVM中,不会执行static方法,只有newinstacne的时候才会执行static

什么是序列化

保存对象在内存中的状态,并且可以把保存对象的状态在读取出来

注解

JDK5.0引入的一种注释机制

作用在代码上的注解: **@Overide、@Deprecated 、@SuppressWarnings **

@Overide:检查该方法是否是个重写方法,如果发现父类、或者引用的接口中没有该方法,会编译报错

@Deprecated:标记方法是过去式,引用的时候会编译告警

@SuppressWarnings:编译时忽略警告

四种元注解@Retention、@Documented、@Target、@Inherited

@Retention:作用范围,代码、编入class、运行时

@Documented:是否包含在用户文档中

@Target:标记该注解用来标注在哪里,属性,方法,类

@Inherited:标记这个注解继承于哪个注解类

实现自定义注解

  • 1、使用关键字@interface创建自定义注解
  • 2、使用元注解标注该注解行为,@Retention、@Target
  • 3、需要使用的注解类添加注解
  • 4、实现注解处理逻辑;获取类上的注解,通过属性判断做出决定

集合

Map

HashMap

初始容量:16,负载因子:0.75f,扩容时机:16*0.75=12 红黑树转换:链表长度大于8

为什么长度是2^n次方?

  • 效率的原因,取余比按位与操作效率慢,但是如果保证长度是2^n的话,结果是一致的
  • 保证了长度是2^n,这样当长度-1操作以后,保证每个位置上都是1,这样让每一位置都参与运算,更好的减少hash碰撞

put方法

  • 底层是同Node[]数组进行存储,初始情况会检查数组长度,进行初始化

  • 根据长度-1与hash值,计算在Node[]中的位置,检查该位置是否有值,没有值,构建新节点存放,记录修改次数,计算是否需要扩容(判断阈值)

  • 如果该位置有值,计算该位置的hash值与传递进来的hash是否相同,key是否相同,相同就覆盖

  • key不相同,判断当前节点的next是否位空,如果为空,构建新节点,添加到链表尾部,并且判断链表的长度是否大于8,如果大于8,将当前链表转变成红黑树,如果下一个节点不为空,并且key相同,直接覆盖

get方法

  • 计算key的hash值
  • 通过数组确定key的位置,拿到Node链表第一个节点,判断hash是否相同,如果相同,判断key是否相同,相同,返回value
  • 如果key不相同,遍历链表,如果链表是红黑树,通过红黑树遍历查找,如果是链表通过链表查找

为什么链表长度>8的时候转变为红黑树?

在良好hashcode影响下,链表中的节点遵从泊松分布,在概率统计下,链表长度达到8的概率已经接近千分之一了,而且此时链表的性能已经很差了,因此,使用红黑树算是一种性能提升吧,如果在理想的情况下,链表长度不到8就已经扩容了。

hash方法

key的hashcode值与hashcode的高16做异火操作。

为什么与高16做异或?

是为了让高16位参与运算,因为int是32位,取中间16位,当数值小于216次方,与自身异或结果不变,当大于216次方的时候,让高16参与计算,增加了随机性,让后面做定位桶位置的时候减少hash碰撞。

扩容操作

扩容时机:初始化、size>阈值

扩容操作:

  • 判断旧数组容量是否大于0
  • 大于0,判断容量是否大于2^30次方,直接将容量调整到最大,如果旧容量>=默认容量(考虑定义好初始容量<16的情况吧),进行扩容,容量变成以前的两倍,阈值也进行两倍的扩大
  • 进行数据的搬移;数组扩大两倍,遍历原来的数据,所有元素重新hash存放到新数组

HashMap和Hashtable的区别?

  • HashMap允许key-value位null,但是Hashtable不可以,value会报空指针
  • HashMap是线程不安全的,Hashtable是线程安全的。
  • 初始值和扩容因子不同;HashMap初始值是16,扩容后位2倍;Hashtable,初始值是11,每次是原始容量*2+1
  • key的hash算法不同,Hashtable直接使用的是key的hashCode方法。

ConcurrentHashMap是如何保证线程安全的?

  • 1.7使用分段锁技术
  • 1.8放弃了分段锁,使用了CAS+sychronized实现线程安全

ConcurrentHashMap是弱一致性,迭代的时候可以添加元素,HashMap是强一致性,添加元素会报异常

为什么 ConcurrentHashMap 的 key 和 value 不能为 null?

因为空指针异常

ConcurrentHashMap 的put方法

  • 定位node节点
  • 拿到首节点为空,casput数据
  • 不为空,查看是否有其他线程在扩容,帮助扩容
  • 为空,sychronized锁住first节点,判断链表还是红黑树,插入

ConcurrentHashMap是否存在线程不安全的情况?

  • 本身是线程安全的,如果你自己的操作不是原子的,比如,取出来,操作,在放回去,就可能有问题,可以使用replace方法替换。

ConcurrentHashMap的get会不会有并发问题?

不会,get逻辑比较简单,value又是volatile修饰的,保证了内存可见性

使用LinkedHashMap实现LRU缓存淘汰算法

LinkedHashMap底层使用的链表存储,迭代的时候按照插入的顺序进行迭代

构造方法传入true,这样在get以后,会移动元素的顺序,实现removeEldestEntry方法,根据这个特性进行LRU

Set

HashMap和HashSet的区别?

HashMap HashSet
HashMap实现了Map接口 HashSet实现了Set接口
HashMap储存键值对 HashSet仅仅存储对象
使用put()方法将元素放入map中 使用add()方法将元素放入set中
HashMap中使用键对象来计算hashcode值 HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false
HashMap比较快,因为是使用唯一的键来获取对象 HashSet较HashMap来说比较慢
查询有序 无序

HashSet应该保证实现hashcode和equals方法,因为对比时是通过这两个值进行比较的

TreeMap和TreeSet如何比较元素?

  • TreeSet要求存放的数据必须实现Comparable接口,接口提供compareTo方法,插入元素的时候会调用该方法进行比较
  • TreeMapa要求key必须实现Comparable接口,内部put调用compareTo方法

List

Vector

底层使用数组线程安全使用的是sychronized关键字进行保证,默认容量:10

get方法都加了线程安全关键字

LinkedList

底层使用双向链表线程不安全,底层方法为进行同步

Arraylist

底层使用数组线程不安全初始容量:0,第一次添加操作后容量扩容,扩容后是10

线程安全的三种list

  • Collections.synchronizedList方法可以实现线程安全的
  • 使用Vector
  • juc下的CopyOnWriteArrayList类是线程安全的(读写分离,最终一致、写时复制)
    • CopyOnWriteArrayList不能指定容量,初始容量0,集合多大,底层数组就多大
    • 只能保证数据的最终一致性,不能保证实时,如果想实时,不建议使用

ArrayList的扩容机制

  • add方法添加元素,如果默认情况下,容量=10,取size+1,和容量的最大值,将得到的数值>容量,扩容
  • 扩容后容量是之前的1.5倍,如果超过了集合的阈值=Interger.MAX_VALUE-8(-8因为对象头最多占用8个位),hugeCapacity()方法
  • 数组拷贝

综合比较

set、list(包含queue)、map
1、Collection:集合list、set、Queue的最基本的接口
2、Iterator:迭代器,可以通过迭代器遍历集合中的数据
3、Map:映射的基础接口

Collection:
    1、List:
        ArrayList:
            1、排列有序,可重复
            2、底层使用数组
            3、速度快、增删慢
            4、线程不安全
            5、容量不够,当前容量*1.5+1
            6、可以添加null对象
        Vector:
            1、排序有序,可重复
            2、底层使用数组
            3、速度快,增删慢
            4、线程安全、效率低
            5、容量不够,默认是扩展一倍
        LinkedList:
            1、排列有序,可重复
            2、底层使用双向循环链表
            3、查询速度慢,增删快,add,remove方法快
            4、线程不安全
    2、Set
        1、HashSet
            1、排列无序,不可重复
            2、底层使用hash表实现
            3、存取速度快
            4、内部使用HashMap
        2、TreeSet
            1、排列无序,不可重复
            2、底层使用二叉树
            3、排序存储
            4、内部使用TreeMap和SortedSet
        3、LinkedHashSet
            1、采用hash表存储,双向链表记录插入顺序
            2、内部是LinkedHashMap
Map
    1、HashMap
        1、键不可重复、值可以重复
        2、底层使用哈希表
        3、线程不安全、
        4、允许key为null,value也可以为null
    2、Hashtable
        1、键不可重复,值可重复
        2、哈希表
        3、线程安全
        4、key、value都不可以为null,value为空直接抛出异常了,key计算hash报错

comparable和Comparator的区别?

  • Comparable接口在lang包下面,当前对象其他对象的比较,有一个compareTo(Object o)方法用来排序
  • Comparator接口在util包下面,比较两个传入对象的大小,有一个compare(Object o1,Object 02)方法用来排序

IO

IO
1、阻塞IO:
用户线程发出IO请求以后,内核查看数据是否就绪,没有准备好,用户线程处于阻塞状态,用户线程交出CPU,数据就绪以后,内核讲数据拷贝到用户线程,返回加过给用户线程,用户线程解除block状态
2、非阻塞IO:
用户线程发起read以后,如果没有就绪马上得到一个结果,可以再次read,一旦数据准备好,并且再次请求的时候就会复制,用户线程不会交出CPU。导致CPU占用率很高
3、多路复用IO
java的NIO实际上就是多路复用IO
由内核进行轮训,比用户线程高效
因为是轮训,因此如果当前响应事件很大,导致后续的事件得不到处理,影响新的事件轮训
4、信号驱动IO模型
用户线程发起请求的时候会给对应的socket一个注册新号,内核准备就绪給用户线程一个新号,用户线程接收到信号以后进行实际的io请求操作。
5、异步IO模型
用户线程发起read操作以后,内核立刻返回,说明read请求成功了,内核会准备好数据,并且将数据复制到用户线程,然后发送信号到用户线程,用户线程可以直接使用数据。

NIO
通道、缓冲区、selector
IO面向流、NIO面向缓冲区

Stream是单向的,channel是双向的,可以用来读,又可以进行写
Buffer:缓冲区,实际上是一个容器,是一个连续数组
Selector:检测多个注册的通道上是否有事件发生,如果有事件发生,获取事件然后针对事件进行相应的响应处理。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容