Java 编程基础

Java 基础

快速入门

环境组成

以下表示 JDKJREJVM 包含关系:

text 复制代码
+----------------------------------------------+
|        JDK                                   |
| +-----------------------+ +----------------+ |
| |      JRE              | |  Other Tools   | |
| | +-----------+         | |                | |
| | |    JVM    |         | |  javac,        | |
| | +-----------+         | |  java,         | |
| |                       | |  javadoc,      | |
| |  lib (rt.jar, etc.)   | |  jdb           | |
| +-----------------------+ +----------------+ |
+----------------------------------------------+
  • JDK(Java Development Kit):是 Java 开发者工具包,它包含了 JREJava 运行环境)和其他开发工具(如 javac 编译器,javadocjdb 调试器等)。
  • JRE(Java Runtime Environment):是 Java 运行环境,它是 JDK 的一部分,负责提供 Java 程序运行所需的环境。它包含了JVMJava 虚拟机)和核心类库。Java 类库提供了大量预编译的类,包括基础的数据结构和算法,网络编程,文件操作,图形用户界面等,以方便开发者使用。
  • JVM(Java Virtual Machine):是 Java 虚拟机,它负责字节码的执行。JVM 是平台相关的,能让相同的 Java 字节码在不同的操作系统和硬件平台上运行。

重要特征

  • Java 作为面向对象编程(OOP) 模型的佼佼者,深受全球开发者的青睐。
  • Java 凭借其强类型特性和自带的垃圾回收(GC) 机制,保证了代码的安全性和健壮性。
  • Java 融合了编译性和解释性的优点,提供了灵活且高效的代码执行方式。
  • Java 具有跨平台性,体现了 "Write Once, Run Anywhere" 的理念。

运行机制

Java 编译执行命令:

bash 复制代码
# 将Java源代码进行编译
➜ javac Hello.java

# 查看生成的字节码文件
➜ ll Hello.class
-rw-r--r--@ 1 mystic  staff  1117  1  6 16:13 Hello.class

# 启动Java应用程序
➜ java Hello
Hello World

Java 基本执行流程:

text 复制代码
+----------------------------+
|         Source Code        | --- MyClass.java 源代码文件
+----------------------------+
              |
              ▼
+----------------------------+
|        Java Compiler       | --- 命令:javac(由源代码编译至字节码的过程,被称为 "编译阶段")
+----------------------------+
              |
              ▼
+----------------------------+
|   Byte Code (.class file)  | --- MyClass.class 字节码二进制文件
+----------------------------+
              |
              ▼
+----------------------------+
| JVM (Java Virtual Machine) | --- 命令:java(不同平台的 JVM 会把字节码转换成能在相应平台运行的机器码,被称为 "解释阶段")
+----------------------------+
              |
              ▼
+----------------------------+
|     Running Application    | --- MyClass 应用程序
+----------------------------+

Java 同时具有编译性和解释性,这使其既能享受到编译型语言的运行效率,又能享受到解释型语言的跨平台特性。

阶段 过程 语言特性 软件/命令 输入 输出 输出类型
开发阶段 编译 编译性 javac 编译器 Java源代码 (*.java 文件) 字节码 (*.class 文件) 二进制字节码
运行阶段 解释执行 解释性 Java虚拟机 (JVM) 字节码 (*.class 文件) 直接执行 无(在 JVM 中执行)
运行阶段 即时编译 (JIT) 编译性 Java虚拟机 (JVM) 字节码 (*.class 文件,特别是热点代码) 机器码 以机器码方式直接执行在 JVM

开发细节

  • Java 源文件以 ".java" 作为其扩展名,这些文件的主要构成部分是类 (class) 定义。

  • Java 应用程序的执行入口为 main() 方法。它的标准编写形式如下:public static void main(String[] args) {...}

  • 需注意,Java 语言对于大小写字母是严格区分的。

  • Java 方法是由一系列语句组成的,每一个语句都应以分号 ";" 结束。

  • 在一个 Java 源文件中,最多只能有一个 public(公共)类,但是其他类型的类(如私有类等)不受数量限制。

  • 如果一个源文件中包含了一个 public 类,那么该源文件必须以该公共类的名字命名。

安装 OpenJDK

下面为大家提供一种免费预编译的 OpenJDK 部署方式

JDK 说明

2019 年开始,Oracle JDK(Java Development Kit) 的商业用途需要付费。也就是说,如果你想要在生产环境中使用最新的 Oracle JDK,并想要获得官方提供的长期支持 (LTS,Long Term Support) 以及更新和补丁,你需要购买 Oracle 的订阅。

