Java 速成

关于 Java

Java 是一种广泛使用的计算机编程语言,拥有 跨平台面向对象泛型编程 的特性,广泛应用于企业级 Web 应用开发和移动应用开发。

环境安装

Windows

可以在 Oracle 官网 下载 Oracle JDK(需要登录 Oracle 账号)。推荐下载 EXE 安装包来自动配置环境变量。

如果需要使用 OpenJDK,可以使用 AdoptOpenJDK 提供的预编译包。如果下载较慢,可以使用 清华大学 TUNA 镜像站。推荐下载 MSI 安装包来自动配置环境变量。

Linux

使用包管理器安装

可以使用包管理器提供的 JDK。

如果是 Debian 及其衍生发行版(包括 Ubuntu),命令如下:

1
2
sudo apt install default-jre
sudo apt install default-jdk

如同时安装了多个版本,可通过 update-java-alternatives -l 查看目前使用的版本,通过 update-java-alternatives -s <status 中显示的名字> 更改使用的版本。

如果 CentOS 7 及以前则使用的是 yum 安装,命令如下:

1
sudo yum install java-1.8.0-openjdk

在稍后询问是否安装时按下y继续安装,或是你已经下好了 rpm 文件,可以使用以下命令安装:

1
2
sudo yum localinstall jre-9.0.4_linux_x64_bin.rpm #安装jre-9.0
sudo yum localinstall jdk-9.0.4_linux-x64_bin.rpm #安装jdk-9.0

如果 CentOS 8 则使用的是 dnf 安装,命令如下:

1
sudo dnf install java-1.8.0-openjdk

在稍后询问是否安装时按下y继续安装,或是你已经下好了 rpm 文件,可以使用以下命令安装:

1
2
sudo dnf install jre-9.0.4_linux_x64_bin.rpm #安装jre-9.0
sudo dnf install jdk-9.0.4_linux-x64_bin.rpm #安装jdk-9.0

如果是 Arch 及其衍生发行版(如 Manjaro),命令如下:

1
sudo pacman -S jdk8-openjdk # 8可以替换为其他版本,不加则为最新版

如同时安装了多个版本,可通过 archlinux-java status 查看目前使用的版本,通过 archlinux-java set <status 中显示的名字> 更改使用的版本。

手动安装

1
sudo mv jdk-14 /opt

并在 .bashrc 文件末尾添加:

1
2
export JAVA_HOME="/opt/jdk-14"
export PATH=$JAVA_HOME/bin:$PATH

在控制台中输入命令 source ~/.bashrc 即可重载。如果是使用的 zsh 或其他命令行,在 ~/.zshrc 或对应的文件中添加上面的内容。

macOS

如果是 macOS,你可以使用以下命令安装包:

1
2
3
4
5
6
cd ~/Downloads
curl -v -j -k -L -H "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-macosx-x64.dmg > jdk-8u121-macosx-x64.dmg
hdiutil attach jdk-8u121-macosx-x64.dmg
sudo installer -pkg /Volumes/JDK\ 8\ Update\ 121/JDK\ 8\ Update\ 121.pkg -target /
diskutil umount /Volumes/JDK\ 8\ Update\ 121
rm jdk-8u121-macosx-x64.dmg

或者直接在官方网站下载 pkg 包或 dmg 包安装。

基本语法

主函数

Java 类似 C/C++ 语言,需要一个函数(在面向对象中,这被称为方法)作为程序执行的入口点。

Java 的主函数的格式是固定的,形如:

1
2
3
4
5
class Test {
    public static void main(String[] args) {
        // 程序的代码
    }
}

一个打包的 Java 程序(名称一般是 *.jar)中可以有很多个类似的函数,但是当运行这个程序的时候,只有其中一个函数会被运行,这是定义在 JarManifest 文件中的,在 OI 比赛中一般用不到关于它的知识。

注释

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

基本数据类型

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

声明变量

1
2
3
4
int a = 12; // 设置 a 为整数类型,并给 a 赋值为 12
String str = "Hello, OI-wiki"; // 声明字符串变量 str
char ch = 'W';
double PI = 3.1415926;

final 关键字

final 含义是这是最终的、不可更改的结果,被 final 修饰的变量只能被赋值一次,赋值后不再改变。

1
final double PI = 3.1415926;

数组

1
2
3
// 有十个元素的整数类型数组
// 其语法格式为 数据类型[] 变量名 = new 数据类型[数组大小]
int[] ary = new int[10];

字符串

  • 字符串是 Java 一个内置的类。
1
2
3
4
5
6
// 最为简单的构造一个字符串变量的方法如下
String a = "Hello";

// 还可以使用字符数组构造一个字符串变量
char[] stringArray = { 'H', 'e', 'l', 'l', 'o' };
String s = new String(stringArray);

包和导入包

Java 中的类(Class)都被放在一个个包(package)里面。在一个包里面不允许有同名的类。在类的第一行通常要说明这个类是属于哪个包的。例如:

1
package org.oi-wiki.tutorial;

包的命名规范一般是:项目所有者的顶级域.项目所有者的二级域.项目名称

通过 import 关键字来导入不在本类所属的包下面的类。例如下面要用到的 Scanner

1
import java.util.Scanner;

如果想要导入某包下面所有的类,只需要把这个语句最后的分号前的类名换成 *

