Java基础

1. JAVA中的几种基本数据类型是什么,各自占用多少字节。

Java中一共8种基本数据类型,一个字节占8位。

  • short 2个字节 16位
  • int 4个字节 32位
  • float 4个字节 32位
  • double 8个字节 64位
  • long 8个字节 64位
  • char 2个字节 16位
  • byte 1个字节 8位
  • boolean 1位

2. String类能被继承吗,为什么。

String类被final修饰,是不可变类,不能被继承。每更新一次都会产生一个新的对象,为了避免系统中产生大量的String对象,所以引入了字符串常量池。
常量池运行机制:创建一个字符串时,首先检查池中是否有值相等的字符串对象,如果有则直接返回池中对象的引用。如果没有则创建新的对象,返回对象引用,并将对象放入常量池中。

3. String,Stringbuffer,StringBuilder的区别。

  • String类是不可变的,每次改变都会产生新的对象
  • StringBuffer是为了解决由String过多的拼接导致产生太多中间对象的问题,可以通过append拼接字符内容,通过在方法上增加synchronized关键字实现线程安全
  • StringBuilder是JDK1.5新增的,跟StringBuffer的功能几乎一致,不同点是StringBuilder没有synchronized关键字,所以是线程不安全的,也是在单线程模式下用来拼接字符串的首选

4. ArrayList和LinkedList有什么区别。

  • ArrayList是基于动态数组的数据结构,默认的初始容量是10,容量不足时自动扩容(每次增加当前容量的一半,即扩容后的容量为当前容量的1.5倍),由于增加/删除数据时会移动列表中的数据,所以增加/删除速度慢,但是查找快
  • LinkedList是基于链表的数据结构,需要维护前后节点信息,因此会有额外的内存开销,但是不需要扩容。插入/删除速度快,查找慢(因为要按照链表一个个找)

5. 讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。

父类静态变量 -> 父类静态代码块 -> 子类静态变量 -> 子类静态代码块 -> 父类非静态变量 -> 父类非静态代码块 -> 父类构造方法 -> 子类非静态变量 -> 子类非静态代码块 -> 子类构造方法

6. 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。

常用的Map类有HashMap、HashTable、TreeMap,他们都是以键值对的形式进行存储。

  • HashMap:非线程安全,支持null键和值,初始容量为16(容量不够时,在现有容量的基础上翻倍扩容,扩容后要将老的数组中的元素重新放入新的数组中,这是扩容的一个主要开销来源),内部是通过数组加单向链表实现,其中链表在JDK1.8中加入了红黑树(即链表长度超过8时自动将链表转换为红黑树),解决了key hash值冲突较多的情况下查询慢的问题
  • HashTable:线程安全(在操作数据的方法上增加synchronized,会锁住所有数据,严重影响并发性能),不支持null键和值,默认初始容量为11,扩容2*原数组长度+1
  • TreeMap:基于红黑树的一种提供顺序访问的Map
  • LinkedHashMap:和HashMap类似,加入了双向链表,遍历顺序符合插入顺序
  • ConcurrentHashMap:默认初始容量为16,不支持null键和值,并发下推荐使用的Map(也可以通过使用Collections.synchronizedMap来获取一个同步包装容器,但是线程安全的实现原理类似HashTable通过synchronized锁整个对象的数据,性能较差不推荐使用)。
    ConcurrentHashMap在JDK1.7中采用分离锁进行分段加锁(对segment加上ReentrantLock可重入锁,此版本下ConcurrentHashMap进行put时,将key进行二次hashCode找到segment,获取segment的分段锁(segment的数量默认为16个,支持调整为2的幂数值),此时其他segment的内容区可正常供其它线程使用,segment内部储存着HashEntry的集合(segment的内部结构相当于HashMap的数组加链表形式结构),需要扩容时对segment进行单独扩容)。
    ConcurrentHashMap在JDK1.8中不再使用segment,整体数据结构跟HashMap类似,锁的粒度更加细化,并发控制使用synchronized和CAS来实现,在没有hash冲突的情况下直接使用CAS来操作(CAS机制:相当于乐观锁,没有锁的性能开销),当hash冲突时,则直接用链表的第一个object作为加锁对象,这里加的锁是synchronized(现代JDK中 ,synchronized已经被不断优化,可以不再过分担心相比于ReentrantLock的性能差异, 但是可以减少了内存消耗)。

你可能感兴趣的:(Java基础)