然而,Oracle 也提供了免费的 JDK 版本,即 Oracle OpenJDK。这个 JDK 的版本每三个月更新一次,但它不提供长期支持。此外,OracleJava SE 8 仍然在商业用途下免费,但这只适用于 20194 月或以前的版本。

对于个人,学术或研究用途,Oracle JDK 仍然是免费的。

请注意,若希望使用免费的 OpenJDK,并且需要长期的支持,也可以选择其他提供商的 JDK,例如:AdoptOpenJDK(更名为 Eclipse Adoptium),Amazon CorrettoAzul Zulu,或者 Red HatOpenJDK 等。这些版本一般也提供长期的支持,并且完全免费。

Adoptium OpenJDK

下面我们选择使用 Eclipse Adoptium 的产品来下载 OpenJDK

版本 截图
最新 LTS
自选平台或版本

如何查看真实的下载地址(GIF 动图操作)?

安装部署 Java8

  1. 在服务器上下载 OpenJDK
bash 复制代码
root@localhost:~# wget https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u392-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u392b08.tar.gz
  1. 将其放置到 /usr/local 下:
bash 复制代码
root@localhost:~# tar -xf OpenJDK8U-jdk_x64_linux_hotspot_2023-12-17-03-51.tar.gz -C /usr/local/
  1. 更改下解包后的目录名:
bash 复制代码
root@localhost:~# mv /usr/local/jdk8u402-b04 /usr/local/jdk8
  1. /etc/profile 末尾添加以下内容:
bash 复制代码
root@localhost:~# cat << EOF >> /etc/profile
export JAVA_HOME=/usr/local/jdk8
export PATH=\$PATH:\$JAVA_HOME/bin
export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tools.jar
EOF
  1. 重新载入环境变量配置:
bash 复制代码
root@localhost:~# source /etc/profile
  1. 检查 javajavac 工具:
bash 复制代码
# Java 运行环境
root@localhost:~# java -version
openjdk version "1.8.0_402-beta"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_402-beta-202312161212-b04)
OpenJDK 64-Bit Server VM (Temurin)(build 25.402-b04, mixed mode)

# Java 编译器
root@localhost:~# javac -version
javac 1.8.0_402-beta

Hello World

  1. 编写 HelloWorld.java 代码:
java 复制代码
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
  1. 编译与运行:
bash 复制代码
# 使用 javac 编译 Java 源代码文件
root@localhost:~# javac HelloWorld.java

# 编译成为 Java 字节码文件
root@localhost:~# ll HelloWorld.class
-rw-r----- 1 root root 427 Dec 18 18:41 HelloWorld.class

# 运行 HelloWorld.class 字节码文件
root@localhost:~# java HelloWorld
Hello, World!

编程基础

注释

Java 中有三种类型的注释:

  • 单行注释:
java 复制代码
// 这是一个单行注释。
  • 多行注释或块注释:
java 复制代码
/*
这是
一个多行
注释。
*/
  • 文档注释:这种类型的注释被 javadoc 工具用来从源文件中生成文档。
java 复制代码
/**
* 这是一个文档化注释(DocComment)。
* @param name 一个代表名字的字符串
* @return String 一个代表问候的字符串
*/
public String sayHello(String name) {
    return "Hello, " + name;
}

变量

Java 在定义变量时遵循 "类型在前,名称在后" 的规则,与 C++C# 等语言一样。而元年后诞生的新语言,如 GoRust 则正相反,在定义变量时采取了 "名称在前,类型在后" 的规则,它们在设计之初使语法更贴近自然语言的表达习惯。

java 复制代码
public class Main {
    public static void main(String[] args) {
        int age = 30;             // 整型变量在 Java 中默认占用4个字节
        double score = 90.6;      // 双精度浮点型变量在 Java 中默认占用8个字节
        char gender = '男';       // 字符型变量在 Java 中占用2个字节
        String name = "mystic";   // 字符串类型在 Java 中是一个引用类型,它的长度只受限于可用内存

        System.out.println("Age: " + age);
        System.out.println("Score: " + score);
        System.out.println("Gender: " + gender);
        System.out.println("Name: " + name);
    }
}

加号

Java 中,加号主要有两种用途,一种是作为数学加法运算符,一种是作为字符串连接运算符。

当一个数字和一个字符串相加时,数字将会被转换为字符串,然后再进行字符串连接。

