👩🏻 作者:一只IT攻城狮 ,关注我不迷路
❤️《java面试核心知识》突击系列,持续更新…
💐 面试必知必会学习路线:Java技术栈面试系列+SpringCloud项目实战学习路线
📝再小的收获*365天都会成就不一样的自己,一起学习,一起进步。
文章目录
- 一、ArrayList和linkedList的区别
- 二、HashMap和HashTable的区别
- 三、Java自动装箱与拆箱
- 四、线程和进程的区别
- 五、什么是java的局部变量、成员变量和全局变量?
- 六、Java的四种引用,强弱软虚
- 1、强引用
- 2、软引用
- 3、弱引用
- 4、虚引用
- 七、volatile关键字
- 八、final有哪些用法?
- 九、static都有哪些用法
- 十、a=a+b与a+=b有什么区别吗?
一、ArrayList和linkedList的区别
List—是一个有序的集合,可以包含重复的元素,它继承Collection。
List有两个重要的实现类:ArrayList和LinkedList
1、ArrayList 内部使用的动态数组来存储元素,LinkedList 内部使用的双向链表来存储元素,这也是 ArrayList 和 LinkedList 最本质的区别。
2、正因为底层数据结构的不同,他们适用的场景不同,ArrayList 更适合随机查找,与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低,因为要移动指针。数据量小时性能差别不是很大。
补充知识:ArrayList的toArray方法返回一个数组
ArrayList的asList方法返回一个列表
二、HashMap和HashTable的区别
1、安全性
Hashtable是线程安全,HashMap是非线程安全。HashMap的性能会高于Hashtable,我们平时使用时若无特殊需求建议使用HashMap
2、HashMap允许null作为键或值,Hashtable不允许,运行时会报NullPointerException。HashMap以null作为key时,总是存储在table数组的第一个节点上。
3、HashMap添加元素使用的是自定义hash算法,Hashtable使用的是key的hashCode
HashMap继承了AbstractMap,HashTable继承Dictionary抽象类,两者均实现Map接口
5、HashMap和HashTable的底层实现都是数组+链表结构实现
但是在jdk 1.8版本之后HashMap增加了一个新的结构叫做红黑树。
6、HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。HashMap扩容时是当前容量翻倍即:capacity 2,Hashtable扩容时是容量翻倍+1即:capacity (2+1)
7、HashMap只支持Iterator遍历,Hashtable支持Iterator和Enumeration
遍历的机制HashMap有一个叫keyset还有一个叫Entryset的两个方法,得到的结果都是Iterator(迭代器)。
而HashTable有一个叫elements的方法,他的结果是Enumeration,同时Hashtable也能得到key和Entry,所以Hashtable的遍历方式多了一个机制。
8、HashMap与HashTable的部分方法不同,比如HashTable有contains方法。
HashTable中有contains方法,HsahMap中就没有。HashMap只有containsKey和containsValue但是没有contains。
三、Java自动装箱与拆箱
装箱
:就是自动将基本数据类型转换为包装器类型(int–>Integer);调用方法:Integer的valueOf(int) 方法
拆箱
:就是自动将包装器类型转换为基本数据类型(Integer–>int)。调用方法:Integer的intValue方法
在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行: Integer i = new Integer(10);
而在从Java SE5开始就提供了自动装箱的特性,如果要生成一个数值为10的Integer对象,只需要
这样就可以了:Integer i = 10;
四、线程和进程的区别
进程
是资源分配的最小单位,线程
是CPU调度的最小单位。
一个进程可以包含多个线程。
进程要比线程消耗更多的计算机资源。
进程间不会相互影响,有独立的地址空间。
不同进程间数据很难共享,同一进程下不同线程间数据可以共享。
五、什么是java的局部变量、成员变量和全局变量?
1、局部变量:在方法内定义的变量称为“局部变量”或“临时变量”,方法结束后局部变shu量占用的内存将被释放。
2、成员变量:在类体的变量部分中定义的变量,也称为字段。
3、全局变量:全局变量,又称“外部变量”,它不是属于哪个方法,作用域从定义的地址开始到源文件结束。
4、局部变量和成员变量主要是他们作用域的区别:
成员变量个是类内部;局部变量是定义其的方法体内部(或者方法体内部的某一程序块内——大括号,主要看定义的位置)。
成员变量可以不显式初始化,它们可以由系统设定默认值;局部变量没有默认值,所以必须设定初始赋值。
在内存中的位置也不一样。成员变量在所在类被实例化后,存在堆内存中;局部变量在所在方法调用时,存在栈内存空间中。
六、Java的四种引用,强弱软虚
1、强引用
强引用是平常中使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收,使用方式:
String str = new String("str");
System.out.println(str);
2、软引用
软引用在程序内存不足时,会被回收,使用方式:
// 注意:wrf这个引用也是强引用,它是指向SoftReference这个对象的,
// 这里的软引用指的是指向new String("str")的引用,也就是SoftReference类中T
SoftReference<String> wrf = new SoftReference<String>(new String("str"));
可用场景: 创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM就会回收早先创建的对象。
3、弱引用
弱引用就是只要JVM垃圾回收器发现了它,就会将之回收,使用方式:
WeakReference<String> wrf = new WeakReference<String>(str);
可用场景: Java源码中的 java.util.WeakHashMap 中的 key 就是使用弱引用,我的理解就是, 一旦我不需要某个引用,JVM会自动帮我处理它,这样我就不需要做其它操作。
4、虚引用
虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入 ReferenceQueue 中。注意哦,其它引用是被JVM回收后才被传入 ReferenceQueue 中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。还有就是,虚引用创建的时候,必须带有 ReferenceQueue , 使用例子:
PhantomReference<String> prf = new PhantomReference<String>(new String("str"),
new ReferenceQueue<>());
可用场景:
对象销毁前的一些操作,比如说资源释放等。 Object.finalize() 虽然也可以做这
类动作,但是这个方式即不安全又低效 。
上诉所说的几类引用,都是指对象本身的引用,而不是指Reference的四个子类的引用
(SoftReference等)。
七、volatile关键字
volatile保证内存可见性
和禁止指令重排
,不能保证它具有原子性
。
volatile用于多线程环境下的单次操作(单次读或者单次写)。
也就是说volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线程是可见的。
但是这里需要注意一个问题,volatile只能让被他修饰内容具有可见性,但不能保证它具有原子性。
比如 volatile int a = 0;之后有一个操作 a++;这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就是这个操作同样存在线程安全问题。
八、final有哪些用法?
1、被final修饰的类不可以被继承;
2、被final修饰的方法不可以被重写;
3、被final修饰的变量不可以被改变;如果修饰引用,那么表示引用不可变,引用指向的内容可变;
4、被final修饰的方法,JVM会尝试将其内联,以提高运行效率
5、被final修饰的常量,在编译阶段会存入常量池中
除此之外,编译器对final域要遵守的两个重排序规则更好:
在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。
九、static都有哪些用法
所有的人都知道static关键字这两个基本的用法:静态变量
和静态方法
.也就是被static所修饰的变量/方法都属于类的静态资源,类实例所共享。
除了静态变量和静态方法之外,static也用于静态块
,多用于初始化操作:
public calss PreCache{
static{
//执行相关操作
}
}
此外static也多用于修饰内部类,此时称之为静态内部类
最后一种用法就是静态导包,即 import static .import static是在JDK 1.5之后引入的新特性,可以用
来指定导入某个类中的静态资源,并且不需要使用类名,可以直接使用资源名,比如:
import static java.lang.Math.*;
public class Test{
public static void main(String[] args){
//System.out.println(Math.sin(20));传统做法
System.out.println(sin(20));
}
}
十、a=a+b与a+=b有什么区别吗?
+= 操作符会进行隐式自动类型转换,此处a+=b隐式的将加操作的结果类型强制转换为持有结果的类型,而a=a+b则不会自动进行类型转换.如:
byte a = 127;
byte b = 127;
b = a + b; // 报编译错误:cannot convert from int to byte
b += a;
以下代码是否有错,有的话怎么改?
short s1= 1;
s1 = s1 + 1;
有错误.short类型在进行运算时会自动提升为int类型,也就是说 s1+1 的运算结果是int类型,而s1是 short类型,此时编译器会报错.
正确写法:
short s1= 1;
s1 += 1;
+=操作符会对右边的表达式结果强转匹配左边的数据类型,所以没错.