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 classclass 都是对类进行声明,用于定义类。
    • 对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 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 数据类型表示一位的信息。
    • 只有两个取值:truefalse
    • 默认值是 false
    • 这种类型只作为一种标志来记录 true/false 情况

char:

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

字符串类型

  • 字符串类型 StringJava 一个内置的类。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 运算符优先级


作用

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

优先级对照

取自菜鸟教程