java 复制代码
public class Main {
    public static void main(String[] args) {
        // 加号作为数学加法运算符
        int a = 5;
        int b = 3;
        int sum = a + b;
        System.out.println("The sum is: " + sum);  // 输出 "The sum is: 8"

        // 加号作为字符串连接运算符
        String str1 = "Hello ";
        String str2 = "World";
        String message = str1 + str2;
        System.out.println(message);  // 输出 "Hello World"

        // 数字和字符串相加
        int num = 30;
        String str = "岁";
        String result = num + str;
        System.out.println(result);  // 输出 "30岁"
    }
}

数据类型

Java 中,每种数据都有其明确定义的数据类型。这种数据类型决定了在内存中为这个特定数据分配的具体空间大小(以 byte 为单位)。这不仅确保数据的安全,并且由于每种数据类型所需要的内存大小是固定的,Java 能够更有效地管理和使用内存。

数据类型 分类 具体 说明
基本数据类型 数值型 整型 byte 1 字节,取值范围:-128~127
基本数据类型 数值型 整型 short 2 字节,取值范围:-32768~32767
基本数据类型 数值型 整型 int 4 字节,取值范围:-2147483648~2147483647(Java 的默认整型)
基本数据类型 数值型 整型 long 8 字节,取值范围:-9223372036854775808~9223372036854775807
基本数据类型 数值型 浮点型 float 4 字节,能表示大约 7 位有效数字的浮点数
基本数据类型 数值型 浮点型 double 8 字节,能表示大约 16 位有效数字的浮点数(Java 的默认浮点型)
基本数据类型 字符型 char 2 字节,用于表示 Unicode 码点在 U+0000 到 U+FFFF 之间的字符
基本数据类型 布尔型 boolean 布尔类型,只有两个取值:true 或 false
引用数据类型 类(Class) String 用于表示字符序列,非常常用
引用数据类型 类(Class) Integer 用于表示整数,是 int 类型的包装类
引用数据类型 类(Class) ArrayList 用于表示动态数组,能够自动调整其大小
引用数据类型 类(Class) Date 用于表示日期和时间
引用数据类型 类(Class) Etc. 类(Class)实际上可以定义任何类型的对象,包括系统内置类和用户定义类
引用数据类型 接口(Interface) - 用来定义行为的类型,包含方法的签名,但不包含方法的实现
引用数据类型 数组(Array) - 用于存储同一类型多个值的容器

类型转换

基本类型转换

自动类型转换(隐式类型)

自动类型转换通常发生在两种兼容类型之间,且目标类型大于源类型时。在这种情况下,数据将自动转换为更宽的类型,不会丢失信息。

java 复制代码
int numInt = 100;
long numLong = numInt; // 自动类型转换,从 int 转为 long

强制类型转换(显式类型)

如果需要将兼容的类型进行转换,但目标类型小于源类型。这可能导致数据丢失。在这种情况下,需要使用强制类型转换。

java 复制代码
double numDouble = 100.99;
int numInt = (int) numDouble; // 强制类型转换,从 double 转为 int

字符串的互转

Java 实际的项目开发中,String 与基本数据类型之间的转换是十分常见的,下面举例可供我们在代码中灵活使用。

基本数据类型转换为 String

使用 String.valueOf() 方法,这是最直接的方式。

java 复制代码
int num = 456;
String str = String.valueOf(num);

使用 + 运算符,对于任何数据类型,Java 都会自动将其他数据类型与 String 相加的结果类型定为 String

java 复制代码
int num = 456;
String str = num + "";

String 转换为基本数据类型

每一种基本数据类型(包含包装类型)都有对应的 parseXXX() 方法(将 String 转换为对应的基本数据类型)。

java 复制代码
String str = "123";
int num = Integer.parseInt(str);

但请注意,parseXXX() 方法在处理不能转换为对应类型的字符串时,会抛出 java.lang.NumberFormatException 异常。

运算符

Java 中的常用运算符及其使用方法:

运算符 符号 说明
算术运算符 + 加法
算术运算符 - 减法
算术运算符 * 乘法
算术运算符 / 除法
算术运算符 % 取余
算术运算符 ++ 自增
算术运算符 -- 自减
关系运算符 == 等于
关系运算符 != 不等于
关系运算符 > 大于
关系运算符 < 小于
关系运算符 >= 大于等于
关系运算符 <= 小于等于
逻辑运算符 && 逻辑与
逻辑运算符 || 逻辑或
逻辑运算符 ! 逻辑非
赋值运算符 = 简单赋值
赋值运算符 += 加等于
赋值运算符 -= 减等于
赋值运算符 *= 乘等于
赋值运算符 /= 除等于
赋值运算符 %= 取余等于
三元运算符 Boolean ? value1 : value2 如果 Boolean 为 true,结果为 value1,否则为 value2

