Java 复习

大一下有过 Java 课程,但是当时主要是为了应试,现在已经忘完了(

这学期的算法课作业要求用 Java 完成,于是打算复习复习 Java 的基础部分(够用就行)。

基础

Java 程序基础

Java 程序基本结构

Hello, world! 为例。

public class Exercise {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

因为 Java 是面向对象的语言,一个程序的基本单位就是 classclass 是关键字,这里定义的 class 名字就是 Exercise

类名要求:

  • 必须以英文字母开头,后接字母,数字和下划线的组合。
  • 习惯以大写字母开头。

其中,public 是修饰符,表示该 class 是公开的。

class 内部,可以定义若干方法(method),如上代码中,有方法 main,返回值是 void,表示没有任何返回值。

注意到 public 除了可以修饰 class 外,也可以修饰方法。而关键字 static 是另一个修饰符,它表示静态方法。

方法命名要求与类名要求一样,但是首字母一般小写。

变量和数据类型

变量

在 Java 中,变量必须先定义再使用,定义时需要指定初始值。

public class Exercise {
    public static void main(String[] args) {
        int x = 10;
        System.out.println("x="+x);
        x=100;
        System.out.println("x="+x);
    }
}

如上代码,其输出为

x=10
x=100

基本数据类型

  • 整数类型:byte, short, int, long
  • 浮点数类型:float, double
  • 字符类型:char
  • 布尔类型:boolean
整型

Java 只定义了带符号的整型。

public class Exercise {
    public static void main(String[] args) {
        int a = 2_000_000_000; // 加下划线更容易识别
        int b = 0xff0000; // 十六进制表示的 16711680
        int c = 0b1000000000; // 二进制表示的 512
        long d = 90000000000000L; // long 型结尾要加 L
        long e = 900; // 没有加 L, 此处 900 为 int 类型,但是 int 类型可以赋值给 long
    }
}

上面是一些正确的定义整型的例子。

但是 long 型无法赋值给 int,如 int g=900L 就是错误的。

浮点型

一些浮点数定义的例子:

float f1 = 3.14f;
float f2 = 3.14e38f; // 科学计数法表示的3.14x10^38
float f3 = 1.0; // 错误:不带f结尾的是double类型,不能赋值给float

double d = 1.79e308;
double d2 = -1.79e308;
double d3 = 4.9e-324; // 科学计数法表示的4.9x10^-324

对于 float 类型,需要加上 f 后缀。

布尔类型

布尔类型 boolean 只有 truefalse 两个值,布尔运算总是关系运算的计算结果。

字符类型

字符类型 char 表示一个字符。Java的 char 类型除了可表示标准的 ASCII 外,还可以表示一个 Unicode 字符。

引用类型

除了上述基本类型的变量,剩下的都是引用类型。例如,引用类型最常用的就是 String 字符串。

引用类型的变量类似于C语言的指针,它内部存储一个“地址”,指向某个对象在内存的位置。

常量

定义变量的时候,如果加上final修饰符,这个变量就变成了常量,类似于 c++const

为了与变量区分开来,常量名通常全部大写。

var 关键字

有时候类型名字太长,写起来很麻烦,例如

StringBuilder sb = new StringBuilder();

这时可以使用 var 关键字:

var sb = new StringBuilder();

整数运算

感觉与 C++ 差不多,一样的部分不写了。

类型自动提升与强制转型

在运算过程中,如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。例如,shortint 计算,结果总是 int,原因是 short 首先自动被转型为 int

也可以将结果强制转型,即将大范围的整数转型为小范围的整数。强制转型使用 (类型) ,例如,将 int 强制转型为 short

要注意,超出范围的强制转型会得到错误的结果,原因是转型时,int 的两个高位字节直接被扔掉,仅保留了低位的两个字节。

浮点数运算

浮点数会产生误差,所以判断两浮点数是否相等时,通常要设一个 eps ,作差后与 eps 比较。

类型提升

如果参与运算的两个数其中一个是整型,那么整型可以自动提升到浮点型。

溢出

整数运算除数为 0 时会报错,但是浮点数运算在除数为 0 时不会报错,会返回几个特殊值:

  • NaN 表示 Not a Number
  • Infinity 表示无穷大
  • -Infinity 表示负无穷大

强制转型

可以将浮点数强制转型为整数。在转型时,浮点数的小数部分会被丢掉。如果转型后超过了整型能表示的最大范围,将返回整型的最大值。

一个应用:如果要进行四舍五入,可以将浮点数加上 0.5 后再强制转型。

布尔运算

运算符与 C++ 一致,不写了。

短路运算

布尔运算的一个重要特点是短路运算。如果一个布尔运算的表达式能提前确定结果,则后续的计算不再执行,直接返回结果。

因为 false && x 的结果总是 false,无论 xtrue 还是 false ,因此,与运算在确定第一个值为 false 后,不再继续计算,而是直接返回 false

public class Exercise {
    public static void main(String[] args) {
        boolean b = 5 < 3;
        boolean result = b && (5 / 0 > 0);
        System.out.println(result);
    }
}

如上代码,如果没有短路运算, && 后面的表达式会因为除数为 0 而报错,但是 b 的值为 false ,由于短路运算,提前计算出了结果 false

|| 类似。

三元运算符

类似 C++ 的三目运算符,不写了。

字符串

字符串类型 String 是引用类型。

字符串连接

Java 中,可以用 + 连接任意字符串和其他数据类型。

如果用 + 连接字符串和其他数据类型,会将其他数据类型先自动转型为字符串,再连接。

多行字符串

Java 13 开始,字符串可以用 ... 来表示多行字符串。

如:

public class Exercise {
    public static void main(String[] args) {
        String s = """
                SELECT * FROM
                  users
                WHERE id > 100
                ORDER BY name DESC
                """;
        System.out.println(s);
    }
}

输出为

SELECT * FROM
  users
WHERE id > 100
ORDER BY name DESC

会以最短的行首空格为基准。

不可变特性

即“引用”特性。

public class Exercise {
    public static void main(String[] args) {
        String s = "hello";
        String t = s;
        s = "world";
        System.out.println(t);
    }
}

由于引用特性,该代码输出为 hello

空值 null

引用类型的变量可以指向一个空值 null ,表示不存在,即该变量不指向任何对象。

注意 null 和 空字符串 "" 的区别,空字符串是一个有效的字符串对象,它不等于 null

数组类型

定义一个数组类型的变量,使用数组类型“类型[]”,例如, int[] 。和单个基本类型变量不同,数组变量初始化必须使用 new int[5] 表示创建一个可容纳 5 个 int 元素的数组。

几个特点:

  • 数组所有元素初始化为默认值,整型都是 0,浮点型是 0.0,布尔型是 false
  • 数组一旦创建后,大小就不可改变。

可以用 数组变量.length 获取数组大小。

数组是引用类型,在使用索引访问数组元素时,如果索引超出范围,运行时将报错。

也可以在定义数组时直接指定初始化的元素,这样就不必写出数组大小,而是由编译器自动推算数组大小,例如 int[] ns = new int[] { 68, 79, 91, 85, 62 } ,还可以进一步简写为 int[] ns = { 68, 79, 91, 85, 62 }

流程控制

输入和输出

输出

上面的例子中,总是使用 System.out.println() 来输出。

println 是 print line 的缩写,表示输出并换行。如果输出后不想换行,可以用 print()

格式化输出

格式化输出使用 System.out.printf() ,占位符有如下几种:

  • %d ,格式化输出整数
  • %x ,格式化输出十六进制整数
  • %f ,格式化输出浮点数
  • %e ,格式化输出科学计数法表示的浮点数
  • %s ,格式化字符串

感觉用法和 C++printf 差不多。

输入

输入较为复杂。

这是从控制台读取一个字符串和一个整数的例子:

public class Exercise {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); // 创建Scanner对象
        System.out.print("Input your name: "); // 打印提示
        String name = scanner.nextLine(); // 读取一行输入并获取字符串
        System.out.print("Input your age: "); // 打印提示
        int age = scanner.nextInt(); // 读取一行输入并获取整数
        System.out.printf("Hi, %s, you are %d\n", name, age); // 格式化输出
    }
}

