javaguide八股文知识补漏洞
章节(Java基础常见面试题总结(上))
基础概念与常识:
- 静态编译
静态编译是在编译时将程序的源代码和所有依赖的库文件编译成一个可执行文件。在执行程序时,操作系统加载这个可执行文件并将其放入内存中运行。由于所有的依赖都已经被编译进可执行文件中,所以在运行时不需要再去查找依赖的库文件。这样可以使得程序运行更快,但是可执行文件的大小会相对较大。
动态编译则是在程序运行时动态地加载所需要的库文件,而不是将它们静态地编译进可执行文件中。 - aot编写的不容易反编译?
运行前编译成机器码 防止源码运行过程暴露。 - LTS服务
long term service 长期服务 - BCL OTN协议
BCL协议,即Oracle Binary Code License Agreement,协议规定你可以使用JDK,但是不能进行修改。私用和商用都可以,但是JDK中的某些商业特性,是需要付费才可以使用的。OTN协议,即Oracle Technology Network License Agreement,目前新发布的JDK用的都是这个协议,可以私用,商用需要付费 - 既然 Oracle JDK 这么好,那为什么还要有 OpenJDK
开源 免费 更新频率快 - 多重继承
多重继承是编程语言中的一个概念,它允许一个类同时从多个基类中继承方法和特性。在面向对象编程中,单一继承指的是一个子类仅从其单个父类继承。虽然多重继承能够提供更多的代码复用性和灵活性,但它也可能引起一些复杂的问题,如潜在的混乱和不一致的行为。
Java 可以通过实现多个接口来实现多重继承 - 指针访问内存不安全
内存泄漏(忘记释放指针) 空指针野指针 悬垂指针 - 操作符重载
把操作符赋予新的运算过程
基本语法:
- Strictfp native volatile
Strictfp 浮点计算结果在各平台都一样的时候
Native java 调用非java 代码接口
Volatile 多线程里面的 除同步锁外的另一个同步机制 禁止指令重排 - 字面值定义
指数值 比如null true - 访问控制default 报错
就是default这个关键字不用写,写出来就报错,不写就是默认。 - 字面值
true false null - << >>指令码
运行更高效 记住>>>这是无符号右移 - double,float 在二进制中的表现比较特殊,因此不能来进行移位操作。
- 如果移位的位数超过数值所占有的位数会怎样?当 int 类型左移/右移位数大于等于 32 位操作时,会先求余(%)后再进行左移/右移操作。也就是说左移/右移 32 位相当于不进行移位操作(32%32=0),左移/右移 42 位相当于左移/右移 10 位(42%32=10)。当 long 类型进行左移/右移操作时,由于 long 对应的二进制是 64 位,因此求余操作的基数也变成了 64。
基本数据类型:
- Java使用long类型数据一定后面加上l
- char单引号 string双引号
- 包装类型可用于泛型,基本类型不可以
- 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
假定我们有这样一个需求:写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?答案是可以使用 Java 泛型。
- 为什么说是几乎所有对象实例都存在于堆中呢?
- 这是因为 HotSpot 虚拟机引入了 JIT 优化之后,会对对象进行逃逸分析,如果发现某一个对象并没有逃逸到方法外部,那么就可能通过标量替换来实现栈上分配,而避免堆上分配内存
- 基本数据类型存放在栈中是一个常见的误区!
- 基本数据类型的存储位置取决于它们的作用域和声明方式。如果它们是局部变量,那么它们会存放在栈中;如果它们是成员变量,那么它们会存放在堆中。
- 缓存池机制对包装类型很重要
- Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False。
- Float,Double没有实现缓存机制。
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2); // 输出 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 i1=Integer.valueOf(40) 。因此,i1 直接使用的是缓存中的对象。而Integer i2 = new Integer(40) 会直接创建新的对象。
- 所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
- BigDecimal 可以实现对浮点数运算,不会造成精度丢失。
- BigInteger可以表示超过long整型的数据。
- 从变量在内存中的存储方式来看,如果成员变量是使用 static 修饰的,那么这个成员变量是属于类的,如果没有使用 static 修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。
方法:
- 静态方法为什么不能调用非静态成员?
1.静态方法是属于类的,在类加载的时候就会分配内存,可以通过类名直接访问。而非静态成员属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问。
2.在类的非静态成员不存在的时候静态方法就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。
- 注意的是一般不建议使用 对象.方法名 的方式来调用静态方法。这种方式非常容易造成混淆
- 重载和重写有什么区别?
- 重载就是同样的一个方法能够根据输入数据的不同,做出不同的处理
- 重写就是当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法。
- 重写
- 构造方法无法被重写
- 方法名、参数列表必须相同,子类方法返回值类型应比父类方法返回值类型更小或相等,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类——覆盖