Java 中运算符优先级的顺序(由高到低):

java 复制代码
[] . ()                // 数组下标、点操作符、括号
! ~ ++ --              // 逻辑非、位非、自增、自减
* / %                  // 乘、除、取模
+ -                    // 加、减
<< >> >>>              // 左位移、右位移、无符号右位移
< <= > >= instanceof   // 小于、小于等于、大于、大于等于、检查是否为某类型
== !=                  // 等于、不等于
&                      // 逻辑与、按位与
^                      // 逻辑异或、按位异或
|                      // 逻辑或、按位或
&&                     // 短路与
||                     // 短路或
?=                     // 赋值、加等、减等、乘等、除等、取模等等

关键字

Java 中的关键字是一些预先定义的、具有特殊意义的单词,它们作为 Java 语言的基本构建块在 Java 代码中起着重要的作用。

以下是 Java 关键字的列表:

text 复制代码
abstract, assert, boolean, break, byte, case, catch, char, class, const, continue, 
default, do, double, else, enum, extends, final, finally, float, for,
goto, if, implements, import, instanceof, int, interface, long, native, 
new, package, private, protected, public, return, short, static, 
strictfp, super, switch, synchronized, this, throw, throws, transient, 
try, void, volatile, while

需注意的是 constgoto 是保留关键字,但在 Java 中并未被使用。

另外,true, false, null 被称为字面量 (Literals),在某些情况下,它们也可以被视为关键字。

用户输入

Java 中,我们通常会使用 java.util.Scanner 类来获取用户输入。以下是一个示例:

java 复制代码
import java.util.Scanner;  // 导入 Scanner 类

public class UserInput {
    public static void main(String[] args) {
        Scanner myObj = new Scanner(System.in);          // 创建一个 Scanner 对象
        System.out.println("Enter username");

        String userName = myObj.nextLine();              // 读取用户输入
        System.out.println("Username is: " + userName);  // 输出用户输入
    }
}

控制结构

顺序控制

Java 中,变量通常应在使用之前进行声明和初始化。Java 中定义成员变量时采用合法的前向引用。如:

java 复制代码
public class ForwardReference {
    public static void main(String[] args) {
        System.out.println(value);  // 错误的前向引用,因为在打印它的值之前它尚未初始化
        int value = 10;
    }
}

分支控制

Java 中,有三种主要的分支控制结构:if 语句、switch 语句和 ?: (三元运算符)。

java 复制代码
public class Main {
    public static void main(String[] args) {

        // if 语句
        int num = 10;
        if (num > 0) {
            System.out.println("Number is positive.");
        } else if (num < 0) {
            System.out.println("Number is negative.");
        } else {
            System.out.println("Number is zero.");
        }

        // switch 语句
        int day = 3;
        switch (day) {
            case 1:
                System.out.println("Monday");
                break;
            case 2:
                System.out.println("Tuesday");
                break;
            case 3:
                System.out.println("Wednesday");
                break;
            // 其他 days...
            default:
                System.out.println("Invalid day");
        }

        // 三元运算符
        String result = (num > 0) ? "Positive" : "Not positive";
        System.out.println(result);
    }
}

循环控制

Java 中,有三种主要的循环结构:for 循环,while 循环和 do...while 循环。

java 复制代码
public class Main {
    public static void main(String[] args) {

        // for 循环
        System.out.println("FOR LOOP:");
        for (int i = 0; i < 5; i++) {
            System.out.println("The value of i is: " + i);
        }

        // while 循环
        System.out.println("\nWHILE LOOP:");
        int j = 0;
        while (j < 5) {
            System.out.println("The value of j is: " + j);
            j++;
        }

        // do...while 循环
        System.out.println("\nDO...WHILE LOOP:");
        int k = 0;
        do {
            System.out.println("The value of k is: " + k);
            k++;
        } while (k < 5);
    }
}

Java 中,breakcontinue 这两个重要的关键字,它们具有控制程序执行流程的能力。

java 复制代码
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {

            // continue 用于在循环中直接开始下一次循环,忽略剩下的循环代码。
            if (j == 2) {
                continue; 
            }

            // break 语句通常用在循环或者 switch 语句中,用来立即结束当前的循环或者 switch,跳到下一条可执行代码。
            if (i == 3) {
                break;
            }
            System.out.println("The value of i is: " + i);
        }
    }
}

数组

Java 的数组是一个容器对象,它能够存储固定数量的具有相同类型的值。也就是说,数组的大小一旦创建,就不能改变。每一个存储在数组中的值可以通过索引进行访问。

