Java - 基本概念与常识
转载声明
# 一、 Java语言的特点
- 简单性:丢弃了C++中少用、难懂的特性,例如操作符重载、多继承、指针、内存管理等,不用手动管理对象的生命周期。
- 面向对象:封装,继承,多态
- 平台无关性:一次编译到处运行
- 解释执行:编译成字节码文件,java解释器对字节码进行解释执行
- 多线程
- 分布式(强大、易于使用的联网能力)
- 高性能(相对其他高级语言,JIT (opens new window)的发展)
- 健壮性(强类型机制、异常处理、垃圾回收机制)
- 安全性(安全机制以防止恶意代码的攻击)
# 1.1 编译与解释并存
由 Java 编写的程序需要先经过 编译 步骤,生成字节码(.class 文件),这种字节码必须由 Java 解释器来 解释执行
# 1.2 跨平台
java 代码被编译成字节码文件,字节码是平台无关的,是面向 JVM 编写的。
JVM 的接口是向下与硬件有关的,在不同平台上有不同的指令系统,才能支持字节码文件在不同的操作系统下解释执行,从而实现 Java 的跨平台性也就是可移植性
# 二、JVM & JDK & JRE
- Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。
- JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。
- JDK 是 Java Development Kit 缩写,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的一切,还有编译器(javac)和工具(如 javadoc 和 jdb)。
JDK > JRE > JVM
浅谈JDK、JRE、JVM区别与联系 (opens new window)
- JVM不能单独执行class
- JRE = JVM + lib(jvm工作需要的类库)。可以执行class
- JDK包含JRE。可以开发、编译、执行

# 2.1 Oracle JDK & OpenJDK (不懂)
Java基础常见知识&面试题总结(上) | JavaGuide (opens new window)
# 三、字节码及优点
JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。
- Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。
- 由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。

为什么
参考: 什么是字节码?采用字节码的最大好处是什么? (opens new window)
解释型语言
- 优点:程序运行时才进行翻译,容易维护 、方便快速部署、不用停机维护。
- 缺点:每次运行都要解释一遍,性能较低
编译型语言
优点:编译器会对程序代码进行优化,并且只需要进行一次编译、效率较高
缺点:修个当个功能需要重新编译整个模块,不同的运行环境需要编译不同的机器码才能执行
采用字节码:
- 先通过编译器对程序进行编译,会有一轮优化,能够一定程度上提高性能
- 字节码面向虚拟机, 可由不同平台的虚拟机直接解释执行,不需要重新编译,实现可移植的特点
# 四、Java 是值传递
# 4.1 值传递 & 引用传递
程序设计语言将实参传递给方法(或函数)的方式分为两种:
- 值传递 :方法接收的是实参值的拷贝,会创建副本。
- 引用传递 :方法接收的直接是实参所引用的对象在堆中的地址,不会创建副本,对形参的修改将影响到实参。
很多程序设计语言(比如 C++、 Pascal )提供了两种参数传递的方式,不过,在 Java 中只有值传递。
# 4.2 修改基本数据类型
class Solution {
public void swap(int a, int b) {
System.out.println("执行交换函数,将a、b的值对换");
int tmp = a;
a = b;
b = tmp;
}
public static void main(String[] args) {
int a = 1;
int b = 2;
System.out.println("执行前:a = " + a + ", b = " + b);
new Solution().swap(a, b);
System.out.println("执行后:a = " + a + ", b = " + b);
}
}
-----------------------------------------------------------------
执行前:a = 1, b = 2
执行交换函数,将a、b的值对换
执行后:a = 1, b = 2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- a和b只是从num1和num2复制得到了值,怎么操作都不会产生影响
# 4.3 修改引用类型中的值
class Solution {
public void print(int[] array) {
for (int num : array) {
System.out.print(num + " ");
}
System.out.println("");
}
public void swap(int[] array) {
System.out.println("执行交换函数,将数组首尾两数对换");
int tmp = array[0];
array[0] = array[array.length - 1];
array[array.length - 1] = tmp;
}
public void change(int[] array) {
System.out.println("创建新的数组");
array = new int[]{4, 5, 6};
}
public static void main(String[] args) {
int[] arr = new int[]{1, 2, 3};
System.out.print("原数组:");
new Solution().print(arr);
new Solution().swap(arr);
System.out.print("交换后数组:");
new Solution().print(arr);
new Solution().change(arr);
System.out.print("创建后数组:");
new Solution().print(arr);
}
}
------------------------------------------------------------------
原数组:1 2 3
执行交换函数,将数组首尾两数对换
交换后数组:3 2 1
创建新的数组
创建后数组:3 2 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
- 函数中的
int[] arr只是对数组 引用 的一个拷贝- 对这个引用指向的数组对象就行内容修改,两个引用都能查看到
- 但是对这个 新的引用 创建新的数组,也不会影响原来的 数组引用 指向的数组对象。

# 4.4 修改引用类型的对象
class Solution {
static class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
}
static void swapName(Student s1, Student s2) {
System.out.println("直接交换两人的姓名");
String name = s1.getName();
s1.setName(s2.getName());
s2.setName(name);
}
static void swapStudent(Student s1, Student s2) {
System.out.println("交换两个对象");
Student tmp = s1;
s1 = s2;
s2 = tmp;
}
public static void main(String[] args) {
Student xz = new Student("xiaoZhang");
Student xl = new Student("xiaoLi");
System.out.println("xz:" + xz.getName() + ", xl: " + xl.getName());
swapName(xz, xl);
System.out.println("xz:" + xz.getName() + ", xl: " + xl.getName());
swapStudent(xz, xl);
System.out.println("xz:" + xz.getName() + ", xl: " + xl.getName());
}
}
---------------------------------------------------------------------------------
xz:xiaoZhang, xl: xiaoLi
直接交换两人的姓名
xz:xiaoLi, xl: xiaoZhang
交换两个对象
xz:xiaoLi, xl: xiaoZhang
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

# 总结
Java 中将实参传递给方法(或函数)的方式是 值传递 :
- 如果参数是基本类型的话,很简单,传递的就是基本类型的字面量值的拷贝,会创建副本。
- 如果参数是引用类型,传递的就是实参所引用的对象在堆中地址值的拷贝,同样也会创建副本。
# 五、程序、进程和线程
简单来说, 一个进程就是一个执行中的程序 ,它在计算 机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如 CPU 时间,内存空 间,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存 中。 线程是进程划分成的更小的运行单位 。线程和进程最大的不同在于基本上各进程是独立的,而 各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系 统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同 时执行一个以上的程序段。