第一章:Java入门

Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称。由 James Gosling 和同事们共同研发,并在 1995 年正式推出。
后来 Sun 公司被 Oracle (甲骨文)公司收购,Java 也随之成为 Oracle 公司的产品。
Java 分为三个体系:

  • JavaSE (J2SE) (Java2 Platform Standard Edition,Java 平台标准版)。
  • JavaEE (J2EE) (Java 2 Platform,Enterprise Edition,Java 平台企业版)。
  • JavaME (J2ME) (Java 2 Platform Micro Edition,Java 平台微型版)。

2005 年 6 月,JavaOne 大会召开,SUN 公司公开 Java SE 6。此时,Java 的各种版本已经更名,以取消其中的数字 “2”:J2EE 更名为 Java EE,J2SE 更名为 Java SE,J2ME 更名为 Java ME。

1.1 主要特征

  • Java 语言是简单的。
  • Java 语言是面向对象的。
  • Java 语言是分布式的。
  • Java 语言是健壮的。
  • Java 语言是安全的。
  • Java 语言是体系结构中立的。
  • Java 语言是可移植的。
  • Java 语言是解释型的。
  • Java 是高性能的。
  • Java 语言是多线程的。
  • Java 语言是动态的。

    1.2 JDK 下载

    1.2.1 JDK、JRE、JVM的区别

  • JDK : Java Development ToolKit (Java 开发工具包)。 JDK 是整个 Java 的核心,包括了 Java 运行环境(Java Runtime Environment),一些 Java 工具(javac/java/jdb 等)和 Java 基础的类库(即Java API 包括 rt.jar )。

  • JRE:Java Runtime Environment (Java 运行时环境)。也就是我们说的 Java 平台,所有的 Java 程序都要在 JRE 下才能运行。包括 JVM 和 Java 核心类库和支持文件。
  • JVM:Java Virtual Mechinal (Java 虚拟机)。JVM 是 JRE 的一部分,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的

下图很好的表明了JDK,JRE,JVM三者间的关系 (JDK 8):
image.png
TIPS:其他版本的关系图,可去 Oracle 官网 查看。

1.2.2 JDK 下载

首先我们需要下载 Java 开发工具包 JDK,进入 官网 下载,找到我们需要的 JDK 版本(截至目前最新的版本 是Java 18)。
image.png
点击 JDK Download 进入下载页面,选择合适的 Windows/Linux 版本进行下载。
image.png
然后勾选 I reviewed and accept the Oracle Technology Network License Agreement for Oracle Java SE,点击下载。最后会提示您进行登录,登录成功后就可以下载了。
image.png
下载完成后就可以开始安装了,双击下载 exe 文件。
image.png
image.png
TIPS:
开发环境:指的是 JDK 内容。
源代码:是安装 Java SE 源代码文件,如果是安装源代码,安装完成之后会在 JDK 安装路径下看到 src.zip 文件。
公共 JRE:就是 Java 运行环境,这里可以不安装,因为 JDK 文件夹中也会有一个 JRE。
image.png

image.png

image.png

image.png
安装完 JDK 之后会弹出一个安装 JRE 的提示,可以选择不安装。

1.3 JDK 安装

1.3.1 Windows 上安装 Java

1.3.1.1 配置环境变量

点击 计算机——系统属性——高级系统设置——高级——环境变量
在环境对话框内有两个变量:上面的是用户变量(用于配置当前的用户);下面的是系统变量(配置所有的用户)。

image.png
TIPS:如果选择在用户变量中新建 JAVA_HOME,可能后面会出现 javac 不是内部或外部命令,也不是可运行的程序

  1. 设置 JAVA_HOME:所以我们选择在系统变量新建。

JAVA_HOME D:\java\jdk (这是JDK的路径)
image.png

  1. 设置 Path:在系统变量中编辑 Path(多个变量之间要用分号隔开)。

Path %JAVA_HOME%\bin (JDK中的bin文件路径)
image.png

  1. 设置 CLASSPATH:防止出现找不到或无法加载主类问题。

TIPS:变量值可以只填一个点,后面的变量写不写都是可以的,如果不放心的话可以加上。
CLASSPATH .;D:\java\jdk\lib;D:\java\jdk\lib\dt.jar;D:\java\jdk\lib\tools.jar
image.png

1.3.1.2 检测 Jdk 是否安装成功

在命令窗口中输入 javac ,看看有没有出现下载类似的信息,代表安装成功。
image.png

1.3.2 Linux 上安装 Java

1.3.2.1 源码包解压

上传至 Linux 系统上,使用 xftp 将 JDK 源码包,上传到 /usr/local (软件一般安装到这个目录)。
image.png
使用解压命令解压。
[root@localhost local]# tar -zxvf jdk-8u181-linux-x64.tar.gz

1.3.2.2 配置环境变量

/etc/profile 文件的改变会涉及到系统的环境,也就是有关 Linux 环境变量的东西。所以需要将 JDK 配置到 /etc/profile,才可以在任何一个目录访问 JDK。
[root@localhost local]# vim /etc/profile
按 i 进入编辑,在 profile 文件尾部添加如下内容。
export JAVA_HOME=/usr/local/jdk1.8.0_181 #jdk安装目录 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib:$CLASSPATH export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin export PATH=$PATH:${JAVA_PATH}
使用 Esc —> :wq 保存并退出编辑,通过命令 source /etc/profile 让 profile 文件立即生效。
[root@localhost local]# source /etc/profile

1.3.2.3 检测是否安装成功

