前言
主要用于记录准备面试阶段遇到的Java基础面试题
正文
1、自动装箱
判断程序输出结果
public static void main(String[] args) {
Integer a = 128, b = 128, c = 127, d = 127;
System.out.println(a == b);
System.out.println(c == d);
}
答案: false, true 解释: 执行Integer a = 128, 相当于执行Integer a = Integer.valueOf(128),基本类型自动转换为包装类的过程称为自动装箱(autoboxing) 查看Integer.valueOf源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
在Integer中引入了IntegerCache来缓存值,默认的范围为:-128 ~ 127 修改默认缓存范围: JVM启动参数:-XX:AutoBoxCacheMax=
2、&和&&的区别
&&: 逻辑与运算符。当运算符左右两边的表达式都为 true,才返回 true。同时具有短路性,如果第一个表达式为 false,则直接返回 false &: 逻辑与运算符、按位与运算符
按位与运算符: 用于二进制的计算,只有对应的两个二进位均为1时,结果位才为1 ,否则为0 &在用于逻辑与时,和&&的区别是不具有短路性。所在通常使用逻辑与运算符都会使用 &&,而 & 更多的适用于位运算。
3、数据类型
基本数据类型: byte、short、int、long、float、double、char、boolean
| 类型 | 概述 | 范围 | 默认值 | 作用 | 例子 |
|---|---|---|---|---|---|
| byte | 8位、有符号,以二进制补码表示的整数 | -2^7 ~ (2^7-1),即 -128 ~ 127 | 0 | byte类型用在大型数组中节约空间,主要代替整数,因为byte变量占用的空间只有int的四分之一; | 例子:byte a=-2 |
| short | 16位,有符号,以二进制补码表示的整数 | -2^15 ~ 2^15-1, 即 -32768 ~ 32767 | 0 | short占用空间是int的二分之一 | 例子:short s=-20000 |
| int | 32位、有符号,以二进制补码表示的整数 | -2^31 ~ 2^31-1 | 0 | 一般整数型默认为int类型; | 例子:int=-200000 |
| long | 64位、有符号,以二进制补码表示的整数 | -2^63 ~ 2^63-1 | 0L | 主要使用在需要比较大整数的系统上 | 例子:long a=10000L |
| float | 32位、单精度,浮点数 | 浮点数不能用于表示精确的值 | 0.0f | 在存储大型浮点数组的时候可以节省内存空间 | 例子:float f1=0.3f |
| double | 64位、双精度,浮点数 | double也不能表示精确的值 | 0.0d | 浮点数的默认类型为double类型 | 例子:double d1=12.3 |
| boolean | 表示一位的信息 | 取值:true/false | false | 只作为一种标志类记录 true/false 情况 | 例子:boolean one=true |
| char | 是一个单一的16位Unicode字符 | \u0000(即0)~\uffff(65,535) | '\u0000' | char可以存储任何字符 | 例子:char letter='A' |
引用数据类型:
- 引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时候被指定为一个特定的类型,声明之后不能改变。
- 引用数据类型包括:类(对象)、接口、数组。
- 所有引用类型默认值都是null.
- 一个引用变量可以用于引用任何与之兼容的类型。
基本数据类型:数据存储在栈上 引用数据类型:数据存储在堆上,栈上只存储引用地址
4、String和StringBuilder、StringBuffer
String: String的值被创建后不能修改,任何对String的修改都会引起新的String对象的生成 StringBuilder: 值可以改变,线程安全(synchronized) StringBuffer: 值可以改变,线程不安全,性能更高
5、==和equals
==: 运算符,用于比较基础类型变量和引用类型变量 对于基础类型变量,比较的变量保存的值是否相同,类型不一定要相同。
short s1 = 1; long l1 = 1;
System.out.println(s1 == l1);
// true,类型不同,但是值相同
对于引用类型变量,比较的是两个变量的地址是否相同。
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println(i1 == i2);
// false,通过new创建,在内存中指向两个不同的对象
equals: Object 类中定义的方法,通常用于比较两个对象的值是否相等。 equals 在 Object 方法中其实等同于 ==,但是在实际的使用中,equals 通常被重写用于比较两个对象的值是否相同。
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println(i1.equals(i2));
// true,两个不同的对象,但是具有相同的值
// Integer的equals重写方法
public boolean equals(Object obj) {
if (obj instanceof Integer) {
// 比较对象中保存的值是否相同
return value == ((Integer)obj).intValue();
}
return false;
}
6、equals()和hashCode()
-
若重写了equals(Object obj)方法,则有必要重写hashCode()方法。
-
若两个对象equals(Object obj)返回true,则hashCode()有必要也返回相同的int数。
-
若两个对象equals(Object obj)返回false,则hashCode()不一定返回不同的int数。
-
若两个对象hashCode()返回相同int数,则equals(Object obj)不一定返回true。
-
若两个对象hashCode()返回不同int数,则equals(Object obj)一定返回false。
-
同一对象在执行期间若已经存储在集合中,则不能修改影响hashCode值的相关信息,否则会导致内存泄露问题。
7、JDK和JRE和JVM
- JDK: Java Development Kit(Java开发工具包)
- JRE: Java Runtime Environment(Java运行环境)
- JVM: Java Virtual Machine(Java虚拟机)
JDK = JRE + Java开发工具(javac.exe,java.exe,javadoc.exe)
JRE = JVM + Java核心类库
8、初始化顺序
public class InitialTest {
public static void main(String[] args) {
A ab = new B();
ab = new B();
}
}
class A {
static { // 父类静态代码块
System.out.print("A");
}
public A() { // 父类构造器
System.out.print("a");
}
}
class B extends A {
static { // 子类静态代码块
System.out.print("B");
}
public B() { // 子类构造器
System.out.print("b");
}
}
执行结果:ABabab
- 静态变量/静态代码块只会初始化(执行)一次
- 当有父类时,完整的初始化顺序为:父类静态变量(静态代码块)->子类静态变量(静态代码块)->父类非静态变量(非静态代码块)->父类构造器 ->子类非静态变量(非静态代码块)->子类构造器
9、try、catch、finally
- 运行顺序
public class TryDemo {
public static void main(String[] args) {
System.out.println(test1());
}
public static int test1() {
int i = 0;
try {
i = 2;
return i;
} finally {
i = 3;
}
}
}
执行结果:2 在进入finally之前,jvm会将i的值暂存
10、多线程实现方式
-
继承Thread类
-
实现Runnable接口
-
实现Callable接口