Skip to content

java ​

1. Java 初识 ​


1.1 第一个Java程序 ​


一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。类似 C/C++ 语言,需要一个函数(在面向对象中,这被称为方法)作为程序执行的入口点。

基本概念:

  • 对象:对象是类的一个实例,有状态和行为。
    • 类:类是一个模板,它描述一类对象的行为和状态。
    • 方法:方法就是行为,一个类可以有很多方法。逻辑运算、数据修改以及所有动作都是在方法中完成的。
    • 实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。

Java程序:

java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World"); 
    }
}

关于public class HelloWorld:

  • public class 和 class 都是对类进行声明,用于定义类。
    • 对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 MyFirstJavaClass。
    • 使用 public class 时,必须保持类名与文件名一致,即 public class HelloWorld 的类名 HelloWorld 和文件名是一致的。
    • 被 public 修饰的类可以被其他包访问,没有被 public 修饰的类可以访问 public 类,但不能被其他包访问。
    • 每个文件中只能有不多于 \(1\) 个 public 类(也可以没有)。

关于public static void main(String[] args):

  • String args[] 与 String[] args 都可以执行,但推荐使用 String[] args,这样可以避免歧义和误读。
    • 既定主函数的格式,所有的 Java 程序由该方法开始执行。

注意:

  • 对于大部分OJ平台,统一提供入口为 public class Main,之后代码示例将延用此标准。

1.2 注释 ​


和 C/C++ 一样,Java 使用 // 和 /* */ 分别注释单行和多行。

作用:

  • 可以用来解释程序的意思,还可以让某段代码不执行(但是依然保留在源文件里)。
    • 在代码中加一些说明和解释,方便自己或其他程序员阅读代码。

两种格式:

  1. 单行注释:// 描述信息
    java
    // 通常放在一行代码的上方,或者一条语句的末尾,对该行代码说明。
  2. 多行注释:/* 描述信息 */
    java
    /* 通常放在一段代码的上方,对该段代码做整体说明。 */

示例:

java
public class HelloWorld {
    /* 这是第一个Java程序
     * 它将输出 Hello World
     * 这是一个多行注释的示例
     */
    public static void main(String[] args) {
        // 这是单行注释的示例
        /* 这个也是单行注释的示例 */
        System.out.println("Hello World"); 
    }
}

1.3 输入和输出 ​


  • 这里我们只介绍简单的输入和输出,关于抛出异常等深入内容暂至后面的章节。

A+B 示例:

java
import java.util.Scanner;  //导入Scanner包

public class Main {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int a = cin.nextInt();  //输入a。
        int b = cin.nextInt();  //输入b。

        System.out.println(a + b);  //输出a + b。
    }
}

1.3.1 输入 ​


方式1:

  • 效率低,输入规模较小时使用。
java
Scanner sc = new Scanner(System.in);
String str = sc.next();  // 读入下一个字符串
int x = sc.nextInt();  // 读入下一个整数
float y = sc.nextFloat();  // 读入下一个单精度浮点数
double z = sc.nextDouble();  // 读入下一个双精度浮点数
String line = sc.nextLine();  // 读入下一行

方式2:

  • 效率较高,输入规模较大时使用。注意需要抛出异常。
java
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str = br.readLine();
        System.out.println(str);
    }
}

1.3.2 输出 ​


方式1:

  • 效率低,输出规模较小时使用。
java
System.out.println("Hello World");  // 输出并换行
System.out.print("Hello World");    // 输出但不换行
System.out.println(123);            // 输出数字
System.out.println(123);  // 输出整数 + 换行
System.out.println("Hello World");  // 输出字符串 + 换行
System.out.print(123);  // 输出整数
System.out.print("lys is a dog\n");  // 输出字符串
System.out.printf("%04d %.2f\n", 4, 123.456D);  // 格式化输出,float与double都用%f输出

方式2:

  • 效率较高,输出规模较大时使用。注意需要抛异常。
java
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        bw.write("Hello World\n");
        bw.flush();  // 需要手动刷新缓冲区
    }
}

2. 数据类型 ​


2.1 变量 ​


作用:

  • 给一段指定的内存空间起名,方便操作这段内存。
    • 变量只是一个声明,声明存储对应的数据类型。

语法:

  • 数据类型 变量名;
    • 数据类型 变量名 = 初始值;

示例:

java
public class Main {
    public static void main(String[] args) {
        int a = 5;
        int b, c = a, d = 10 / 2;
    }
}

2.2 内置数据类型 ​


Java 语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。

类型名意义字节数
byte字节型1
short短整型2
int整型4
long长整型8
float单精度浮点型4
double双精度浮点型8
boolean布尔型1
char字符型2

