面试题总结02

1.==和equals的区别

== 用来比较基本类型的值和引用类型的地址值
equlas是Object类的比较方法,原生的equals也是使用 == 来进行比较的如果对引用类型进行过比较,通常是将equals进行重写Java中有很多类已经重写了equals
比如String类,那我也查看了一下String类重写了的equals的源码它是先比较长度,如果长度相同,依次比较每个字符,完全一致之后返回true
比较的就是字符串的内容,但是String类被final修饰了所以不能改变String的equals了如果我们的类想自定义比较规则,可以在类里面对equals进行重写

2.Java8新特性有哪些

接口中默认方法 lambda表达式 Streams(流)Date API(日期相关API)Annotations(注解)

3.Lambda表达式是啥?有什么优点和缺点?

lambda表达式,也被称为闭包,lambda允许把函数作为一个方法的参数,使用Lambda表达式可以使代码变得更加简洁紧凑

  • 优点∶
    1 代码更加简洁
    2 减少匿名内部类的创建,节省资源
    3 使用时不用去记忆所使用的接口和抽象方法
  • 缺点∶
    1 不易于后期维护,必须熟悉lamdba表达式和抽象方法中参数的类型
    2 可读性差
    3 不容易调试
    4 若其他程序员没有学习过lambda表达式,代码不容易让其他语言的程序员看懂

4.TCP和UDP区别

  1. TCP基于连接,UDP基于无连接
  2. TCP要求系统资源较多,UDP较少
  3. UDP程序结构比较简单
  4. TCP保证数据的正确性,UDP可能丢包
  5. TCP保证数据顺序,UDP不保证

5.描述下TCP连接4次挥手的过程?为什么要4次挥手 - 了解

因为TCP是全双工,每个方向都必须进行单独关闭.关闭连接时,当Server端收到FIN报文(结束标志)很可能并不会立即关闭Socket,所以只能先回复一个ACK报文(确认字符)告诉Client端,“你发的FIN报文我收到了”.只有等到Server端所有报文都发送完了,才能发送FIN报文,因此不能一起发送,故需要4次握手

6.创建线程的三个方法

  1. 通过继承Thread类创建线程类
  2. 实现Runnable接口创建线程类
  3. 通过Callable和Future接口创建线程

7.开启一个线程的方法

  1. 继承Thread类,新建一个当前类对象,并运行其start()方法
  2. 实现Runnable接口,然后创建当前类对象,接着新建Thread对象把当前类对象传进去,最后运行Thread对象的start()方法
  3. 实现Callable接口,新建当前类对象,在新建FutureTask类对象时传入当前类对象,接着新建Thread类对象时传入FutureTack类对象,最后运行Thread对象的start()方法

8.线程安全问题如何产生,Java如何保证线程安全

多条线程同时操作同一个资源可能会产生线程安全问题
解决线程安全问题∶

  1. 使用同步代码块
  2. 使用同步方法
  3. 使用lock锁机制,通过创建lock对象,采用locak()加锁,unlock()解锁,来保护指定代码块

补充∶
多线程同步有哪些方式
使用synchronized关键字,新版本的synchronized已经优化了性能问题
wait和notify
(活锁和死锁问题可以简单了解)
活锁∶需要同步的对象没有被锁锁住,锁错了对象
死锁∶释放锁之前需要获取另外一个被锁住但无法释放的对象,被称之为死锁)
(不用记)
使用特殊域变量 volatile实现线程同步使用重入锁少赵蛋
使用局部变量使用阻塞队列解
使用原子变量

9.了解线程和进程的区别

操作系统中可以拥有多个进程,一个进程里可以拥有多个线程,线程在进程内执行
从内存上来说∶每个进程拥有独立的内存空间,同一进程下的线程共享该进程的内存空间,不单独分配
同一进程的线程之间可以通过wait()等方法进行直接通信,但是操作系统中的进程之间需要使用"进程间通信"来进行通信

  1. 线程可以控制同一进程的其他线程。进程无法控制兄弟进程,只能控制其子进程
  2. 进程拥有自己的内存空间。线程使用进程的内存空间,且要和该进程的其他线程共享这个空间而不是在进程中给每个线程单独划分一点空间
  3. 同一进程中的线程在共享内存空间中运行。而进程在不同的内存空间中运行
  4. 线程可以使用wait(),notify(),notifyAll()等方法直接与同一进程的其他线程进行通信。而进程需要使用"进程间通信"来对操作系统中的其他进程通信

10.反射的作用(基本原理),反射创建类实例的三种方式是什么