首先,我们通过 import 语句导入 java.util.Scannerimport 是导入某个类的语句,必须放到 Java 源代码的开头,后面我们在 Java 的 package 中会详细讲解如何使用 import

然后,创建 Scanner 对象并传入 System.inSystem.out 代表标准输出流,而 System.in 代表标准输入流。直接使用 System.in 读取用户输入虽然是可以的,但需要更复杂的代码,而通过 Scanner 就可以简化后续的代码。

有了 Scanner 对象后,要读取用户输入的字符串,使用 scanner.nextLine(),要读取用户输入的整数,使用 scanner.nextInt()Scanner 会自动转换数据类型,因此不必手动转换。

if 条件判断

基本用法与 C++ 相同,不写了。

判断引用类型相等

无法直接用 == 来判断。

因为 == 只能用来判断两个引用类型的变量是否指向同一个对象,有时候它们的内容相同,但是指向不同的对象。

判断引用类型的变量内容是否相等,必须使用 equals() 方法。

例如判断字符串 s1s2s1.equals(s2)

switch 多重选择

C++ 差不多,不写了。

which 循环

C++ 差不多,不写了。

do while 循环

C++ 差不多,不写了。

for 循环

C++ 差不多,不写了。

for each 循环

int[] ns = { 1, 4, 9, 16, 25 };
for (int n : ns) {
    System.out.println(n);
}

C++ 高级版本里面更新的用法差不多。

breakcontinue

C++ 差不多,不写了。

数组操作

遍历数组

用前面的 for 循环和 for each 循环都可以实现对数组的遍历。

数组排序

可以用 Java 标准库内的 Arrays.sort() 函数来实现对数组的从小到大排序。

int[] ns = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };
Arrays.sort(ns);

多维数组

一个定义二维数组的例子:

public class Exercise {
     public static void main(String[] args) {
            int[][] ns = {
                { 1, 2, 3, 4 },
                { 5, 6, 7, 8 },
                { 9, 10, 11, 12 }
            };
            System.out.println(ns.length); // 3
     }
}

要打印一个二维数组,可以用两层嵌套的 for 循环:

public class Exercise {
     public static void main(String[] args) {
         int[][] ns = {
                    { 1, 2, 3, 4 },
                    { 5, 6 },
                    { 7, 8, 9 }
         };
         for (int[] arr : ns) {
                for (int n : arr) {
                    System.out.print(n);
                    System.out.print(", ");
                }
                System.out.println();
         }
     }
}

或者使用 Java 标准库的 Arrays.deepToString()

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[][] ns = {
            { 1, 2, 3, 4 },
            { 5, 6 },
            { 7, 8, 9 }
        };
        System.out.println(Arrays.deepToString(ns));
    }
}

类似的,也可知三维数组的定义与遍历。

参考资料

简介 – Java教程 – 廖雪峰的官方网站 (liaoxuefeng.com)

Avatar photo
HoshiuZ
文章: 13

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注