Java基本类型(8种)
byte (8位)
short (16位)
int (32位)
long (64位)
float (32位)
double (64位)
char (16位)
boolean (8位)
final关键字的几种用法
- 修饰类
修饰的类不能被继承
final类中的成员变量可以根据需要设为final
final类中的所有成员方法都会被隐式地指定为final方法
- 修饰方法
禁止该方法在子类中被覆盖
注:类的private方法会被隐式地指定为final方法
- 修饰变量(成员变量和局部变量)
如果是基础类型的变量,一旦初始化后其值便不能更改
如果是引用类型的变量,对其初始化后并不能再让其指向另一个对象
注:当用final修饰类的成员变量时,必须在定义时或者构造器中进行初始化赋值;当用final修饰局部变量时,只需要保证在使用之前被初始化赋值即可。
为什么Java内部类要设计成静态和非静态两种?
java 内部类和静态内部类的区别
String为什么要设计成final
-
安全:
String经常被用于HashMap或HashSet的键值,如果String可变,可能破坏HashSet键值的唯一性,所以千万不要用可变类型做HashMap和HashSet键值。
在并发场景下,多个线程同时读一个资源,不可变对象不能被写,所以是线程安全的。
-
性能:支持字符串常量池数据共享,节省资源,提高效率(因为如果已经存在这个常量便不会再创建,直接拿来用)
注:类似的,Long, Double, Integer之类的全都是final的。
HashMap原理?为什么每次扩容都是扩大一倍为什么不是三倍四倍?
HashMap原理,注意不是取模运算,而是与运算(效率高),这也是扩容2倍的原因!
/**
* 返回数组下标
*/
static int indexFor(int h, int length) {
return h & (length-1);
}
什么时候扩容: 当向容器添加元素的时候,会判断当前容器的元素个数,如果大于等于阈值—即当前数组的长度乘以加载因子的值的时候,就要自动扩容啦。
加载因子的参数,如果加载因子为0.75 ,如果你hashmap的 空间有 100 那么 当你插入了75个元素的时候 hashmap就需要扩容了,不然的话 会形成很长散列桶 , 对于查询和插入都会增加时间,因为 他要一个一个的equals。
但是你又不能让加载因子很小,0.01 这样是不合适的,因为 他会大大消耗你的 内存, 你一加入一个对象hashmap就扩容。
这时就存在着一个平衡,,jdk中默认是0.75 可以根据自己的实际情况进行调整
扩容(resize) 就是重新计算容量,向HashMap对象里不停的添加元素,而HashMap对象内部的数组无法装载更多的元素时,对象就需要扩大数组的长度,以便能装入更多的元素。当然Java里的数组是无法自动扩容的,方法是使用一个新的数组代替已有的容量小的数组,就像我们用一个小桶装水,如果想装更多的水,就得换大水桶。
反射中Class.forName()和ClassLoader.loadClass()的区别
Java中Class.forName和classloader都可以用来对类进行加载。Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。而classloader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。Class.forName(name,initialize,loader)带参数也可控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数,创建类的对象。
java中的静态变量、静态方法与静态代码块详解与初始化顺序
静态变量 先于 静态代码块 初始化
Java 反射 使用总结
Java集合体系总结—Map、Set、List、Queue
描述一下ArrayList和LinkedList各自实现和区别
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
Java中的队列都有哪些,有什么区别
阻塞队列与普通队列。区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列.
普通队列(非阻塞队列):LinkedList、PriorityQueue 和 ConcurrentLinkedQueue
阻塞队列:java.util.concurrent 中加入了 BlockingQueue 接口和五个阻塞队列类。它实质上就是一种带有一点扭曲的 FIFO 数据结构。不是立即从队列中添加或者删除元素,线程执行操作阻塞,直到有空间或者元素可用。
- ArrayBlockingQueue :一个由数组支持的有界队列。
- LinkedBlockingQueue :一个由链接节点支持的可选有界队列。
- PriorityBlockingQueue :一个由优先级堆支持的无界优先级队列。
- DelayQueue :一个由优先级堆支持的、基于时间的调度队列。
- SynchronousQueue :一个利用 BlockingQueue 接口的简单聚集(rendezvous)机制。
java5、java6、java7、java8的新特性
Java7语法新特性
JAVA8 十大新特性详解
Java 8 新特性
数组与链表
Java内存泄露的问题调查定位:jmap,jstack的使用等等
jmap (linux下特有,也是很常用的一个命令)
观察运行中的jvm物理内存的占用情况。
参数如下: -heap :打印jvm heap的情况
-histo: 打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live : 同上,但是只答应存活对象的情况
-permstat: 打印permanent generation heap情况
jmap -heap 2083
可以观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况
输出内容:
jmap -histo 2083 | jmap -histo:live 2083
可以观察heap中所有对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。
写个脚本,可以很快把占用heap最大的对象找出来,对付内存泄漏特别有效。
jstack用法
Java中的String,StringBuilder,StringBuffer三者的区别
注:String是线程安全的,图中错误。
HashTable和HashMap的区别详解
Java 异常机制,异常的结构,运行时异常和非运行时异常
RunntimeException的子类:
- ClassCastException
多态中,可以使用Instanceof 判断,进行规避
- ArithmeticException
进行if判断,如果除数为0,进行return
- NullPointerException
进行if判断,是否为null
- ArrayIndexOutOfBoundsException
使用数组length属性,避免越界
非运行时异常:
非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。如IOException、SQLException等以及用户自定义的Exception异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。
String a= “abc” String b = “abc” String c = new String(“abc”) String d = “ab” + “c” .他们之间用 == 比较的结果
public class TestString {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
String c = new String("abc");
String d = "ab" + "c";
System.out.println(a == b); // true
System.out.println(a == c); // false
System.out.println(a == d); // true
System.out.println(c == d); // false
}
}
String 类的常用方法
Java 的引用类型有哪几种
Java中的四种引用类型 Strong, Soft, Weak And Phantom
JAVA的四种引用类型
Java中四种引用类型详细介绍
接口和抽象类有什么区别
Hashtable,HashMap,ConcurrentHashMap 底层实现原理与线程安全问题(建议熟悉 jdk 源码,才能从容应答)
Hashtable,HashMap,ConcurrentHashMap 底层实现原理与线程安全问题
如果不让你用Java Jdk提供的工具,你自己实现一个Map,你怎么做。说了好久,说了HashMap源代码,如果我做,就会借鉴HashMap的原理,说了一通HashMap实现
Hash冲突怎么办?哪些解决散列冲突的方法?
java 解决Hash(散列)冲突的四种方法–开放定址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区
- 开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
- 再哈希法(当发生冲突时,使用第二个、第三个、哈希函数计算地址,直到无冲突时。缺点:计算时间增加。)
- 链地址法(Java hashmap就是这么做的)
- 建立一个公共溢出区(假设哈希函数的值域为[0,m-1],则设向量HashTable[0..m-1]为基本表,另外设立存储空间向量OverTable[0..v]用以存储发生冲突的记录。)
HashMap冲突很厉害,最差性能,你会怎么解决? 从O(n)提升到log(n)咯,用二叉排序树的思路说了一通???
- 修改hashCode计算方式
- 链表排序(初始化使用快排),新加节点使用插入排序,在查找插入删除过程中,可以使用二分查找
- 链表改为红黑树结构(自平衡二叉查找树)
HashMap rehash
当hash表中的负载因子达到负载极限的时候,hash表会自动成倍的增加容量(桶的数量),并将原有的对象重新的分配并加入新的桶内,这称为rehash,这个过程是十分好性能的。
扩容2倍,只需要比较扩容对应的最高位,最高位为0,保持不变,最高位为1,分配到对应的新的位置。
/**
* 返回数组下标
*/
static int indexFor(int h, int length) {
return h & (length-1);
}