包含关系
JIT
我们需要格外注意的是 .class->机器码 这一步。在这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT(Just in Time Compilation) 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言 。
编译vs解释
编译:一次性将源码转换字节码,执行速度快,开发效率低。C、C++、GO、RUST
解释:解释器一句一句解释执行,执行慢,开发效率高,python,JavaScript、PHP
Java:先编译后解释。
先编译成字节码,后使用解释器来解释执行。
AOT
AOT==静态编译,程序被执行前就将其编译成机器码。
减少JIT预热的花销,减少内存占用,编译提升安全性,不容易被修改反编译。
为什么不全使用AOT
AOT 编译无法支持 Java 的一些动态特性,如反射、动态代理。
很多框架和库(如 Spring、CGLIB)都用到了这些特性。如果只使用 AOT 编译,那就没办法使用这些框架和库了。
包装类型的缓存机制
Float,Double 并没有实现缓存机制。
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
静态方法为什么不能调用非静态成员?
这个需要结合 JVM 的相关知识,主要原因如下:
静态方法是属于类的,在类加载的时候就会分配内存,可以通过类名直接访问。而非静态成员属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问。
在类的非静态成员不存在的时候静态方法就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。
静态方法vs实例方法区别
类名.方法名vs对象.方法名
静态方法在访问本类的成员时,只允许访问静态成员
String、StringBuffer、StringBuilder区别
String为什么不可变
保存字符串的数组被 final 修饰且为私有的,并且String 类没有提供/暴露修改这个字符串的方法。
字符串+的实现
字符串对象通过“+”的字符串拼接方式,实际上是通过 StringBuilder 调用 append() 方法实现的,拼接完成之后调用 toString() 得到一个 String 对象 。
String#equals() 和 Object#equals() 有何区别?
String 中的 equals 方法是被重写过的,比较的是 String 字符串的值是否相等。 Object 的 equals 方法是比较的对象的内存地址。
值传递
Java中只有值传递!没有引用传递!!!
即使传递的是引用类型,也是传递地址的副本,对副本进行操作,本身没有变!!!
Java 中将实参传递给方法(或函数)的方式是值传递:
如果参数是基本类型的话,很简单,传递的就是基本类型的字面量值的拷贝,会创建副本。
如果参数是引用类型,传递的就是实参所引用的对象在堆中地址值的拷贝,同样也会创建副本。
获取 Class 对象的四种方式
- 知道具体类的情况下可以使用:Class alunbarClass = TargetObject.class;
但是我们一般是不知道具体类的,基本都是通过遍历包下面的类来获取 Class 对象,通过此方式获取 Class 对象不会进行初始化 - 通过 Class.forName()传入类的全路径获取:Class alunbarClass1 = Class.forName(“cn.javaguide.TargetObject”);
- 通过对象实例instance.getClass()获取:TargetObject o = new TargetObject();
Class alunbarClass2 = o.getClass(); - 通过类加载器xxxClassLoader.loadClass()传入类路径获取:ClassLoader.getSystemClassLoader().loadClass(“cn.javaguide.TargetObject”);
通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行
Java反射机制主要由以下几个类实现:
Class:Class类的实例表示正在运行的Java应用程序中的类和接口。
Field:Field对象表示类的成员变量,可以用来获取和设置类及其实例的字段值。
Method:Method对象表示类的方法,可以用来调用对象的方法。
Constructor:Constructor对象表示类的构造器,可以用来创建类的新实例。
拆箱封箱
Integer i = 10 等价于 Integer i = Integer.valueOf(10)
int n = i 等价于 int n = i.intValue();