显示版本号就是安装成功了。
[root@localhost local]# java -version
image.png

1.4 开发工具

正所谓工欲善其事必先利其器,我们在开发 Java 语言过程中同样需要一款不错的开发工具,目前市场上的 IDE 很多,本文为大家推荐以下下几款 Java 开发工具:

  1. 进入 IDEA 官方下载页面,点击 Download 下载。

image.png

  1. IntelliJ IDEA 是一款跨平台的开发工具,支持 Windows、Mac、Linux 等操作系统,选择我们需要的版本进行下载(以 Windows 为例)。

image.png

  1. 点击下载后可能需要注册,一般情况下,不用理会,浏览器会自动进行下载,等待下载完成即可。
  2. 下载完成后,我们会得到一个 IntelliJ IDEA 安装包,双击打开下载的安装包,选择 Next,正式开始安装。

image.png

  1. 设置 IDEA 的安装目录,建议不要安装在系统盘(通常 C 盘是系统盘),这里选择安装到 D 盘。

image.png

  1. 自行选择需要的功能,若无特殊需求,按图中勾选即可。

image.png
TIPS:

  • Create Desktop Shortcut:创建桌面快捷方式图标,建议勾选 64-bit launcher;
  • Update context menu:是否将从文件夹打开项目添加至鼠标右键,根据需要勾选;
  • Create Associations:关联文件格式,可以不推荐勾选,使用如 Sublime Text、EditPlus 等轻量级文本编辑器打开;
  • Download and install 32-bit JetBrains Runtime:下载并安装 JetBrains 的 JRE。如果已经安装了JRE,则无需勾选此项;
  • Update PATH variable (restart needed):是否将 IDEA 启动目录添加到环境变量中,即可以从命令行中启动 IDEA,根据需要勾选。
  1. 选择开始菜单文件夹后,点击 Install 等待安装。

image.png

  1. 等待安装进度条达到 100% 后,点击 Finish,IntelliJ IDEA 就安装完成了。可以勾选 Run IntelliJ IDEA 选项,表示关闭此窗口后运行 IDEA。

image.png

1.4.2 第一个Hello World

IDEA 安装成功后,我们就可以开始编写第一个 Java 程序了。
点击 Create New Project,创建一个项目。
image.png
首次进入,会让我们添加安装的 JDK。选择指定目录下的 JDK 作为 Project SDK。
image.png
如果要创建 Web 工程,则需要勾选上面的 Web Application。如果不需要创建 Web 工程的话,则不需要勾选。这里先不勾选,我们只是创建简单的 Java 工程,点击 Next。
image.png
输入项目名称,点击 Finish。
image.png
创建好后,在 src 下右键选择 New -> Java Class,输入名称 Main。
image.png
然后开始编写我们的第一个 Java 程序。
public class Main { public static void main(String[] args) { System.out.println(“Hello World!”); } }
点击左侧运行按钮,可以在控制台看到打印结果 Hello World!。
image.png

第二章:基础语法、变量

2.1 Java 基础语法

一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。

  • 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
  • :类是一个模板,它描述一类对象的行为和状态。
  • 方法:方法就是行为,一个类可以有很多方法。逻辑运算、数据修改以及所有动作都是在方法中完成的。
  • 实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。

    1. //实例
    2. public class HelloWorld {
    3. /* 第一个Java程序
    4. * 它将输出字符串 Hello World
    5. */
    6. public static void main(String[] args) {
    7. // 输出 Hello World
    8. System.out.println("Hello World");
    9. }
    10. }

    下面将逐步介绍如何保存、编译以及运行这个程序:

  • 打开代码编辑器,把上面的代码添加进去;

  • 把文件名保存为:HelloWorld.java;
  • 打开 cmd 命令窗口,进入目标文件所在的位置,假设是 C:\;
  • 在命令行窗口输入 javac HelloWorld.java 按下回车键编译代码。如果代码没有错误,cmd 命令提示符会进入下一行(假设环境变量都设置好了)。
  • 再键输入 java HelloWorld 按下回车键就可以运行程序了。

image.png
你将会在窗口看到 Hello World。

  1. $ javac HelloWorld.java
  2. $ java HelloWorld
  3. Hello World
  1. public class Solution {
  2. public void myMethod(){
  3. System.out.println("Hello World");
  4. }
  5. }

2.1.1 基本语法

编写 Java 程序时,应注意以下几点:

  • 大小写敏感:Java 是大小写敏感的,这就意味着标识符 Hello 与 hello 是不同的。
  • 类名:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 MyFirstJavaClass。
  • 方法名:所有的方法名都应该以小写字母开头。如果方法名含有若干单词,则后面的每个单词首字母大写。
  • 源文件名:源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记 Java 是大小写敏感的),文件名的后缀为 .java。(如果文件名和类名不相同则会导致编译错误)。
  • 主方法入口:所有的 Java 程序由 public static void main(String[] args) 方法开始执行。

    2.1.2 Java 标识符

    Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。
    关于 Java 标识符,有以下几点需要注意:

  • 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始。

  • 首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合。
  • 关键字不能用作标识符。
  • 标识符是大小写敏感的。
  • 合法标识符举例:age、$salary、_value、__1_value。
  • 非法标识符举例:123abc、-salary。

    2.1.3 Java 修饰符

    像其他语言一样,Java 可以使用修饰符来修饰类中方法和属性。主要有两类修饰符:

  • 访问控制修饰符 : default, public , protected, private。

  • 非访问控制修饰符 : final, abstract, static, synchronized。

在后面的章节中我们会深入讨论 Java 修饰符。

