JVM是运行Java字节码的虚拟机。而基于不同平台,相同的Java字节码,执行之后会产生相同的结果,这也是实现跨平台的关键。
JVM 并不是特有的,只要满足JVM规范,每个公司或组织或者个人,都可以开发自己专属的JVM。
JDK是 Java Development Kit 的缩写,是功能齐全的 SDK。它包含 JRE 所拥有一切,还包括: javac、javadoc、jdb。它能够创建程序、编译程序。
JRE是Java运行时环境。用来运行已编译好的Java程序,包括Java虚拟机、Java类库、java命令和其他的一些基础构建。但是它不能用于创建新程序。如果只是要运行Java程序的话,则只需要安装JRE就可以了,如果需要支持Java编程工作的话,则需要安装JDK了。
在Java中,字节码是可以被JVM理解的代码 (即扩展名为 .class的文件)。它跟特定的设备无关,只面向于虚拟机JVM。Java语言通过字节码的方式,在一定程度上解决了那些传统语言执行效率低的问题,同时又保留了可移植的特性,为此Java程序的执行效率还算是比较高的了,并且实现一次编译跨平台执行。
Java程序从源码到运行的过程如下:
我们需要重点关注一下 .class -> 机器码 这一步。首先是 JVM 类加载器加载字节码文件 .class。然后通过解释器逐步解释执行,这种方式执行速度比较慢。为此后来引入了 JIT 编译器(运行时编译)。 当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。
这是因为 Java 语言既具有编译型语言的特征,也具有解释型语言的特征。因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(.class
文件),这种字节码必须由 Java 解释器来解释执行。
举例:
# char 是基本数据类型,一个char 只能保存一个 Unicode 字符:
char c1 = 'A';
char c2 = '中';
# Java 在内存中,总是使用 Unicode 表示字符,所以一个英文字符和一个中文字符,都只占用两个字节。如果要显示一个字符的 Unicode 编码,只需要将 char 类型直接赋值给 int 类型即可:
int n1 = 'A'; //字符 A 的Unicode编码是 65
int n2 = '中'; // 汉字 “中” 的Unicode 编码是 20013
# 还可以直接用转义字符
\u
+ Unicode 编码来表示一个字符:char c3 = ‘\u0041’; // 'A', 因为十六进制0041 = 十进制65
char c4 = '\u4e2d'; // '中', 因为十六进制4e2d = 十进制 20013
这个需要结合 JVM 的相关知识,主要原因如下:
3.1 调用方式上的区别
调用一个静态方法的可以是 类.方法名,也可以是 对象.方法名,一般我们使用 类.方法名。
调用一个非静态方法只能是 对象.方法名。
3.2 访问类成员是否存在限制?
静态方法里在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),不允许访问实例成员(即实例成员变量和实例方法),而实例方法不存在这个限制。
重载 就是名字相同但参数不同的几个方法,能够根据输入参数的不同,做出不同的处理。典型的应用场景是 构造方法的重载。
重写 就是当子类继承父类中的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法。
4.1 重载
发生在同一个类中 (或者父类和子类之间),重载的方法名必须相同,参数类型、个数、顺序不同,返回值和访问修饰符也可以不同。
综上:重载就是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。
4.2 重写
重写是发生在运行期间的,是子类对父类中允许访问的方法的实现过程 进行重新实现。
private / final / static
则子类就不能重写该方法,但是被 static
修饰的方法能够被再次声明。综上:重写就是子类对父类方法的重新改造,外部样子不能改变,内部逻辑可以改变。
byte
、short
、int
、long
float
、double
char
boolean
。这 8 种基本数据类型的默认值以及所占空间的大小如下:
这八种基本类型都有对应的包装类分别为:Byte
、Short
、Integer
、Long
、Float
、Double
、Character
、Boolean
null
,而基本类型的默认值不是 null
。static
修饰 )存放在 JVM 堆中。包装类型属于对象类型,我们知道几乎所有对象实例都存在于 JVM 堆中。注意:基本数据类型存放在栈中是一个常见的误区! 基本数据类型的成员变量如果没有被 static
修饰的话(不建议这么使用,应该要使用基本数据类型对应的包装类型),就存放在堆中。
Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。
Byte、
Short、
Integer、
Long
这 4 种包装类型默认创建了数值 [-128,127] 的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据,Boolean
直接返回 True
or False
。
8.1 什么是自动拆装箱
Integer i = 10; //装箱
int n = i; //拆箱
查看生成的字节码可知:
Integer i = 10
等价于 Integer i = Integer.valueOf(10)
int n = i
等价于 int n = i.intValue()
;