目录
6、String、StringBuffffer 和 StringBuilder 的区别是什么?
12、HashMap 与 ConcurrentHashMap 的异同
Java(基础篇)
1、JDK和JRE有什么区别?
JDK:Java开发工具包,提供了Java的开发环境和运行环境。
JRE:Java运行环境,为Java的运行环境提供所需要的环境。
2、面向对象和面向过程的区别?
面向过程:是分析解决问题的步骤,然后用函数把这些步骤一步一步地实现,然后在使用的时候一一调用则可。性能较高,所
以单片机、嵌入式开发等一般采用面向过程开发。
3、equals与==的区别?
equals用来比较俩个对象的内容是否相同,由于所有的类都是继承java.lang.Object类的,所以适用于所有对象,如果没有对该
方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。
4、Hashcode的作用?
否已经存在该元素呢,可以通过equals方法。但是如果元素太多,用这样的方法就会比较慢。于是有人发明了哈希算法来提高
集合中查找元素的效率。 这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组
分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储的那个区域。
hashCode我是这样理解的:他返回的是根据对象的内存算出来的一个值。这样一来当我们需要添加元素的时候,先调用这个
元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位
置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存
了,不相同的化,这就是我们平时说的产生哈希冲突了。解决哈希冲突的方法有三种,分别是拉链法、开放定址法、再哈希。
用来解决哈希冲突。
5、final有哪些用法?
(1)、被final修饰的类不可以继承和重写。
(2)、被final修饰的方法,JVM会尝试将其内联,可以提高运行效率。
(3)、被final修饰的变量不可以改变。如果修饰引用,那么表示引用不可变,引用指向的内容可变。
(4)、被final修饰的常量,在编译时会存入常量池中。
6、String、StringBuffffer 和 StringBuilder 的区别是什么?
String:String是只读字符串,它并不是基本数据类型,而是一个对象。从底层源码来看是一个final类型的字符数组,所引用
的字符串不能被改变,一经定义,无法再增删改。每次对String的操作都会生成新的String对象。
StringBuffffer和StringBuilder:StringBuffffer和StringBuilder他们两都继承了AbstractStringBuilder抽象类,从
AbstractStringBuilder抽象类中我们可以看到他们的底层都是可变的字符数组,所以在进行频繁的字符串操作时,建议使用
StringBuffffer和StringBuilder来进行操作。 另外StringBuffffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安
全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。但是没加锁意味着它的执行效率更高。
7、重载和重写的区别?
重写:
重载:
8、接口与抽象类的区别?
(1)、抽象类可以存在普通成员方法,而接口只能存在抽象方法。
(2)、抽象类只能继承一个,而接口可以多实现。
(3)、成员变量在抽象类中是各个类型的,在接口中只能是常量类型。
9、说说List,Set,Map三者的区别?
10、ArrayList和linkedList的区别
ArrayList:ArrayList底层是基于动态数组存放数据的,一旦数据存储好了,查询的效率就会变高。
LinkedList:LinkedList底层是基于链表实现的,对于新增删除元素的操作,LinkedList比较占优势。
但是我在开发中,大部分还是使用的ArrayList。因为我觉得ArrayList在处理好的情况下,性能不比LinkedList差。在我们一开始建立集合时,如果确定其容量然后再使用尾插法进行添加元素。就可以大大提高其的性能。而且LinkedList下创建对象时,会大量创建node对象,这样会使其性能变差。而且如果我们在遍历元素的时候只能使用迭代器来遍历元素,想要使用for来遍历元素并且用get(i)取元素的时候。每次get的时候都需要遍历元素。这样也会对其的性能消耗变差。
11、HashMap和HashTable的区别?
(1)、HashMap方法没有synchronize修饰,线程不安全。HashTable线程为安全。
(2)、HashMap允许key和value为null。key只能有一个空值,而value可以为多个空值。而HashTable不允许为空值。
(3)、但是HashMap的效率要远高于HashTable。如果想要使用多线程并保证线程安全,我们可以使用ConcurrentHashMap
12、HashMap 与 ConcurrentHashMap 的异同
(1)、都是 key-value 形式的存储数据。
(2)、HashMap 是线程不安全的,ConcurrentHashMap 是JUC下的线程安全的。
(3)、HashMap 底层数据结构是数组 + 链表(JDK 1.8 之前)。JDK 1.8 之后是数组 + 链表 + 红黑树。当链表中元素个数
达到 8 的时候,链表的查询速度不如红黑树快,链表会转为红黑树,红黑树查询速度快。
(4)、HashMap 初始数组大小为 16(默认),当出现扩容的时候,以 0.75 * 数组大小的方式进行扩容;
(5)、ConcurrentHashMap 在 JDK 1.8 之前是采用分段锁来现实的 Segment + HashEntry,Segment 数组大小默认是 16,
2 的 n 次方;JDK 1.8 之后,采用 Node + CAS + Synchronized来保证并发安全进行实现。
13、JDK1.7和JDK1.8发生了什么变化?
(1)、JDK1.7底层为数组+链表。JDK1.8底层为数组+链表+红黑树。红黑树用来提高其插入和查询的效率。
(2)、JDK1.7使用的插入方法是头插法。JDK1.8使用的插入方法是尾插法。
(3)、JDK1.7中的算法比较复杂,JDK1.8增加了红黑树节省了CPU的资源。
14、浅拷贝和深拷贝?
(1)、浅拷贝:如果我们要拷贝基本数据类型直接拷贝,如果我们要拷贝引用数据类型时,只能拷贝它的引用地址。它们还
同时指向一个对象。
(2)、深拷贝:如果我们要拷贝基本数据类型直接拷贝,如果我们要拷贝引用数据类型时,拷贝之后,他们会指向不同的对
象,相当于重新建立一个对象。
15、hashMap的扩容机制?
JDK1.7(数组+链表):
(1)、生成一个新数组。
(2)、遍历老数组每个位置上的链表元素。
(3)、取出key,并基于新数组的长度,计算出新数组的下标。
(4)、将数组复制到新数组中去。
(5)、所有元素转移完后,将新数组将新数组赋值给HashMap的table属性。
JDK1.8(数组+链表+红黑树):
(1)、生成一个新数组。
(2)、遍历数组中的链表和红黑树。
(3)、如果是链表,则计算出列表的下标,并添加到新数组中去。
(4)、如果为红黑树,计算出红黑树每个元素对象的数组下标位置。
(4.1)、统计红黑树的下标个数。
(4.2)、如果超过了8个,则会产生新的红黑树,并将根点添加。
(4.3)、如果没有超过8个,则生成一个链表,并将链表插入新数组中去。
(5)、将新数组添加到HashMap对象的table属性中。
16、什么是字节码?使用字节码的好处?
编译器(javac)将java源文件(*.java)编译成为字节码文件(*.class)。
采用字节码的好处就是,一方面可以跨平台使用。另一方面编译器在编译源代码可以做一些编译器的优化,比如锁消除、标准替换、方法内联等。
17、Java中的异常分类?
(1)、Java中异常都来自于Throwable
(2)、Throwable下有俩个子类分别为Exception和Error。
(3)、Exception又分为RuntimeException(编译以后报错),和非RuntimeException(直接不能进行编译)。
18、Java中的类加载器?
JDK自带的有三个:bootstrap Classloader 、ExtClassLoader 、AppClassloader。
bootstrap Classloader 是 ExtClassLoader 的父类。加载lib下的jar包和class文件。
ExtClassLoader 是 AppClassloader的父类。加载lib/ext下的jar包class文件。
AppClassloader是 自定义类加载器的父类。负责加载classpath下的类文件。