2.1.4 Java 数组

数组是储存在堆上的对象,可以保存多个同类型变量。在后面的章节中,我们将会学到如何声明、构造以及初始化一个数组。

2.2 打印 “Hello Java”

  1. public class Solution {
  2. /* Your first java code
  3. * print Hello Java to console
  4. */
  5. public static void main(String[] args) {
  6. // write your code here
  7. System.out.print("Hello Java");
  8. }
  9. }

2.3 打印 Welcome to LintCode!

  1. public class Solution {
  2. public static void main(String[] args) {
  3. // write your code here
  4. System.out.print("Welcome to LintCode!");
  5. }
  6. }

2.4 Java 关键字

下面列出了 Java 关键字。这些保留字不能用于常量、变量、和任何标识符的名称。

关键字 说明
private 私有的
protected 受保护的
public 公共的
default 默认
abstract 声明抽象
class
extends 扩充,继承
final 最终值,不可改变的
implements 实现(接口)
interface 接口
native 本地,原生方法(非 Java 实现)
new 新,创建
static 静态
strictfp 严格,精准
synchronized 线程,同步
transient 短暂
volatile 易失
break 跳出循环
case 定义一个值以供 switch 选择
continue 继续
default 默认
do 运行
else 否则
for 循环
if 如果
instanceof 实例
return 返回
switch 根据值选择执行
while 循环
assert 断言表达式是否为真
catch 捕捉异常
finally 有没有异常都执行
throw 抛出一个异常对象
throws 声明一个异常可能被抛出
try 捕获异常
import 引入
package
boolean 布尔型
byte 字节型
char 字符型
double 双精度浮点
float 单精度浮点
int 整型
long 长整型
short 短整型
super 父类,超类
this 本类
void 无返回值

以上共 48 个关键字,还有两个关键字,但是他们不能使用,goto 和 const。

第三章:数据类型

变量就是申请内存来存储值。也就是说,当创建变量的时候,需要在内存中申请空间。
内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据。
image.png
因此,通过定义不同类型的变量,可以在内存中储存整数、小数或者字符。
Java 的两大数据类型:

  • 基本数据类型
  • 引用数据类型

    3.1 基本数据类型

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

  • byte 数据类型是 8 位、有符号的,以二进制补码表示的整数;

  • 最小值是 -128(-2^7)
  • 最大值是 127(2^7-1)
  • byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;
  • 默认值是 0

// 例子: byte a = 100; byte b = -50;
short:

  • short 数据类型是 16 位、有符号的以二进制补码表示的整数
  • 最小值是 -32768(-2^15)
  • 最大值是 32767(2^15 - 1)
  • short 数据类型也可以像 byte 那样节省空间。一个 short 变量是 int 型变量所占空间的二分之一;
  • 默认值是 0

// 例子: short s = 100; short r = -20000;
int:

  • int 数据类型是 32 位、有符号的以二进制补码表示的整数;
  • 最小值是 -2,147,483,648(-2^31)
  • 最大值是 2,147,483,647(2^31 - 1)
  • 一般地整型变量默认为 int 类型;
  • 默认值是 0

// 例子: int a = 100000; int b = -200000;
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 混淆,不容易分辩。所以最好大写。

// 例子: long a = 100000L; Long b = -200000L;
float:

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

//例子: float f1 = 234.5f;
double:

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

// 例子: // 7 是一个 int 字面量,而 7D,7. 和 8.0 是 double 字面量。 double d1 = 7D ; double d2 = 7.; double d3 = 8.0; double d4 = 8.D; double d5 = 12.9867;
boolean:

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

// 例子: boolean a1 = true; boolean a2 = false;
char:

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

// 例子: char letter = ‘A’;

3.1.1 数据转换

整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。
// 转换从低级到高级。 // 低 ——————————————————> 高 byte/short/char —> int —> long —> float —> double
数据类型转换必须满足如下规则:

  • 不能对 boolean 类型进行类型转换。
  • 不能把对象类型转换成不相关类的对象。
  • 在把容量大的类型转换为容量小的类型时必须使用强制类型转换。
  • 转换过程中可能导致溢出或损失精度,例如:

int i =128; // 因为 byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出。 byte b = (byte) i; System.out.println(b); // 127

  • 浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入,例如:

int a = (int) 23.7; int b = (int) -45.89f; System.out.println(a); // 23 System.out.println(b); // -45

3.1.1.1 自动类型转换

必须满足转换前的数据类型的位数要低于转换后的数据类型,例如: short 数据类型的位数为 16 位,就可以自动转换位数为 32 的 int 类型,同样 float 数据类型的位数为 32,可以自动转换为 64 位的 double 类型。
public class Main{ public static void main(String[] args){ // 定义一个 char 类型 char c1=’a’; // char 自动类型转换为 int int i1 = c1; // char 自动类型转换为 int 后的值等于 97 System.out.println(“char 自动类型转换为 int 后的值等于” + i1); // 定义一个 char 类型 char c2 = ‘A’; // char 类型和 int 类型计算 int i2 = c2 + 1; // char 类型和 int 计算后的值等于 66 System.out.println(“char 类型和 int 计算后的值等于” + i2); } }

3.1.1.2 强制类型转换

  • 条件是转换的数据类型必须是兼容的。
  • 格式:(type)value type 是要强制类型转换后的数据类型 实例:

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

3.1.1.3 隐含强制类型转换

  • 整数的默认类型是 int。
  • 小数默认是 double 类型浮点型,在定义 float 类型时必须在数字后面跟上 F 或者 f。

