Java面试知识学习笔记01
此为本人对于Java基础知识及其相关问题的一些总结,里面的一些知识点及问题参考了几位大佬的文章。
1.java基础
1).java的特点
- 平台无关性:Java编译器将源代码编译成字节码(bytecode,即.class文件)。然后该字节码可以在安装了JVM的系统上运行。
- 面向对象
- 内存管理: java有自己的垃圾回收机制,自动管理和回收不再使用的对象。
2).java为什么是跨平台的
java源码通过编译生成.class文件(字节码文件),java虚拟机(JVM)将字节码文件翻译成特定平台下的机器码然后运行。
JVM相当于一个桥梁,是实现跨平台的关键。JVM是C/C++实现的,不同平台下的JVM的版本是不一样的。
3).为什么Java解释和编译都有?
正常流程下Java程序源代码到运行的过程如下:
%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
javaFileName(.java)
op1{javac编译}
classFileName(.class)
op2{解释器&JIT}
machineFileCode(机器可理解的代码)
javaFileName --> op1 --> classFileName -->op2
-->machineFileCode --> A[/电脑\]
JVM中有一个方法调用计数器,当累计计数大于一定值的时候,会把部分热点代码存入JIT中。通过JIT编译生成机器码。如果不是热点代码,则会通过解释器去解释生成机器码
- 编译型语言:C、C++、Go、Rust等。会通过编译器将源代码一次性翻译成可被平台执行的机器码。编译语言的执行速度快,但开发效率比较低。
- 解释型语言:Python、JavaScript等。会通过解释器一句一句将代码解释为机器码后再执行。解释型开发效率快,但执行速度比较慢。
4).JVM是什么
JVM是java虚拟机。主要是解释自己的指令集(字节码)并映射到本地的CPU指令集和OS的系统调用。
5).基本的数据类型
数据类型分为 基本类型和 引用类型
基本类型:
-
数值型
- 整数型 (byte, short, int, long)
- 浮点型 (float, double)
- 字符型 (char)
- 布尔型(boolean)
引用类型:
- 类 (class)
- 接口 (interface)
- 数组
6).数据类型转换方式有哪些?
- 自动类型转换(隐式转换): 目标类型的范围大于源类型时,Java会自动将源类型转化为目标类型。例如 将
int转化为long。 - 强制类型转换(显示转换):目标类型范围小于源类型时,需要使用强制类型转换将源类型转换为目标类型。例如
long转int。可能会导致精度丢失或移除。 - 字符串转换:例如字符串转换为整型
int。可以使用Integer.parseInt()。 - 数值之间的转换。例如整型转换为字符型,字符型转化为整型,可以通过包装类提供的转换方法。
7).基础类型和包装类型的区别?
- 用途:对象属性中很少会用到基本类型,而包装类型可用于泛型。
- 存储方式:基本数据类型的局部变量存放在Java虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被static修饰)(在class中,与实例化的对象绑定)存放在Java虚拟机的堆中。而包装类属于对象类型,所以包装类基本上存在于堆中。
- 占用空间:相比于包装类型(对象类型),基本数据类型占用的空间往往很小。
- 对于基本数据类型来说。
==比较的是值,而包装类型中==标胶的是对象的内存递增。所以整型包装类型之间值的比较,全部使用.equals()。
8).装箱和拆箱是什么?
Integer i = 10; //装箱
int n = i; // 拆箱
自动装箱的弊端:
Integer sum = 0;
for (int i = 1000; i < 5000; i ++) {
sum += i;
}
这里的sum += i可以看成sum = sum + i,但是 +这个操作不适用于Integer对象,首先sum会进行自动拆箱,然后再进行数值相加操作,最后发生自动装箱操作转换成Integer对象。
// sum += i的内部变化。
int result = sum.intValue() + i;
Integer sum = new Integer(result);
这样频繁的拆箱装箱操作会多创建4000个无用的Integer对象。会降低了程序的性能并且加重了垃圾回收的工作量。
9).Java为什么要有Integer?
Java中绝大部分方法或类都是用来处理 类 类型对象,如ArrayList集合类就只能以类作为他的存储对象,而把一个int型的数据存入list是不可能的,必须把它包装成类,也就是Integer才能被List所接受。
10).Integer相比int有什么优点?
- 基本类型和引用类型: int是基本数据类型,Integer是一种引用类型。引用类型是需要通过实例化对象来使用,而基本数据类型是预定义的,不需要实例化就可以使用。意味着当使用int来存储一个整数时,不需要任何额外的内存分配,使用Integer时,需要为对象分配内存。性能方面,基本数据类型的操作通常闭相应的引用类型快。
- 空指针异常:int变量可以赋值为0,Integer变量必须通过实例化对象来赋值。如果对一个未经初始化的Integer变量进行操作,就会出现空指针异常,因为它被赋予了null值,null值是无法自动拆箱。
11).包装类型的缓存机制?
Byte, Short, Integer, Long4中包装类型默认创建了数值 [-128,127] 相应类型的缓存数据。Character创建了数值在 [0, 127] 范围的缓存数据Boolean直接返回了TrueorFalse- 但是
Dobule, Float没有实现缓存机制。
// Integer缓存源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static {
// high value may be configured by property
int h = 127;
}
}
// Character缓存源码
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
private static class CharacterCache {
private CharacterCache(){}
static final Character cache[] = new Character[127 + 1];
static {
for (int i = 0; i < cache.length; i++)
cache[i] = new Character((char)i);
}
}
// Boolean缓存源码
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true
Float i11 = 333f;
Float i22 = 333f;
System.out.println(i11 == i22);// 输出 false
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);// 输出 false
又例如这个例子
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);
这里Integer i1 = 40这一行会发生装箱操作,即这行代码等价于
Integer i1 = Integer.valueOf(40)
即i1直接使用的是缓存中的对象,而Integer i2 = new Integer(40)则会直接创建新的对象。
所以答案是false。所有整型包装类对象之间值的比较,全部使用equals方法比较。