反射机制就是使lava程序在运行时具有自省的能力,通过反射我们可以直接操作类和对象,比如说获取某个类的定义,获取类的属性和方法还有构造方法等,就算是私有的也可以获取
创建类的实例的三种方式是
创建class 对象

  1. 对象实例.getClass()
  2. Class.forName(包名.类名)创建
  3. 类名.class 创建

newInstance() 创建当前类对象
如何使用反射

  1. 通过class对象获取一个属性对象
    getFields() 获取某个类的所有的公开(public)的字段,包括父类中的字段
    getDeclaredFields>(); 获取某个类的所有声明的字段,包括public private proteced 不包括父类声明的字段
  2. 通过class对象获取一个方法对象
    getMethod(“方法名”….所有公开的方法
    getDeclaredMethod(“方法名”)可以任意修饰符的方法 但是不能执行私有
    setAccessible(true)(让私有的方法可以执行)
  3. 执行方法
    Method.invoke(obj实例对象,obj可变参数)(是有返回值的)

11.Java中常用集合及特点

List :ArrayList,LinkedList,Vector,Stack
Set :LinkedSet,HashSet,TreeSet
Map:HashMap,LinkHashMap,TreeMap
Vector∶底层是数组,查询快,增删慢,线程安全,效率低,默认长度是为10,超出会100%,变成20,浪费空间
ArrayList∶基于数组,便于按照index访问,超过数组需要扩容,扩容成本高
LinkedList∶使用链表实现,无需扩容
HashSet∶底层数据结构是哈希表(无序,唯一),通过hashcode()和equals保证元素唯一
TreeSet∶底层是红黑树(唯一,有序)
HashMap∶空间换时间,哈希冲突不大的情况下查找数据性能高

12.如何选用集合

主要是根据集合的特点来选用,比如我们需要根据键值获取到元素值就选用Map接口下的集合

  1. 需要排序时选择TreeMap,
  2. 不需要排序是选用HashMap,
  3. 需要保证线程安全用ConcurrentHashMap

当我们只需要存放元素时,就可以选择实现Collection接口的集合

  1. 需要保证元素唯一时可以使用TreeSet或HashSet
  2. 不需要唯一,使用ArrayList或者LinkedList

13.ArrayList和LinkedList的区别

从线程安全来说
都不是同步的,都不能保证线程安全
底层数据结构
ArrayList底层使用的是Object数组
LinkedList底层使用的是双向链表数据结构(jdk1.6之前是循环链表JDK1.7取消了循环)
插入和删除是否影响元素
ArrayList采用数组存储,插入元素和删除元素的时间复杂度受元素位置影响如果在末尾追加这种相对时间复杂度容易一些,直接增加数组容量就可以了
如果在指定位置追加,不仅仅要增加容量,还要让元素向后挪动一位,时间复杂度比较高
LinkedList采用链表存储,如果是在头尾插入或者删除不受位置影响
如果在指定位置插入元素,需要先移动到指定位置时间复杂度相对ArrayList在末尾追加的难度几乎一致
因此频繁增删的话可以选择LinkedList
是否支持快速随机访问
LinkedList不支持高效的随机元素访问,但是ArrayList基于数组下标,非常快
内存空间占用
ArrayList的空间浪费在List列表结尾会预留一定内容空间
LinkedList的空间花费则体现在它每一个元素都是消耗比ArrayList更多空间
总结:除非只有大量增删操作,使用LinkedList否则都建议使用ArrayList

14. HashMap和Hashtable区别

线程安全上来看
HashMap是非线程安全的
Hashtable是线程安全的,因为它内部的方法基本都经过synchronized修饰,效率因为线程安全问题,HashMap要比Hashtable效率高一点
(Hashtable基本被淘汰,不要再代码中使用,如果想要线程安全,我们经常使用ConcurrentHashMap)
对于Null key 和Null value的支持上来看
HashMap可以存储nul的key和value的,但是null作为键,只能有一个,null作为值,,可以有多个
HashTable不可以有null键和null值,否则会抛出NPE
初始容量和扩容机制

  1. 创建时不指定大小
    Hashtable默认初始大小为11,每次扩容,变为原来的2n+1
    HashMap默认初始大小为16之后每次扩容,容量变为原来的二倍
  2. 创建时指定大小
    Hashtable会直接使用你给的大小
    HashMap会将其这设置为比输入值大的并且为2幂次方大小

底层数据结构
JDK1.8之后的HashMap在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认8)
将链表转换为红黑树,减少搜索时间,Hashtable没有这种机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值