    3.2 字符的ASCII码(Java 版)

    ```java import java.util.Scanner;

public class Main { public static void main(String[] args) { // write your code here Scanner sc = new Scanner(System.in); char character = sc.next().charAt(0); System.out.println((int)character); } }

  1. <a name="dFkxR"></a>
  2. ## 3.3 **ASCII码对应的字符(Java 版)**
  3. ```java
  4. import java.util.*;
  5. public class Main {
  6. public static void main(String[] args){
  7. // write your code here
  8. Scanner sc = new Scanner(System.in);
  9. char n = (char)sc.nextInt();
  10. if (n>-1 && n<128) {
  11. System.out.println(n);
  12. return;
  13. }
  14. System.out.println("error");
  15. }
  16. }

3.4 引用类型

  • 在 Java 中,引用类型的变量非常类似于 C/C++ 的指针。引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定为一个特定的类型,比如 Employee、Puppy 等。变量一旦声明后,类型就不能被改变了。
  • 对象、数组都是引用数据类型。
  • 所有引用类型的默认值都是 null。
  • 一个引用变量可以用来引用任何与之兼容的类型。

    3.4.1 拆箱和装箱

    Java 为每种基本数据类型都提供了对应的包装器类型。
基本数据类型 包装类型
int Integer
byte Byte
short Short
long Long
float Float
double Double
char Character
boolean Boolean

3.4.1.1 什么是装箱

简单来说,装箱就是自动将基本数据类型转换为包装器类型。

  1. // 例:
  2. //自动装箱:
  3. Integer a = 1;
  4. Boolean b = true;
  5. Byte c = 1;
  6. Character d = 'a';
  7. Short e = 1;
  8. Long f = 1L;
  9. Float q = 1.0f;
  10. Double w = 1.2;

3.4.1.2 什么是拆箱

拆箱就是自动将包装器类型转换为基本数据类型。

  1. // 例:
  2. Integer a = 1;
  3. Boolean b = true;
  4. //自动拆箱
  5. int a1 = a;
  6. boolean b1 = b;
  1. public class Solution {
  2. public void myMethod(){
  3. Integer a = 1;
  4. Boolean b = true;
  5. //自动拆箱
  6. int a1 = a;
  7. boolean b1 = b;
  8. System.out.println(a1);
  9. System.out.println(b1);
  10. }
  11. }

3.5 Integer 的取值范围

  1. public class Solution {
  2. public boolean equivalence(Integer a, Integer b) {
  3. // write your code here
  4. return a.equals(b);
  5. }
  6. }

3.6 浮点数与字符串的相互转换

  1. public class Solution {
  2. public String add(String a, String b) {
  3. // write your code here
  4. double result = Double.parseDouble(a) + Double.parseDouble(b);
  5. return String.format("%.2f", result);
  6. }
  7. }

第四章:数组

4.1 Java 数组

数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。
Java 语言中提供的数组是用来存储固定大小的同类型元素。
你可以声明一个数组变量,如 numbers[100] 来代替直接声明 100 个独立变量 number0,number1,….,number99。

4.1.1 声明数组变量

声明数组的方式有两种,只有声明完数组后,才能开始使用。
// 方式一: int[] arr; // 方式二: int arr[];

4.1.2 一维数组

4.1.2.1 创建数组

使用 new 关键字来创建数组,在创建数组时,需要声明数组的 size 容量。
// 例: int arr[] = new int[10]; Object[] objects = new Object[10]; boolean bool[] = new boolean[10];
数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 arr.length - 1。
除了上一种创建方式外,另一种方式是在创建时为其赋值。
// 例: int arr[] = {1,2,3};
我们通常使用 arr.length 来获取数组的长度。
// 例: int arr[] = {1,2,3,4}; int len = arr.length; // len的值为4

4.1.2.2 处理数组

数组的元素类型和数组的大小都是确定的,所以当处理数组元素时候,我们通常使用基本循环或者 For-Each 循环。在后续的章节会对循环进行详细的讲解。
使用 arr[i] 的方式获取数组中下标为 i 中的元素。
// 例: int arr[] = {1,2,3,4,5}; for(int i = 0; i < arr.length; i++){ // 在控制台打印 arr 数组中的数据 System.out.println(arr[i]); }

4.1.3 二维数组

二维数组在可以简单的理解为矩阵,每个元素占据一个位置。它就是一个特殊的一维数组,其每一个元素都是一个一维数组。

4.1.3.1 创建数组

二维数组的创建方式与一维数组基本相同。
// 例: // 方式一:我们可以只指定行数,而不用指定列数 int[][] arr = new int[10][]; // 方式二:可以同时指定行数和列数 int[][] arrs = new int[10][10]; //但是不能只指定列数,不指定行数,下面的例子编译是不通过的。 int[][] err = new int[][10];
那么该如何获取数组的长度呢?我们需要先获取指定的再获取指定上的元素。
// 例: int arr[][] = new int[10][11]; int x = arr.length; // x 的值为 10 int y = arr[0].length; // y 的值为 11 // 当使用如下方式创建数组时,不能获取列的长度,否则会报错 int[][] arr = new int[10][]; int x = arr.length; // x 的值为 10 int y = arr[0].length; // 报错:java.lang.NullPointerException

4.1.3.2 处理数组

对于二维数组的遍历,也是采用基本循环或 For-Each 循环的方式。
// 例: int arr[][] = {{1, 2, 3}, {4, 5, 6}}; for(int i = 0; i < arr.length; i++){ for(int j = 0; j < arr[i].length; j++){ // 在控制台打印 arr 数组中的数据 System.out.println(arr[i][j]); } }

4.1.4 Arrays工具类

java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。
下面列举一些常用的方法:

  • 给数组赋值:通过 fill() 方法。
  • 对数组排序:通过 sort() 方法,按升序。
  • 比较数组:通过 equals() 方法比较数组中元素值是否相等。
  • 数组转换:通过 asList() 将数组转换为 List (你可以在以后的章节里来学习 List)。

    4.1.5 实例

    请看下面的实例代码,我们声明了三个数组 arr1、arr2 和 arr3,长度都是 3 ,通过 fill() 方法为他们赋值,最后比较他们是否相等: ```java import java.util.Arrays;

public class Solution { public void myMethod() { // 声明三个数组 int arr1[] = new int[3]; int arr2[] = new int[3]; int arr3[] = new int[3];

  1. // 为数组赋值
  2. Arrays.fill(arr1,1);
  3. Arrays.fill(arr2,1);
  4. Arrays.fill(arr3,2);
  5. // 判断 arr1 和 arr2 是否相等、arr1 和 arr3 是否相等
  6. System.out.println("数组arr1和数组arr2是否全等:" + Arrays.equals(arr1,arr2));
  7. System.out.println("数组arr1和数组arr3是否全等:" + Arrays.equals(arr1,arr3));
  8. // 输出 arr3 的内容
  9. System.out.print("数组arr3:");
  10. for (int i = 0; i < 3; i++) {
  11. System.out.print(arr3[i] + " ");
  12. }
  13. }

}

  1. <a name="kxDez"></a>
  2. ## 4.2 **判断两个数组是否相等**
  3. ```java
  4. import java.util.*;
  5. public class Solution {
  6. public boolean equalityOfArrays(int[] arr1, int arr2[]) {
  7. // -- write your code here --
  8. Arrays.sort(arr1);
  9. Arrays.sort(arr2);
  10. return Arrays.equals(arr1,arr2);
  11. }
  12. }

4.3 求数组反对角线的和

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args){
  4. // write your code here
  5. Scanner scanner = new Scanner(System.in);
  6. int n = scanner.nextInt();
  7. float sum = 0;
  8. float[][] arr = new float[n][n];
  9. for (int i = 0; i < n; i++) {
  10. for (int j = 0; j < n; j++) {
  11. arr[i][j] = scanner.nextFloat();
  12. }
  13. sum += arr[i][n - 1 - i];
  14. }
  15. System.out.printf("%.2f",sum);
  16. }
  17. }

第五章:运算符

image.png

5.1 运算符(一)

计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java 也提供了一套丰富的运算符来操纵变量。我们可以把运算符分成以下几组:

  • 赋值运算符
  • 算术运算符
  • 关系运算符
  • 短路运算符
  • 条件运算符
  • 位运算符
  • 其他运算符

    5.1.1 赋值运算符

    下面是 Java 语言支持的赋值运算符:
操作符 描述 例子
= 简单的赋值运算符,将右操作数的值赋给左侧操作数 C = A + B将把A + B得到的值赋给C
+ = 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 C += A等价于C = C + A
- = 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 C -= A等价于C = C - A
* = 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 C = A等价于C = C A
/ = 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 C /= A,C 与 A 同类型时等价于 C = C / A
%= 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 C %= A等价于C = C%A
<< = 左移位赋值运算符 C <<= 2等价于C = C << 2
>> = 右移位赋值运算符 C >>= 2等价于C = C >> 2
&= 按位与赋值运算符 C &= 2等价于C = C&2
^ = 按位异或赋值操作符 C ^= 2等价于C = C ^ 2
| = 按位或赋值操作符 C |= 2等价于C = C | 2

示例:

  1. int a = 10;
  2. int b = 20;
  3. int c = 0;
  4. c = a + b;
  5. System.out.println("c = a + b = " + c ); // c = a + b = 30
  6. c += a ;
  7. System.out.println("c += a = " + c ); // c += a = 40
  8. c -= a ;
  9. System.out.println("c -= a = " + c ); // c -= a = 30
  10. c *= a ;
  11. System.out.println("c *= a = " + c ); // c *= a = 300
  12. a = 10;
  13. c = 15;
  14. c /= a ;
  15. System.out.println("c /= a = " + c ); // c /= a = 1
  16. a = 10;
  17. c = 15;
  18. c %= a ;
  19. System.out.println("c %= a = " + c ); // c %= a = 5
  20. c <<= 2 ;
  21. System.out.println("c <<= 2 = " + c ); // c <<= 2 = 20
  22. c >>= 2 ;
  23. System.out.println("c >>= 2 = " + c ); // c >>= 2 = 5
  24. c >>= 2 ;
  25. System.out.println("c >>= 2 = " + c ); // c >>= 2 = 1
  26. c &= a ;
  27. System.out.println("c &= a = " + c ); // c &= a = 0
  28. c ^= a ;
  29. System.out.println("c ^= a = " + c ); // c ^= a = 10
  30. c |= a ;
  31. System.out.println("c |= a = " + c ); // c |= a = 10

扩展:a = a + b 与 a += b 的区别。
+= 隐式的将加操作的结果类型强制转换为持有结果的类型。如果两这个整型相加,如 byte、short 或者 int,首先会将它们提升到 int 类型,然后在执行加法操作。

  1. byte a = 127;
  2. byte b = 127;
  3. b = a + b; // error : cannot convert from int to byte
  4. b += a; // ok

