java面试八股文2

一、Object中有哪些方法  


protected Object clone()--->创建并返回此对象的一个副本。
boolean equals(Object obj)--->指示某个其他对象是否与此对象“相等
protected void finalize()--->当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
Class<? extendsObject> getClass()--->返回一个对象的运行时类。
int hashCode()--->返回该对象的哈希码值。
void notify()--->唤醒在此对象监视器上等待的单个线程。
void notifyAll()--->唤醒在此对象监视器上等待的所有线程。
String toString()--->返回该对象的字符串表示。
void wait()--->导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
      void wait(long timeout)--->导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll()方法,或者超过指定的时间量。
      void wait(long timeout, int nanos)--->导致当前的线程等待,直到其他线程调用此对象的 notify()

二、说一下集合体系

(1)我们先分析一下使用数组的弊端:
①长度开始时必须指定,并且一旦指定,不能更改
②保存的元素必须为同一类型
③增加/删除元素比较麻烦
(2)集合的好处
①可以动态保存任意多个对象,使用比较方便
②提供了很多方便的操作对象的方法:add、remove、set、get等

(3)集合的框架体系如下:
①单列集合②双列集合

(4)COW并发容器
①COW并发容器,全称Copy On Write容器,写时复制容器(即读写分离容器)
②原理:
向容器中添加元素时,先将容器进行Copy复制出一个新容器,然后将元素添加到新容器中,再将原容器的引用指向新容器。并发读的时候不需要锁定容器,因为原容器没有变化,所以可以读取到原容器中的值,使用的是一种读写分离的思想。
③这种设计的好处是什么?
注意上面的操作arr数组本身是无锁的,没有锁,在添加数据的时候,做了额外的复制;此时如果有线程来读数据,那么读取的是
老arr的数据,此时arr的地址还没有改呢,在添加元素的过程中,无论有多少个线程来读线程,读的都是原来的arr,不是新的arr,
所以性能很高,读写分离。提高了并发性能,如果再读就会再复制
④注意
CopyOnWrite容器只能保证数据的最终一致性,不能保证数据实时一致性。所以如果你希望写入的数据,马上就能读到,就不要
再使用CopyOnWrite容器了
⑤适合特定场合
这个应用场景显而易见,适合读多写少的情况。如果一万个线程都添加操作,都在集合中添加数据,数组就会不断复制,长度不断+1,
那么JVM肯定会一直往上飙升。你用的时候就需要先评估一下使用场景。由于每次更新都会复制新容器,所以如果数据量较大并且更新
操作频繁则对内存消耗很高,建议在高并发读的场景下使用
⑥COW容器有两种,一种是CopyOnWriteArrayList,一种是CopyOnWriteArraySet;一个是替代ArrayList,一个是替代Set

HashMap与HashTable的区别?
(1)HashMap没有考虑同步,是线程不安全的;HashTable使用了synchronized关键字,是线程安全的
(2)HashMap允许<K/V>都为null,而HashTable不允许为<K/V>为null。
(3)Hashtable,HashMap 都使用了 Iterator。而由于历史原因,Hashtable 还使用了Enumeration 的方式
(4)HashTable中hash数组的默认大小是11,增加方式是old*2+1,HashMap中hash数组的默认大小是16,之后每次
扩容变为原来的两倍。
(5)HashTable继承自Dictionary,HashMap继承自AbstractMap

HashMap与ConcurrentHashMap的区别?
HashMap是线程不安全的,如果需要需要考虑线程安全的情况下还要考虑性能,可以使用ConcurrentHashMap。
(1)ConcurrentHashMap是JUC(java.util.concurrent)下的线程安全
(2)ConcurrentHashMap对整个桶数组进行了分割分段(Segment),然后在每一个分段上都用lock锁
进行保护,相对于HashTable的synchronized锁的粒度更精细了一些,并发性能更好,而
HashMap没有锁机制,不是线程安全的。(JDK1.8之后ConcurrentHashMap启用了一种全新的
方式实现,利用CAS算法。)
(3)HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。

三、ArrarList和LinkedList区别   

             
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
对于随机访问get和set,ArrayList效率优于LinkedList,因为LinkedList要移动指针。
对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。

四、HashMap底层是 数组+链表+红黑树,为什么要用这几类结构  


数组 Node<K,V>[] table ,哈希表,根据对象的key的hash值进行在数组里面是哪个节点
链表的作用是解决hash冲突,将hash值取模之后的对象存在一个链表放在hash值对应的槽位
红黑树 JDK8使用红黑树来替代超过8个节点的链表,主要是查询性能的提升,从原来的O(n)到O(logn),
通过hash碰撞,让HashMap不断产生碰撞,那么相同的key的位置的链表就会不断增长,当对这个Hashmap的相应位置进行查询的时候,就会循环遍历这个超级大的链表,性能就会下降,所以改用红黑树

五、HashMap和HashTable区别 

  
线程安全性不同
HashMap是线程不安全的,HashTable是线程安全的,其中的方法是Synchronized,在多线程并发的情况下,可以直接使用HashTable,但是使用HashMap时必须自己增加同步处理。

是否提供contains方法
HashMap只有containsValue和containsKey方法;HashTable有contains、containsKey和containsValue三个方法,其中contains和containsValue方法功能相同。

key和value是否允许null值
Hashtable中,key和value都不允许出现null值。HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。

数组初始化和扩容机制
HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。

Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。

六、线程的创建方式    

  1. 继承Thread类创建线程
  2. 实现Runnable接口创建线程
  3. 使用Callable和Future创建线程   有返回值
  4. 使用线程池创建线程

七、线程的状态转换有什么(生命周期)

新建状态(New) :线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。
就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
运行状态(Running):线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。
同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

八、Java中有几种类型的流

字节流:

1.输入流(inputstream):

FileInputStream:从文件系统中的某个文件中获得输入字节用于读取诸如图像数据之类的字节流。

缓冲流BufferedInputStream:是InputStream的间接子类。

2.输出流(OutputStream):

BufferedOutStream: 缓冲流,是OutputStream的间接子类。

FileOutStream:用于写入诸如图像数据之类的原始字节的

字符流:

1.Reader输入流:
InputStreamReader转换流:字符流通向字符流的桥梁
FileReader
读取字符文件的便捷类
BufferedReader缓中流特有方法:readLine()
2.Writer输出流
BufferedWriter:缓冲流,特有方法:newLine()、write(String str)
OutputStreamWriter转换流:是字符流通向字节流的桥梁
FileWriter写入字符文件的便提类ler_s0n

九、请写出你最常见的5个RuntimeException  


java.lang.NullPointerException
空指针异常;出现原因:调用了未经初始化的对象或者是不存在的对象。

java.lang.ClassNotFoundException
指定的类找不到;出现原因:类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发异常。

java.lang.NumberFormatException
字符串转换为数字异常;出现原因:字符型数据中包含非数字型字符。

java.lang.IndexOutOfBoundsException
数组角标越界异常,常见于操作数组对象时发生。

java.lang.IllegalArgumentException
方法传递参数错误。

java.lang.ClassCastException
数据类型转换异常。

十、谈谈你对反射的理解    


反射机制
所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底了解自身的情况为下一步的动作做准备。

Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method;其中class代表的时类对 象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组成部分。

Java反射的作用
在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,可以调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。

Java 反射机制提供功能
在运行时判断任意一个对象所属的类。

在运行时构造任意一个类的对象。

在运行时判断任意一个类所具有的成员变量和方法。

在运行时调用任意一个对象的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值