byte:

  • byte 数据类型是 8 位、有符号的,以二进制补码表示的整数。
    • 范围: -128(-2^7) ~ 127(2^7-1)。
    • 默认值是 0。
    • byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一。

short:

  • short 数据类型是 16 位、有符号的以二进制补码表示的整数。
    • 范围: -32768(-2^{15}) ~ 32767(2^{15} - 1)。
    • 默认值是 0。

int:

int 数据类型是 32 位、有符号的以二进制补码表示的整数。

  • 范围:-2,147,483,648(-2^{31}) ~ 2,147,483,647(2^{31} - 1)
  • 默认值是 0
  • 一般地整型变量默认为 int 类型

long:

  • long 数据类型是 64 位、有符号的以二进制补码表示的整数。
    • 最小值是 -9,223,372,036,854,775,808(-2^{63}) ~ 9,223,372,036,854,775,807(2^{63} - 1)
    • 默认值是 0L
    • 这种类型主要使用在需要比较大整数的系统上
    • "L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易辨别。所以最好大写

float:

  • float 数据类型是单精度、32 位、符合 IEEE 754标准 的浮点数。
    • 默认值是 0.0f
    • 浮点数不能用来表示精确的值
    • float 在储存大型浮点数组的时候可节省内存空间

double:

  • double 数据类型是双精度、64 位、符合 IEEE 754标准 的浮点数。
    • 默认值是 0.0d
    • double 类型同样不能表示精确的值
    • 浮点数的默认类型为 double 类型

boolean:

  • boolean 数据类型表示一位的信息。
    • 只有两个取值:true 和 false
    • 默认值是 false
    • 这种类型只作为一种标志来记录 true/false 情况

char:

  • char 类型是一个单一的 16 位 Unicode 字符。
    • 范围:\u0000(十进制等效值为 0) ~ \uffff(即为 65535)
    • char 数据类型可以储存任何字符

字符串类型:

  • 字符串类型 String 是 Java 一个内置的类。String 表示字符串类型,属于 引用数据类型,不属于基本数据类型。
    • 关于此内容详见后续章节

对应格式化输出:

符号意义
%d整数类型
%f浮点类型
%c字符类型

2.3 特殊转义字符 ​


Java 语言支持一些特殊的转义字符序列。

符号字符含义
\n换行 (0x0a)
\r回车 (0x0d)
\f换页符 (0x0c)
\b退格 (0x08)
\0空字符 (0x0)
\s空格 (0x20)
\t制表符
\"双引号
\'单引号
\\反斜杠
\ddd八进制字符 (ddd)
\uxxxx16进制 Unicode 字符 (xxxx)

2.4 常量 ​


作用:

  • 使用 final 修饰,用于记录程序中不可更改的数据

语法:

  • final 数据类型 常量名 = 初始化值;

注意:

常量是固定值,在程序执行期间不会改变。
常量的值在定义后不能被修改,修改则会报错。


2.5 类型转换 ​


2.5.1 自动类型转换 ​


解释:

  • 整型、实型、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。

规则:

  • 自动类型转换从低级到高级。
java
低  ----------------------------------------->  高
byte,short,char —> int —> long —> float —> double
  • 不能对 boolean 类型进行类型转换。

  • 不能把对象类型转换成不相关类的对象。

  • 在把容量大的类型转换为容量小的类型时必须使用强制类型转换。

  • 转换过程中可能导致溢出或损失精度,例如:

java
int i = 128;   
byte b = (byte)i;

因为 byte 类型是 8 位,最大值为 127,所以当 int 强制转换为 byte 类型时,值 128 就会导致溢出。

  • 浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入,例如:
java
(int)23.7 == 23;        
(int)-45.89f == -45;

条件:

  • 必须满足转换前的数据类型的容量要低于转换后的数据类型。
    • 例如:short 数据类型就可以自动转换为 int 类型,同样 float 数据类型可以自动转换为 double 类型。

示例:

java
public class Main {
    public static void main(String[] args) {
        char c1 = 'a'; // 定义一个char类型
        int i1 = c1; // char自动类型转换为int
        System.out.println("char自动类型转换为int后的值等于" + i1);
        char c2 = 'A'; // 定义一个char类型
        int i2 = c2 + 1; // char类型和int类型计算
        System.out.println("char类型和int计算后的值等于" + i2);
    }
}

2.5.2 强制类型转换 ​


条件:

  • 转换的数据类型必须是兼容的。

格式:

  • (type) value,其中 type 是要强制转换后的数据类型。

示例:

java
public class Main {
    public static void main(String[] args) {
        int i1 = 123;
        byte b = (byte) i1; // 强制类型转换为byte
        System.out.println("int强制类型转换为byte后的值等于" + b);
    }
}