5.1.2 算术运算符

算术运算符用在数学表达式中,它们的作用和在数学中的作用一样。下表列出了所有的算术运算符。
表格中的实例假设整数变量 A 的值为 10,变量 B 的值为 20 :

操作符 描述 例子
+ 加法 - 相加运算符两侧的值 A + B 等于 30
- 减法 - 左操作数减去右操作数 A – B 等于 -10
* 乘法 - 相乘操作符两侧的值 A * B 等于200
/ 除法 - 左操作数除以右操作数 B / A 等于2
取余 - 左操作数除以右操作数的余数 B % A 等于0
++ 自增: 操作数的值增加1 B++ 或 ++B 等于 21(区别详见下文)
自减: 操作数的值减少1 B— 或 —B 等于 19(区别详见下文)

例:下面的简单示例程序演示了算术运算符。

  1. int a = 10;
  2. int b = 20;
  3. int c = 25;
  4. int d = 25;
  5. System.out.println("a + b = " + (a + b) ); // a + b = 30
  6. System.out.println("a - b = " + (a - b) ); // a - b = -10
  7. System.out.println("a * b = " + (a * b) ); // a * b = 200
  8. System.out.println("b / a = " + (b / a) ); // b / a = 2
  9. System.out.println("b % a = " + (b % a) ); // b % a = 0
  10. System.out.println("c % a = " + (c % a) ); // c % a = 5
  11. System.out.println("a++ = " + (a++) ); // a++ = 10
  12. System.out.println("a-- = " + (a--) ); // a-- = 11

5.1.3 自增自减运算符

自增(++)自减(—)运算符是一种特殊的算术运算符,在算术运算符中需要两个操作数来进行运算,而自增自减运算符是一个操作数。

  1. int a = 3; //定义一个变量;
  2. int b = ++a; //自增运算
  3. int c = 3;
  4. int d = --c; //自减运算
  5. System.out.println("进行自增运算后的值等于"+b); // 进行自增运算后的值等于4
  6. System.out.println("进行自减运算后的值等于"+d); // 进行自减运算后的值等于2

解析:
int b = ++a; 拆分运算过程为: a=a+1=4; b=a=4, 最后结果为b=4,a=4
int d = —c; 拆分运算过程为: c=c-1=2; d=c=2, 最后结果为d=2,c=2

5.2 简单的加减乘除运算

  1. public class Solution {
  2. public int addition(int a, int b) {
  3. // write your code here
  4. return a + b;
  5. }
  6. public int subtraction(int a, int b) {
  7. // write your code here
  8. return a - b;
  9. }
  10. public int multiplication(int a, int b) {
  11. // write your code here
  12. return a * b;
  13. }
  14. public float division(int a, int b) {
  15. // write your code here
  16. return (float) a / b;
  17. }
  18. }

5.3 数字2的朋友

  1. public class Solution {
  2. public static boolean isFriend(int n) {
  3. // write your code here
  4. return Integer.bitCount(n) == 2;
  5. }
  6. }

5.4 运算符(二)

5.4.1 关系运算符

下表为 Java 支持的关系运算符:

运算符 描述 例子
== 检查如果两个操作数的值是否相等,如果相等则条件为真。 (A == B)为假
!= 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 (A != B)为真
> 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 (A > B)为假
< 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 (A < B)为真
>= 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 (A >= B)为假
<= 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 (A <= B)为真

下面的简单示例程序演示了关系运算符。

  1. int a = 10;
  2. int b = 20;
  3. System.out.println("a == b = " + (a == b) ); // a == b = false
  4. System.out.println("a != b = " + (a != b) ); // a != b = true
  5. System.out.println("a > b = " + (a > b) ); // a > b = false
  6. System.out.println("a < b = " + (a < b) ); // a < b = true
  7. System.out.println("b >= a = " + (b >= a) ); // b >= a = true
  8. System.out.println("b <= a = " + (b <= a) ); // b <= a = false

5.4.2 短路运算符

下表列出了逻辑运算符的基本运算:

操作符 描述 例子
&& 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 (A && B) 为假
| | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 (A | | B) 为真
称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为 true,则逻辑非运算符将得到false。 !(A && B) 为真