声明数组

格式:

java 复制代码
dataType[] arrayName;   // 推荐使用
dataType arrayName[];   // 也可以,但不常见

示例:

java 复制代码
int[] myArray;

初始化数组

创建新数组:

java 复制代码
myArray = new int[5];   // 它有5个元素,默认值是0

声明并初始化

在声明时直接初始化数组:

java 复制代码
int[] myArray = new int[5];

也可以指定数组的具体内容:

java 复制代码
int[] myArray = {1, 2, 3, 4, 5};

访问数组

可以通过数组的索引来访问数组的元素:

java 复制代码
int firstElement = myArray[0];

也可以修改数组中的元素:

java 复制代码
myArray[0] = 60;

获取数组长度

通过 length 属性,可以得到数组的长度:

java 复制代码
int length = myArray.length;

遍历数组

可以使用 for 循环或 foreach 循环来遍历数组:

java 复制代码
// 使用普通 for 循环遍历数组
for(int i = 0; i < myArray.length; i++) {
    System.out.println(myArray[i]);
}

// 使用 foreach 循环遍历数组
for(int num : myArray) {
    System.out.println(num);
}

引用传递

Java 中,数组是对象,所以在对数组赋值或复制时,是按引用传递的,而不是按值传递。

java 复制代码
// 当你把一个数组标识符赋值给另一个数组标识符时,你只是复制了数组的引用,而不是数组本身。这意味着这两个引用指向的是同一个数组。
int[] array1 = {1, 2, 3, 4, 5};
int[] array2 = array1;

array2[0] = 10;

System.out.println(array1[0]);  // 输出 10

拷贝数组

如果想要在 Java 中得到数组的一个新副本,需要创建一个新的数组并复制每个元素,可以使用 System.arraycopyArrays.copyOf 方法。

java 复制代码
public class Main {
    public static void main(String[] args) {
        int[] array1 = {1, 2, 3, 4, 5};
        int[] array2 = new int[array1.length];

        // 1. 使用 System.arraycopy 方法
        System.arraycopy(array1, 0, array2, 0, array1.length);

        // 2. 使用 Arrays.copyOf 方法
        // int[] array2 = Arrays.copyOf(array1, array1.length);

        array2[0] = 10;

        System.out.println(array1[0]);  // 输出 1
        System.out.println(array2[0]);  // 输出 10
    }
}

反转数组

java 复制代码
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5};
        System.out.println("原始数组:" + Arrays.toString(array));

        int temp = 0;
        int len = array.length;
        for (int i = 0; i < len / 2; i++) {
            temp = array[len - 1 - i];
            array[len - 1 - i] = array[i];
            array[i] = temp;
        }

        System.out.println("反转数组:" + Arrays.toString(array));
    }
}

二维数组

Java 中,二维数组其实就是数组的数组,通常可以用来表示一个表格或者矩阵。

初始化二维数组

java 复制代码
int[][] array = new int[3][3];  // 3x3的二维数组,所有元素初始化为0

在声明的同时给二维数组赋值:

java 复制代码
int[][] array = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

这个数组可以被看成一个 3x3 的矩阵。

访问二维数组元素

可以通过两个索引来访问二维数组的一个元素:

java 复制代码
int value = array[2][2]; // 此时, value 的值是9

遍历二维数组

可以使用两层嵌套的 for 循环来遍历二维数组:

java 复制代码
for (int i = 0; i < array.length; i++) {
    for (int j = 0; j < array[i].length; j++) {
        System.out.println(array[i][j]);
    }
}
相关推荐
Pandaconda3 分钟前
【计算机网络 - 基础问题】每日 3 题(十)
开发语言·经验分享·笔记·后端·计算机网络·面试·职场和发展
loveLifeLoveCoding5 分钟前
Java List sort() 排序
java·开发语言
草履虫·11 分钟前
【Java集合】LinkedList
java
AngeliaXue13 分钟前
Java集合(List篇)
java·开发语言·list·集合
世俗ˊ14 分钟前
Java中ArrayList和LinkedList的比较
java·开发语言
zhouyiddd19 分钟前
Maven Helper 插件
java·maven·intellij idea
攸攸太上27 分钟前
Docker学习
java·网络·学习·docker·容器
Milo_K35 分钟前
项目文件配置
java·开发语言
程序员大金39 分钟前
基于SpringBoot+Vue+MySQL的养老院管理系统
java·vue.js·spring boot·vscode·后端·mysql·vim
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS网上购物商城(JAVA毕业设计)
java·vue.js·spring boot·后端·开源