隐含强制类型转换

  • 整数的默认类型是 int。
    • 小数默认是 double 类型浮点数,在定义 float 类型时必须在数字后面跟上 F 或者 f。
    • 例如:double x = 12, y = 4 * 3.3;

3. 运算符 ​


3.1 算术运算符 ​


作用:

  • 用于处理四则运算。

算术运算符包括以下符号:

运算符术语示例结果
+正号+33
-负号-3-3
+加10 + 515
-减10 - 55
*乘10 * 550
/除10 / 52
%取模(取余数)10 % 31
++前置递增a = 2; b = ++a;a = 3; b = 3;
++后置递增a = 2; b = a++;a = 3; b = 2;
--前置递减a = 2; b = --a;a = 1; b = 1;
--后置递减a = 2; b = a--;a = 1; b = 2;

注意:

  • 在除法运算中,除数不能为 0。
    • 只有整型变量可以进行取模运算。
    • 前置递增先对变量进行 ++,再计算表达式,后置递增相反。

3.2 赋值运算符 ​


作用:

  • 用于将表达式的值赋给变量。

赋值运算符包括以下几个符号:

运算符术语示例结果
=赋值a = 2; b = 3;a = 2; b = 3;
+=加等于a = 0; a += 2;a = 2;
-=减等于a = 5; a -= 3;a = 2;
*=乘等于a = 2; a *= 2;a = 4;
/=除等于a = 4; a /= 2;a = 2;
%=模等于a = 3; a %= 2;a = 1;

对于复合赋值运算符 +=:例如 a = 0; a += 2;,等价为 a = 0; a = a + 2,结果 a = 2,其余复合赋值运算符的运算同理。


3.3 比较运算符 ​


作用:

  • 用于表达式的比较,并返回一个真值或假值。

比较运算符有以下符号:

运算符术语示例结果
==相等于4 == 30
!=不等于4 != 31
&lt;小于4 < 30
&gt;大于4 > 31
&lt;=小于等于4 <= 30
&gt;=大于等于4 >= 11

注意:

要将等于运算符 == 和赋值运算符 = 区分开来,这在判断语句中尤为重要。

  • 例如:if (op = 1) 与 if (op == 1) 看起来类似,但实际功能却相差甚远。第一条语句是在对 op 进行赋值,若赋值为非 0 时为真值,表达式的条件始终是满足的,无法达到判断的作用;而第二条语句才是对 op 的值进行判断。

3.4 逻辑运算符 ​


作用:

  • 用于根据表达式的值返回真值或假值。

逻辑运算符有以下符号:

运算符术语示例结果
!非!a如果 a 为假,则 !a 为真;如果 a 为真,则 !a 为假。
&&与a && b如果 a 和 b 都为真,则结果为真,否则为假。
``或

3.5 位运算符 ​


作用:

  • 位运算就是基于整数的二进制表示进行的运算。
    • 由于计算机内部就是以二进制来存储数据,位运算是相当快的。

运算符及运算规则:

运算运算符数学符号解释
与&\(\&\)只有两个对应位都为 \(1\) 时才为 \(1\)
或|\(\mid\)只要两个对应位中有一个为 \(1\) 时就为 \(1\)
取反~\(\sim\)按位取反,即对应的 \(0\) 变为 \(1\), \(1\) 变为 \(0\)
异或^\(\oplus\)只有两个对应位不同时才为 \(1\)
java
// 与运算
0 & 0 = 0;
0 & 1 = 0;
1 & 0 = 0;
1 & 1 = 1;

// 或运算
0 | 0 = 0;
0 | 1 = 1;
1 | 0 = 1;
1 | 1 = 1;

// 取反运算
~0 = 1;
~1 = 0;

// 异或运算
0 ^ 0 = 0;
0 ^ 1 = 1;
1 ^ 0 = 1;
1 ^ 1 = 0;

// 右移运算
n >> k  // 表示 n / 2^k

// 左移运算
n << k  // 表示 n * 2^k

常用模板:

java
// 求x的第k位数字
x >> k & 1;

// 求x的最后一位1
x & -x;

3.6 逗号运算符 ​


作用:

  • 逗号运算符 , 可将多个表达式分隔开来,被分隔开的表达式按从左至右的顺序依次计算,整个表达式的值是最后的表达式的值。

注意:

  • 逗号表达式的优先级在所有运算符中是最低的,即在进行多个表达式运算时,在所有其他运算符运算完毕后才执行逗号运算符的运算。

3.7 运算符优先级 ​


作用:

  • 不同的运算符在表达式中的优先级不同,会使得表达式按一定的运算规则进行运算,使得运算不发生歧义。

优先级对照:

取自菜鸟教程