下面的简单示例程序演示了逻辑运算符。

  1. boolean a = true;
  2. boolean b = false;
  3. System.out.println("a && b = " + (a && b)); // a && b = false
  4. System.out.println("a || b = " + (a || b) ); // a || b = true
  5. System.out.println("!(a && b) = " + !(a && b)); // !(a && b) = true
  • 当使用与逻辑运算符时,在两个操作数都为 true 时,结果才为 true,但是当得到第一个操作为 false 时,其结果就必定是 false,这时候就不会再判断第二个操作了。

    1. int a = 5; //定义一个变量;
    2. boolean b = (a<4) && (a++<10);
    3. System.out.println("使用短路逻辑运算符的结果为"+b); //使用短路逻辑运算符的结果为false
    4. System.out.println("a的结果为"+a); //a的结果为5

    解析:该程序使用到了短路逻辑运算符 (&&),首先判断 a<4 的结果为 false,则 b 的结果必定是 false,所以不再执行第二个操作 a++<10 的判断,所以 a 的值为 5。

  • 当使用或操作运算符时,两个操作数中,有一个结果为 true,结果就为 true。当第一个操作数为 true,就不会运行后一个运算符,当第一个操作数为 false 时,才会去执行后一个操作数的内容。 ```java // 例一 int a = 3; // 定义一个变量; int b = 3; // 定义一个变量; boolean x = (++a) > 10 || (++b) > 2 ; System.out.println(“使用或运算符后 a 的结果为:” + a); // 使用或运算符后 a 的结果为:4 System.out.println(“使用或运算符后 b 的结果为:” + b); // 使用或运算符后 b 的结果为:4

// 例二 int a1 = 3; // 定义一个变量; int b1 = 3; // 定义一个变量; boolean x1 = (++a1) > 2 || (++b1) > 2 ; System.out.println(“使用或运算符后 a1 的结果为:” + a1); // 使用或运算符后 a1 的结果为:4 System.out.println(“使用或运算符后 b1 的结果为:” + b1); // 使用或运算符后 b1 的结果为:3

  1. <a name="XXdc4"></a>
  2. ## 5.5 小数字的和
  3. ```java
  4. import java.util.*;
  5. public class Main {
  6. public static void main(String[] args) {
  7. // write your code here
  8. Scanner sc = new Scanner(System.in);
  9. int n = sc.nextInt();
  10. int[] num = new int[n];
  11. int max = num[0];
  12. int sum = 0;
  13. for (int i = 0; i < num.length; i++) {
  14. num[i] = sc.nextInt();
  15. max = Math.max(max, num[i]);
  16. }
  17. for (int i : num) {
  18. if (i < max) {
  19. sum += i;
  20. }
  21. }
  22. System.out.println(sum);
  23. }
  24. }

5.6 这是什么三角形?

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. // write your code here
  5. //创建键盘录入对象
  6. Scanner sc = new Scanner(System.in);
  7. //输入
  8. int a = sc.nextInt();
  9. int b = sc.nextInt();
  10. int c = 180 - (a + b);
  11. if ((a + b) != 180 && (a > 0) && (b > 0)) {
  12. if ((a == 90) || (b == 90) || (c == 90)) {
  13. System.out.println("直角三角形");
  14. } else if ((a > 90) || (b > 90) || (c > 90)) {
  15. System.out.println("钝角三角形");
  16. } else if ((a < 90) && (b < 90) && (c < 90)) {
  17. System.out.println("锐角三角形");
  18. }
  19. } else {
  20. System.out.println("无法组成三角形");
  21. }
  22. }
  23. }

5.7 运算符(三)

5.7.1 条件运算符

条件运算符也被称为三元运算符。该运算符有 3 个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。
variable x = (expression) ? value if true : value if false

  1. int a , b;
  2. a = 10;
  3. // 如果 a 等于 1 成立,则设置 b 为 20,否则为 30
  4. b = (a == 1) ? 20 : 30;
  5. System.out.println( "Value of b is : " + b ); // Value of b is : 30
  6. // 如果 a 等于 10 成立,则设置 b 为 20,否则为 30
  7. b = (a == 10) ? 20 : 30;
  8. System.out.println( "Value of b is : " + b ); // Value of b is : 20

5.7.2 位运算符

Java 定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型。
位运算符作用在所有的位上,并且按位运算。假设 a = 60,b = 13;它们的二进制格式表示将如下:
A = 0011 1100
B = 0000 1101
A & B = 0000 1100
A | B = 0011 1101
A ^ B = 0011 0001
~A = 1100 0011
下表列出了位运算符的基本运算,假设整数变量 A 的值为 60 和变量 B 的值为 13:

操作符 描述 例子
如果相对应位都是1,则结果为1,否则为0 (A&B),得到12,即0000 1100
| 如果相对应位都是 0,则结果为 0,否则为 1 (A | B)得到61,即 0011 1101
^ 如果相对应位值相同,则结果为0,否则为1 (A ^ B)得到49,即 0011 0001
按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 (〜A)得到-61,即1100 0011
<< 按位左移运算符。左操作数按位左移右操作数指定的位数。 A << 2得到240,即 1111 0000
>> 按位右移运算符。左操作数按位右移右操作数指定的位数。 A >> 2得到15即 1111
>>> 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。
  1. int a = 60; // 60 = 0011 1100
  2. int b = 13; // 13 = 0000 1101
  3. int c = 0;
  4. c = a & b; // 12 = 0000 1100
  5. System.out.println("a & b = " + c ); // a & b = 12
  6. c = a | b; // 61 = 0011 1101
  7. System.out.println("a | b = " + c ); // a | b = 61
  8. c = a ^ b; // 49 = 0011 0001
  9. System.out.println("a ^ b = " + c ); // a ^ b = 49
  10. c = ~a; // -61 = 1100 0011
  11. System.out.println("~a = " + c ); // ~a = -61
  12. c = a << 2; // 240 = 1111 0000
  13. System.out.println("a << 2 = " + c ); // a << 2 = 240
  14. c = a >> 2; // 15 = 1111
  15. System.out.println("a >> 2 = " + c ); // a >> 2 = 15
  16. c = a >>> 2; // 15 = 0000 1111
  17. System.out.println("a >>> 2 = " + c ); // a >>> 2 = 15

5.7.3 instanceof 运算符

该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。
instanceof 运算符使用格式如下:
( Object reference variable ) instanceof (class/interface type)
如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真。
下面是一个例子:

  1. String name = "James";
  2. boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真

如果被比较的对象兼容于右侧类型,该运算符仍然返回 true。

5.7.4 Java 运算符优先级