输入

可以通过 Scanner 类来处理命令行输入。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package org.oiwiki.tutorial;

import java.util.Scanner;

class Test {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in); // System.in 是输入流
        int a = scan.nextInt();
        double b = scan.nextDouble();
        String c = scan.nextLine();
    }
}

输出

可以对变量进行格式化输出。

符号意义
%f浮点类型
%s字符串类型
%d整数类型
%c字符类型
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Test {
    public static void main(String[] args) {
        int a = 12;
        char b = 'A';
        double s = 3.14;
        String str = "Hello world";
        System.out.printf("%f\n", s);
        System.out.printf("%d\n", a);
        System.out.printf("%c\n", b);
        System.out.printf("%s\n", str);
    }
}

更高速的输入输出

ScannerSystem.out.print 在最开始会工作的很好,但是在处理更大的输入的时候会降低效率,因此我们会使用来自 Kattis 的 Kattio.java 来提高 IO 效率。1

下方即为应包含在代码中的 IO 模板,由于 Kattis 的原 Kattio 包含一些并不常用的功能,下方的模板经过了一些调整(原 Kattio 使用 MIT 作为协议)。

 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
class Kattio extends PrintWriter {
    private BufferedReader r;
    private StringTokenizer st;
    // 标准 IO
    public Kattio() { this(System.in,System.out); }
    public Kattio(InputStream i, OutputStream o) {
        super(o);
        r = new BufferedReader(new InputStreamReader(i));
    }
    // 文件 IO
    public Kattio(String intput, String output) throws IOException {
        super(output);
        r = new BufferedReader(new FileReader(intput));
    }
    // 在没有其他输入时返回 null
    public String next() {
        try {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(r.readLine());
            return st.nextToken();
        } catch (Exception e) {}
        return null;
    }
    public int nextInt() { return Integer.parseInt(next()); }
    public double nextDouble() { return Double.parseDouble(next()); }
    public long nextLong() { return Long.parseLong(next()); }
}

而下方代码简单展示了 Kattio 的使用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Test {
    public static void main(String[] args) {
        Kattio io = new Kattio();
        // 字符串输入
        String str = io.next();
        // int 输入
        int num = io.nextInt();
        // 输出
        io.println("Result");
        // 请确保关闭 IO 流以确保输出被正确写入
        io.close();
    }
}

控制语句

Java 的流程控制语句与 C++ 是基本相同的。

选择

  • if
1
2
3
4
5
6
7
class Test {
    public static void main(String[] args) {
        if ( /* 判断条件 */ ){
            // 条件成立时执行这里面的代码
        }
    }
}
  • if...else
1
2
3
4
5
6
7
8
9
class Test {
    public static void main(String[] args) {
        if ( /* 判断条件 */ ) {
            // 条件成立时执行这里面的代码
        } else {
            // 条件不成立时执行这里面的代码
        }
    }
}
  • if...else if...else
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Test {
    public static void main(String[] args) {
        if ( /* 判断条件 */ ) {
            //判断条件成立执行这里面的代码
        } else if ( /* 判断条件2 */ ) {
            // 判断条件2成立执行这里面的代码
        } else {
          // 上述条件都不成立执行这里面的代码
        }
    }
}
  • switch...case
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Test {
    public static void main(String[] args) {
        switch ( /* 表达式 */ ){
          case /* 值 1 */:
              // 当表达式取得的值符合值 1 执行此段代码
              break; // 如果不加上 break 语句,会让程序按顺序往下执行直到 break
          case /* 值 2 */:
              // 当表达式取得的值符合值 2 执行此段代码
              break;
          default:
              // 当表达式不符合上面列举的值的时候执行这里面的代码
        }
    }
}

循环

  • for

for 关键字有两种使用方法,其中第一种是普通的 for 循环,形式如下:

1
2
3
4
5
6
7
class Test {
    public static void main(String[] args) {
        for ( /* 初始化 */; /* 循环的判断条件 */; /* 每次循环后执行的步骤 */ ) {
            // 当循环的条件成立执行循环体内代码
        }
    }
}

第二种是类似 C++ 的 foreach 使用方法,用于循环数组或者集合中的数据,相当于把上一种方式中的循环变量隐藏起来了,形式如下:

1
2
3
4
5
6
7
class Test {
    public static void main(String[] args) {
        for ( /* 元素类型X */ /* 元素名Y */ : /* 集合Z */ ) {
            // 这个语句块的每一次循环时,元素Y分别是集合Z中的一个元素。
        }
    }
}
  • while
1
2
3
4
5
6
7
class Test {
    public static void main(String[] args) {
        while ( /* 判定条件 */ ) {
            // 条件成立时执行循环体内代码
        }
    }
}
  • do...while
1
2
3
4
5
6
7
class Test {
    public static void main(String[] args) {
        do {
          // 需要执行的代码
        } while ( /* 循环判断条件 */ );
    }
}

注意事项

类名与文件名一致

创建 Java 源程序需要类名和文件名一致才能编译通过,否则编译器会提示找不到类。通常该文件名会在具体 OJ 中指定。

例:

Add.java

1
2
3
4
5
class Add {
    public static void main(String[] args) {
        // ...
    }
}

在该文件中需使用 Add 为类名方可编译通过。

参考资料


评论