JAVA基础第二部分
- String类为什么是final的。
主要是为了“效率”和“安全性”的缘故。因为String使用率较高,因此final方法编译器会采取内联方式实现,JVM执行效率得到提高;String作为HashMap的key以及其他场合的时候,需要保持不可变性,否则会发生错误,因此需要声明成final的。
2、HashMap的源码,实现原理,底层结构。
3、list、set、queue、map实现类
Collection接口实现了Set、List、Queue三个接口,其中List是有序的,允许元素重复。Set是无序的,不允许重复,Queue用于模拟先进先出的队列。List和Set依然是接口,向下生成AbstractList和AbstractSet两个抽象类。
List下面有ArrayList、LinkedList和Vetor。其中,ArrayList和Vetor采用线性存储,Vector是线程安全的,ArrayList不是线程安全的;LinkedList采用链式存储,不是线程安全的。
Set下面有HashSet、EnumSet和TreeSet。HashSet底层是使用没有value的Map来实现;TreeSet使用了一个排序的平衡二叉树;EnumSet枚举类型的Set。
Queue下面有Dueue与PriorityQueue。其中,Dueue是一个双端队列,PriorityQueue是一个排序队列。
Map接口下面是AbstractMap抽象类,下面有HashMap,EnumMap,HashTable,LinkedHashMap,WeakHashMap。HashMap根据key的HashCode值存储数据。EnumMap是使用枚举类型作为key的map,HashTable是同步的Map,不允许null值。LinkedHashMap只是对HashMap做了一层简单的包装,保证放进去和拿出来的顺序是一样的。TreeMap使用树实现,支持排序等操作。WeakHashMap内部使用弱引用来管理数据,可以被垃圾回收器回收,因此是作为缓存实现的极好的方式。
4、描述一下ArrayList和LinkedList各自实现和区别
ArrayList是线性表,随机取数快,数据删除插入较慢,占用内存小
LinkedList是链表,插入删除快,查找遍历较慢占用内存稍大
5、Java中的队列都有哪些,有什么区别。
包含普通队列、阻塞队列、非阻塞队列
阻塞队列与普通队列区别在于,当阻塞队列为空时,从队列中获取元素的操作将被阻塞,或阻塞队列满时,往队列里添加元素的操作会被阻塞。
阻塞队列与非阻塞队列都是线程安全的,区别在于阻塞队列通过加锁方式实现阻塞的插入和移除方法,达到线程安全。非阻塞队列采用循环CAS实现多线程并发。
6、反射中,Class.forName和classloader的区别
Class.forName()方法底层调用Class.forName(className,true,classloader);表示在加载类的时候,执行初始化步骤;
ClassLoader.loadClass()方法底层调用ClassLoader.loadClass(className,false);表示不执行初始化步骤;
初始化步骤会初始化静态变量和静态代码块,如果此处没有初始化,那就需要在newInstance时,初始化。根据不同的需要,调用相应的方法。
可能会引申到JVM装载类的过程:编译解释java文件为二进制class,装载class(通过类的完全限定名和类加载器实例),链接(对二进制字节码校验,初始化静态变量,找到父类接口和类,确定调用的方法和类都是存在的且具备权限),初始化(静态代码块其他)。
7、Java7、Java8的新特性
Java7:try包含资源代码块,自动释放;更强的类型推测,new的时候不再需要指定类型;数字字面量下划线支持,增前阅读性;switch可以使用String;通过[],{}初始化集合。
Java8:Lambda表达式与函数接口;接口支持默认方法和静态方法;可使用类似于C++的方法引用class::method;多重注解;api可以直接连缀调用。
8、Java数组和链表两种结构的操作效率
数组:不能动态扩容,占内存小,添加删除操作稍慢,查询快。
链表:可以动态扩容,占内存大,添加删除操作快,查询慢。
9、string、stringbuilder、stringbuffer区别
String是final的字符串,不可变。StringBuffer是线程安全的可变字符串,StringBuilder是线程不安全的可变字符串,单线程情况下StringBuilder效率更高。
10、hashtable和hashmap的区别
a) HashMap继承自AbstractMap接口,HashTable继承自Dictionary类。
b) HashTable不支持用null作为key,而HashMap支持
c) HashTable是线程安全的map集合,HashMap不是线程安全的。
d) HashTable因为支持线程安全,所以没有HashMap的快速失败机制,但是HashTable不能保证多个api复合调用时保证安全。
e) HashTable使用Enumeration进行遍历,HashMap使用Iterator进行遍历。
11、Hash冲突怎么办?哪些解决散列冲突的方法?
Hash冲突指多个不同值的哈希值相同,造成冲突,应该改进Hash算法。一般解决散列冲突的方法有:开放地址法、再哈希法、链地址法。
12、异常的结构,运行时异常和非运行时异常,各举个例子
Java把异常当做对象来处理,并定义一个基类Throwable作为所有异常的超类。然后实现了两种错误的处理类:Error(错误)和Exception(异常)。
Error表示程序运行期间出现了非常严重的错误,并且该错误不可恢复,会导致程序终止执行。
Exception表示可恢复异常,可以被编译器捕捉。包含:运行时异常(Runtime Exception)和检查异常(Checked Exception)。
检查异常发生在编译阶段,Java编译器强制程序去捕获此类型异常,把可能出现异常的代码放到try块中,异常处理代码放到catch块中。例如:数据库连接失败、IO读写等。
运行时异常编译器不会强制捕获和处理,出现异常后,系统会将异常一直往上层抛出,直到处理代码为止。如果没有处理块,则抛到最上层,如果是多线程就由Thread.run()方法抛出并该线程结束,如果是单线程就由main()方法抛出,整个程序结束。常见有:NullPointerException(空指针异常)、ArrayStoreException(数据存储异常)、ClassCastException(数据转换异常)、IndexOutOfBoundException(数组越界异常)、BufferOverflowException(缓存区溢出异常)以及ArithmeticException(算术异常)等。
13、String a= “abc” String b = “abc”
String c = new String(“abc”)
String d = “ab” + “c” .他们之间用==比较的结果
a,b,d指向内存同一区域,结果为true,c为不同区域,为false
14、String类的常用方法
length,subString,indexOf,lastIndexOf,charAt,equals,toUpperCase,equalsIgnoreCase,trim,toString,toLowerCase,replace,match(用于正则) , startsWith,compareTo,format,split等
15、Java的引用类型有哪几种
强引用:new创建的对象就是强引用,如果一个对象具有强引用,JVM就不会去GC,宁可OOM来终止程序。
软引用:如果一个对象只具备软引用,如果内存空间足够,那么JVM就不会GC,不足才会GC
弱引用:如果一个对象只具备弱引用,只要JVM的GC线程检测到了,就会立即回收
虚引用:如果一个对象只具备虚引用,即没有任何引用,随时会被JVM当做垃圾被GC
16、抽象类和接口的区别
- 接口只有定义,没有方法实现,抽象类可以有定义与实现。
- 实现接口关键词为implements,继承抽象类关键词为extends,一个类可以实现多个接口,只能继承一个抽象类。
- 接口强调特定功能实现,抽象类强调所属关系
- 接口中定义成员默认为public static final,成员方法为public abstract;抽象类成员没有限制,抽象方法只能有abstract修饰
- 接口被运用于实现比较常用的功能,便于日后维护或添加删除,抽象类更倾向于充当公共类角色。
17、java的基础类型和字节大小。
byte | Byte | 1 |
char | Character | 2 |
short | Short | 2 |
int | Integer | 4 |
float | Float | 4 |
double | Double | 8 |
long | Long | 8 |
boolean | Boolean | 1 |
18、Hashtable,HashMap,ConcurrentHashMap 底层实现原理与线程安全问题
HashTable:底层数组+链表实现,key/value均不能为null,线程安全,实现方式是对整个HashTable加锁,效率低。
HashMap:底层数组+链表实现,key(一个)/value(多个)可以为null,线程不安全。
ConcurrentHashMap:JDK1.7中底层采用分段的数组+链表实现,内部使用volatile关键字,使得共享变量在多线程之间可见和同步,采用分段锁方式实现线程安全;JDK1.8中底层采用Node数组+链表+红黑树实现,并发控制使用Synchronized和CAS来操作。
19、如果不让你用Java Jdk提供的工具,你自己实现一个Map,你怎么做。
结合HashMap说明自己实现Map的思想,数组特点:寻址容易,插入和删除困难;链表特点:寻址困难,插入和删除容易。综合两者特性,实现链表数组HashMap,而HashMap本身是一个线性的数组,内部实现一个静态的内部类Entry,包含key、value、next属性,即键值对链表。