当多个运算符出现在一个表达式中,谁先谁后呢?这就涉及到运算符的优先级别的问题。在一个多运算符的表达式中,运算符优先级不同会导致最后得出的结果差别甚大。
例如,(1+3) + (3+2) 2,这个表达式如果按加号最优先计算,答案就是 18,如果按照乘号最优先,答案则是 14。
再如,x = 7 + 3
2 ;这里 x 得到 13,而不是 20,因为乘法运算符比加法运算符有较高的优先级,所以先计算 3 * 2 得到 6,然后再加 7。
下表中具有最高优先级的运算符在的表的最上面,最低优先级的在表的底部。

类别 操作符 关联性
后缀 () [] . (点操作符) 左到右
一元 expr++ expr— 从左到右
一元 ++expr —expr + - ~ ! 从右到左
乘性 * / % 左到右
加性 + - 左到右
移位 >> >>> << 左到右
关系 > >= < <= 左到右
相等 == != 左到右
按位与 左到右
按位异或 ^ 左到右
按位或 | 左到右
逻辑与 && 左到右
逻辑或 | | 左到右
条件 ?: 从右到左
赋值 = += -= *= /= %= >>= <<= &= ^= |= 从右到左
逗号 左到右

5.8 唯一存在的数字

  1. public class Solution {
  2. /**
  3. * @param nums: Represents the incoming number
  4. * @return: A int value representing whether the
  5. * return is a palindrome or not
  6. */
  7. public int uniqueNumber(int nums[]) {
  8. // write your code here
  9. int ans = 0;
  10. for (int i = 0; i < nums.length; i++) {
  11. ans ^= nums[i];
  12. }
  13. return ans;
  14. }
  15. }

5.9 加密的情书

  1. import java.math.BigInteger;
  2. import java.util.Scanner;
  3. public class Main {
  4. public static void main(String[] args) {
  5. // write your code here
  6. Scanner scanner = new Scanner(System.in);
  7. String input = scanner.next();
  8. System.out.print((new BigInteger(input)).xor(new BigInteger("19990606")));
  9. }
  10. }

第六章:注释

Java 支持三种注释方式。前两种分别是 // 和 / /,第三种被称作说明注释,它以 /* 开始,以 / 结束。
说明注释允许你在程序中嵌入关于程序的信息。你可以使用 javadoc 工具软件来生成信息,并输出到 HTML 文件中。
说明注释,使你更加方便的记录你的程序信息。
Java 支持以下三种注释方式:

  1. 单行注释:以双斜杠 // 标识,只能注释一行内容,用在注释信息内容少的地方。

    1. public class Main{
    2. public static void main(String[] args) {
    3. //这是单行注释
    4. System.out.println("注释方式");
    5. }
    6. }
  2. 多行注释:包含在 /* 和 / 之间,能注释很多行的内容。为了可读性比较好,一般首行和尾行不写注释信息(这样也比较美观好看)。

注意:多行注释可以嵌套单行注释,但是不能嵌套多行注释和文档注释。

  1. public class Main{
  2. public static void main(String[] args) {
  3. /*
  4. * 这是多行注释
  5. * 可以注释多行内容
  6. */
  7. System.out.println("注释方式");
  8. }
  9. }
  1. 文档注释:包含在 /* 和 / 之间,也能注释多行内容,一般用在类、方法和变量上面,用来描述其作用。注释后,鼠标放在类和变量上面会自动显示出我们注释的内容。

注意:文档注释能嵌套单行注释,不能嵌套多行注释和文档注释,一般首行和尾行也不写注释信息。

  1. public class Main{
  2. /**
  3. * 这是文档注释
  4. * 可以注释多行内容
  5. * @param args
  6. */
  7. public static void main(String[] args) {
  8. System.out.println("注释方式");
  9. }
  10. }

javadoc 标签
javadoc 工具软件识别以下标签:

标签 描述 示例
@author 标识一个类的作者 @author description
@deprecated 指名一个过期的类或成员 @deprecated description
{@docRoot} 指明当前文档根目录的路径 Directory Path
@exception 标志一个类抛出的异常 @exception exception-name explanation
{@inheritDoc} 从直接父类继承的注释 Inherits a comment from the immediate surperclass.
{@link} 插入一个到另一个主题的链接 {@link name text}
{@linkplain} 插入一个到另一个主题的链接,但是该链接显示纯文本字体 Inserts an in-line link to another topic.
@param 说明一个方法的参数 @param parameter-name explanation
@return 说明返回值类型 @return explanation
@see 指定一个到另一个主题的链接 @see anchor
@serial 说明一个序列化属性 @serial description
@serialData 说明通过writeObject( ) 和 writeExternal( )方法写的数据 @serialData description
@serialField 说明一个ObjectStreamField组件 @serialField name type description
@since 标记当引入一个特定的变化时 @since release
@throws 和 @exception标签一样. The @throws tag has the same meaning as the @exception tag.
{@value} 显示常量的值,该常量必须是static属性。 Displays the value of a constant, which must be a static field.
@version 指定类的版本 @version info

对两种标签格式的说明:

  • @tag 格式的标签(不被{ }包围的标签)为块标签,只能在主要描述(类注释中对该类的详细说明为主要描述)后面的标签部分(如果块标签放在主要描述的前面,则生成 API 帮助文档时会检测不到主要描述)。
  • { @tag } 格式的标签(由{ }包围的标签)为内联标签,可以放在主要描述中的任何位置或块标签的注释中。

Javadoc 标签注意事项:

  • Javadoc 标签必须从一行的开头开始,否则将被视为普通文本。
  • 一般具有相同名称的标签放在一起。
  • Javadoc 标签区分大小写,代码中对于大小写错误的标签不会发生编译错误,但是在生成 API 帮助文档时会检测不到该注释内容。