第三章 Java的基本程序设计结构

▲一个简单的Java程序

▲注释

▲数据类型

▲变量与常量

▲运算符

▲字符串

▲输入与输出

▲控制流程

▲大数

▲数组

3.1 一个简单的Java程序

Java标准命名约定

  • 以大写字母开头的名词(尽量少出现拼音);
  • 如果有多个单词组成,每个单词的首字母大写(大驼峰)【FirstName】;
  • 如果有多个单词组成,第一个单词全小写,从第二个单词开始,每个单词的首字母大写(小驼峰)【firstName】

​ 根据Java语言规范,main方法必须声明为public(Java语言规范是描述Java语言的官方文档。可以从网站http://docs.oracle.com/javase/specs阅读或下载)。
​ 不过,即使main方法没有声明为public,有些版本的Java解释器也会执行Java程序。有个程序员报告了这个bug。如果感兴趣,可以访问https://bugs.openjdk.java.net/browse/JDK-4252539查看这个bug。1999年,这个bug被标记为“关闭,不予修复”(Closed, Will not be fixed)。Sun公司的一个工程师解释说:Java虚拟机规范并没有强制要求main方法一定是public,并且“修复这个bug有可能带来其他的隐患”。好在,这个问题最终得到了解决。在Java 1.4及以后的版本中,Java解释器强制要求main方法必须是public。
​ 当然,让质量保证工程师对bug报告做出决定不仅让人生疑,也让他们自己很头疼,因为他们的工作量很大,而且他们对Java的所有细节也未必了解得很清楚。不过,Sun公司在Java开源很久以前就把bug报告及其解决方案放在网站上让所有人监督检查,这是一个非常了不起的举措。

3.2 注释

单行注释

最常用的方式是使用//,其注释内容从//开始到本行结尾

public class FirstSample {public static void main(String[] args) {// 单行注释System.out.println("Hello World!");}
}

多行注释

public class FirstSample {public static void main(String[] args) {/*多行注释*/System.out.println("Hello World!");}
}

文本注释

这种注释可以自动生成类似API样式的文档

/*** @author: yuan_hao* @description: 案例1* @date: 2023/1/4 22:40* @version: 1.0*/
public class FirstSample {public static void main(String[] args) {System.out.println("Hello World!");}
}

阿里巴巴规范

3.3 数据类型

Java是一种强类型语言,每个变量必须声明一个数据类型。

数据类型分为:基本数据类型和引用数据类型

基本数据类型:4种整型(int、short、long、byte)、2种浮点类型(float、double)、1种字符类型(char)、1种表示真值的类型(boolen)

注意:字符串(String)不是基本数据类型,是引用数据类型

3.3.1 整型

类型 存储需求 取值范围
int 4字节 -2147483648 ~ 2147483647(略高于20亿)
short 2字节 -32768 ~ 32767
long 8字节 -9223372036854775808 ~ 9223372036854775807
byte 1字节 -128 ~ 127

int 类型最常用。但如果想要表示整个地球的居住人口,就需要使用 long类型了。

byte 和 short 类型主要用于特定的应用场合,例如,底层的文件处理或者存储空间有限时的大数组。

在Java 中,整型的范围与运行 Java代码的机器无关。这就解决了软件从一个平台移植到另一个平台,或者在同一个平台中的不同操作系统之间进行移植给程序员带来的诸多问题。

注意,Java没有任何无符号(unsigned)形式的int、long、short或 byte类型。

  • 长整型数值有一个后缀L或l(如4000000000L)。
  • 十六进制数值有一个前缀0x或0X(如0XCAFE)。
  • 八进制有一个前缀0(例如,010对应十进制中的8)。显然,八进制表示法比较容易混淆,所以很少有程序员使用八进制常数。
  • 加上前缀0b或0B还可以写二进制数。例如,0b1001就是9。
  • 另外,可以为数字字面量加下画线,如用1_000_000(或0b1111_0100_0010_0100_0000)表示100万。这些下画线只是为了让人更易读。Java编译器会去除这些下画线。

​ 如果要使用不可能为负的整数值而且确实需要额外的一位(bit),也可以把有符号整数值解释为无符号数,但是要非常仔细。例如,一个byte值b可以不表示范围-128到127,如果你想表示0到255的范围,也可以存储在一个byte中。基于二进制算术运算的性质,只要不溢出,加法、减法和乘法都能正常计算。但对于其他运算,需要调用Byte.toUnsignedInt(b)来得到一个0到255的int值,然后处理这个整数值,再把它转换回byte。Integer和Long类都提供了处理无符号除法和求余数的方法。

3.3.2 浮点型

类型 存储需求 取值范围
float 4字节 大约±3.40282347E+38F(有效位数为6~7位)
double 8字节 大约±1.79769313486231570E+308(有效位数为15位)

float 类型的数值有一个后缀F或f(例如,3.14F)。

没有后缀F的浮点数值(如3.14)总是默认为 double 类型。

也可以在浮点数值后面添加后缀D或d(例如,3.14D)。

可以使用十六进制表示浮点数值。例如,0.125=2-3可以表示成0x1.0p-3。在十六进制表示法中,使用p表示指数,而不是e。(e是一个十六进制数位。)注意,尾数采用十六进制,指数采用十进制。指数的基数是 2,而不是 10。

所有的浮点数值计算都遵循IEEE 754规范。

  • 正无穷大
  • 负无大
  • NaN (不是一个数字)

例如,一个正整数除以0的结果为正无穷大。计算0/0 或者负数的平方根结果为 NaN。

常量Double.POSITIVE_INFINITY、Double.NEGATIVE_INFINITY和Double.NaN(以及相应的Float 类型的常量)分别表示这三个特殊的值,但在实际应用中很少遇到。

特别要说明的是,不能如下检测一个特定值是否等于Double.NaN:
if(x== Double.NaN)
所有“非数值(NaN)”的值都认为是不相同的。不过,可以如下使用Double.isNaN方法来判断:
if (Double.isNaN(x))

浮点数值不适用于无法接受舍入误差的金融计算。例如,命令 System.out.println(2.0-1.1)将打印出0.8999999999999999而不是人们期望的0.9。

这种舍入误差的主要原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确地表示分数1/10。这就好像十进制无法精确地表示分数 1/3 一样。如果在数值计算中不允许有任何舍入误差,就应该使用 BigDecimal类。

3.3.3 字符型

char类型的字面量值要用单引号括起来。例如:A’ 是编码值为65 的字符常量。它与"A"不同,"A"是包含一个字符A的字符串。

char 类型的值可以表示为十六进制值,其范围从\u0000到\uFFFF。例如,\u2122表示商标符号(TM),\u03C0 表示希腊字母π。

转义序列\u还可以出现在加引号的字符常量或字符串之外(而其他所有转义序列不可以)。

例如:public static void main(String\u005B\u005D args)就完全符合语法规则,\u005B和\u005D分别是 [ 和 ] 的编码。

转移序列 名称 Unicode值 转义序列 名称 Unicode值
\b 退格 \u0008 \" 双引号 \u0022
\t 制表 \u0009 \’ 单引号 \u0027
\n 换行 \u000a \\ 反斜线 \u005c
\r 回车 \u000d \s 空格,在文本块中用来保留末尾空白符 \u0020
\f 换页 \u000c \newline 只在文本块中使用:连接这一行和下一行

Unicode转义序列会在解析代码之前得到处理。

例如,“\u0022+\u0022"并不是一个由引号(U+0022)包围加号构成的字符串。实际上, u0022会在解析之前转换为这会得到” “+” ",也就是一个空串。

更隐秘地,一定要当心注释中的 u。
// \u000A is a newline会产生一个语法错误,因为读程序时\u000A会替换为一个换行符。

类似地,下面这个注释
// look inside c:\users 也会产生一个语法错误,因为 u后面并没有跟着4个十六进制数。

3.3.4 boolen型

boolean (布尔)类型有两个值: false 和 true,用来判定逻辑条件。整型值和布尔值之间不能进行相互转换

3.4 变量与常量

3.3.1 声明变量

变量名命名规范:由字母、数字、货币符号、标点连接符组成。第一个字符不能为数字

  • '+'和’©’之类的符号不能出现在变量名中,空格也不行
  • 字母区分大小写(main和Main就是不同的变量名)
  • 大多数使用的是A-Z、a-z、0-9、和下划线"_"
  • 不能使用Java关键字做为变量名
  • 在Java9中,单个下划线"_"是一个保留字。

尽管$是一个合法的 Java 字符,但不要在你自己的代码中使用这个字符。它只用在 Java编译器或其他工具生成的名字中。

3.3.2 初始化变量

声明一个变量之后,必须用赋值语句对变量进行显式初始化,千万不要使用未初始化的变量的值。

例如,Java 编译器认为下面的语句序列是错误的:

int vacationDays;
System.out.println(vacationDays);

在 Java中可以将声明放在代码中的任何地方

在Java 中,变量的声明尽可能地靠近变量第一次使用的地方,这是一种良好的程序编写风格。

注释:从Java 10开始,对于局部变量,如果可以从变量的初始值推断出它的类型就不再需要声明类型。只需要使用关键字 var而无须指定类型

var vacationDays =12;//  intvar greeting="Hello";// String

3.3.3 常量

在Java中使用关键字final定义常量

关键字 final 表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。习惯上,常量名使用全大写。

在Java 中,经常希望某个常量可以在一个类的多个方法中使用,通常将这些常量称类常量(class constant)。可以使用关键字 static final设置一个类常量。

public class constant {public static final double CM_PER_INCH = 2.54;public static void main(String[] args) {double width = 8.5;double height = 11.0;System.out.println(width * CM_PER_INCH + " + " + height * CM_PER_INCH);//21.59 + 27.94}
}

3.3.4 枚举类型

有时候,变量的取值只在一个有限的集合内。例如,销售的服装或比萨只有小、中、大和超大这四种尺寸。

当然,可以将这些尺寸分别编码为 1、2、3、4或字符S、M、L、X。但这种设置很容易出错。很可能在变量中保存的是一个错误的值(如@或m)。

针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。

例如,enum Size{ SMALL,MEDIUM,LARGE,EXTRA_LARGE };
现在,可以声明这种类型的变量:
Size s = Size.MEDIUM:
size类型的变量只能存储这个类型声明中给定的某个枚举值,或者特殊值 null,null表示这个变量没有设置任何值。

3.5 运算符

3.3.1 算数运算符

加(+)、减(-)、乘(*)、除(/)、取模(取余)(%)

3.3.2 数学函数与常量

在Math类中,包含了各种各样的数学函数

double x = 4;
double y = Math.sqrt(x);System.out.println(y);//2.0

Math 类提供了一些常用的三角函数:

  • Math.sin
  • Math.cos
  • Math.tan
  • Math.atan
  • Math.atan2

还有指数函数以及它的反函数一自然对数以及以 10 为底的对数:

  • Mathexp
  • Math.log
  • Math.log10

最后,Java还提供了两个用于表示“和e常量的最接近的近似值:

  • Math.PI
  • Math.E

3.3.3 数据类型之间的转换

3.3.4 强制类型转换

强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。

double x = 9.997;
int y = (int) x;
System.out.println(y);//9

如果想对浮点数进行舍入运算,需要使用Math.round 方法

double x = 9.997;
int y = (int) Math.round(x);
System.out.println(y);//10

如果试图将一个数值从一种类型强制转换为另一种类型,而又超出了目标类型的表示范围,结果就会截断成一个完全不同的值。

例如,(byte)300的实际值为44。

3.3.5 赋值

"="表示赋值,不是判断相等

赋值:将等号右边的值赋给等号右边的变量

int x = 1;
int y = x += 4;//y = 5
System.out.println(y);//5

如果运算符得到一个值,其类型与左侧操作数的类型不同,就会发生强制类型转换。

例如,如果x是一个int,则以下语句

x+= 3.5;

是合法的,将把x设置为(int)(x+3.5)

3.3.6 自增与自减运算符

i++:先运算,再相加

++i:先相加,再运算

int x = 1;
int y = 1;int a = x++;//1
int b = ++y;//

3.3.7 关系和boolean运算符

大于(>)、等于(=)、不等于(!=)、小于(<)、小于等于(<=)、大于等于(>=)

&&:一假全假(如果左边的表达式为假,则直接判断为假,右边不再进行判断)

||:一真全真(如果左边的表达式为真,则直接判断为真,右边不再进行判断)

3.3.8 条件运算符

条件运算符也叫三目运算符

格式:表达式1?表达式2:表达式3

3.3.9 位运算符

& 按位与

| 按位或
^ 按位异或

~ 取反

>>右移

<<左移

移位运算符的右操作数要完成模32的运算(除非左操作数是 long类型,在这种情况下需要对右操作数模64)。

例如,1<35的值等同于1<<3或8

3.3.10 括号与运算符级别

运算符 综合性
[]、. 、() 从左到右
!、~、++、–、+、-、()、new 从右到左
*、/、% 从左到右
+、- 从左到右
<<、>>、>>> 从左到右
<、<=、>、>=、instanceof 从左到右
==、!= 从左到右
& 从左到右
^ 从左到右
| 从左到右
&& 从左到右
|| 从左到右
? : 从右到左
=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=、>>>= 从右到左

3.6 字符串

3.6.1 字串

String类的substring 方法可以从一个较大的字符串提取出一个子串。

String greeting ="Hello";
String s = greeting.substring(0,3);//Hel

3.6.2 拼接

Java语言允许使用+号连接(拼接)两个字符串

String expletive ="Expletive";
String PG13 ="deleted";
String message =expletive + PG13;
System.out.println(message);//Expletivedeleted

当将一个字符串与一个非字符串的值进行拼接时,后者会转换成字符串

int answer = 3;
System.out.println("The answer is "+ answer);//The answer is 3

如果需要把多个字符串放在一起,用一个界定符分隔,可以使用静态join 方法:

String all = String.join("/","S","M","L","XL");
System.out.println(all);//S/M/L/XL

在Java11中,还提供了一个repeat 方法:

String repeated = "Java".repeat(3);
System.out.println(repeated);//JavaJavaJava

3.6.3 字符串不可变

String类没有提供修改字符串中某个字符的方法

/*将greeting的内容修改为   Help!*/
String greeting = "hello";
greeting = greeting.substring(0,3) + "p!";
System.out.println(greeting);// Help!

不可变字符串有一个优点:编译器可以让字符串共享

可以想象将各种字符串存放在公共的存储池中。字符串变量指向存储池中相应的位置。如果复制一个字符串变量,原始字符串与复制的字符串共享相同的字符。

Java 的设计者认为共享带来的高效率远远胜过于提取子串、拼接字符串所带来的低效率。可以看看你自己的程序,我们发现:大多数情况下都不会修改字符串,而只是需要对字符串进行比较

3.6.4 判断字符串是否相等

使用equals方法检测两个字符串是否相等

要想检测两个字符串是否相等,而不区分大小写,可以使用equalsIgnoreCase方法

一定不要使用==运算符检测两个字符串是否相等(==比较两个字符串的地址值,不是实际的值)

3.6.5 空字符串与Null

空字符"“是长度为0的字符串

空字符是一个Java对象,有自己的串长度(0)和内容(空)

Strin可以存放一个特殊的值,名为 null,表示目前没有任何对象与该变量关联

有时要检查一个字符串既不是 null 也不是空串,这种情况下就需要使用以下条件:(首先检查不为null)

if (str != null && str.length() != 0)

3.6.6 Sting API

3.6.7 构建字符串

需要用许多小段的字符串来构建一个字符串

先构建一个空的字符串构建器

StringBuilder builder = new StringBuilder();

当每次需要添加一部分内容时,就调用append 方法

builder.append(greeting);// Help!
builder.append(all);//S/M/L/XL

在字符串构建完成时就调用tostring方法,将可以得到一个String对象,其中含了构建器中的字符序列。

String str = builder.toString();System.out.println(str);//help!S/M/L/XL

StringBuffer 类的效率不如StringBuilder 类,不过它允许采用多线程的方式添加或删除字符。

如果所有字符串编辑操作都在单个线程中执行(通常都是这样),则应当使用StringBuilder 类。这两个类的 API是一样的。

3.6.8 文本块

文本块 (text block) 特性【 Java 15 新增】,可以很容易地提供多行的字符串字面量

文本块以"““开头(这是开始””“),后面是一个换行符,并以另一个”““结尾(这是结束””")

String a = """HelloWorld""";
String b = "Hello\nWorld\n";
System.out.println(a);
System.out.println(b);

字符串a相比于b更加易于读写

文本块特别适合包含用其他语言编写的代码,如 SQL或 HTML。可以直接将那些代码粘贴到一对三重引号之间

String html = """<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><title>Title</title></head><body>""";
  • 在文本块中一般不需要对引号进行转义,以下两种情况除外

    • 文本块以一个引号结尾。
    • 文本块中包含三个或更多引号组成的一个序列。
  • 所有反斜线都需要转义

  • 常规字符串中的所有转义序列在文本块中也有同样的作用。

  • 行尾的\会把这一行与下一行连接起来。

    • """Hello\World""";
      等同于
      "HelloWorld";
      
    • 文本块会对行结束符进行标准化,删除末尾的空白符,并把 Windows 的行结束符 (\r\n)改为简单的换行符 (\n)。

  • 对于前导空白符则更为复杂。考虑一个从左边界缩进的典型的变量声明。文本块也可以缩进

    • s1与s2一样

    • String s1 = """<div class="Warning">Beware of those who say "Hello" to the world</div>""";
      String s2 = " <div class=\"Warning\">\n  Beware of those who say \"Hello\" to the world\n </div>\n";
      
    • 要当心缩进文本块的公共前缀中混用制表符和空格的情况

      不小心漏掉一个空格很容易得到一个缩进错误的字符串

3.7 输入与输出

3.7.1 读取输入

Scanner sc = new Scanner(System.in);

创建Scanner对象后,可以使用Scanner类的方法读取输入

  • nextLine方法读取一行

    • System.out.println("请输入你的姓名:");
      String name = sc.nextLine();
      
  • 读取一个单词

    • System.out.println("请输入你的性别:");
      String gender = sc.next();
      
  • nextInt 方法读取一个整数

    • System.out.println("请输入你的年龄:");
      int age = sc.nextInt();
      

因为输入是可见的,所以Scanner 类不适用于从控制台读取密码。Java6特别引入了Console类来实现这个目的。

Console cons = System.console();
String username = cons.readLine("用户名");
char[] password = cons.readPassword("密码");

为安全起见,返回的密码存放在一个字符数组中,而不是字符串中。在对密码处理完成之后,应该马上用一个填充值覆盖数组元素。

采用Console对象处理输入不如采用Scanner 方便。必须每次读取一行输入,而没有能够读取单个单词或数值的方法。

3.7.2 格式化输出

String s = "A";
//三种输出方式
System.out.println(s);//自动换行
System.out.print(s);//不会自动换行
System.out.printf("%s",s);//格式化打印

printf转换字符

转换符 类型 示例 转换符 类型 示例
d 十进制整数 159 s 字符串 hello
x 十六进制整数 9f c 字符 H
o 八进制整数 237 b 布尔 true
f 定点浮点数 15.9 h 散列码 42628b2
e 指数浮点数 1.59e+01 tx或Tx 日期时间 已过时(现在使用Java.time类)
g 通用浮点数 % 百分号 %
a 十六进制浮点数 0.x1.fccdp3 n 行分隔符

可以使用s转换字符格式化任意对象。如果调用的对象实现了Formattable接口,会调用formatTo方法,否则会调用toString方法将对象转换为一个字符串

还可以指定控制格式化输出外观的各种标志

System.out.printf("%,.2f", 1000.0 / 3.0);//3,333.33
标志 目的 示例
+ 打印正数和负数符号 +3333.33
空格 在正数之前添加空格 | 3333.33|
0 数字前补0 003333.33
- 左对齐 |3333.33|
( 将负数括在括号内 (3333.33)
, 添加分组分隔符 3,333.33
#(对于f格式) 包含小数点 3,333.
#(对应x或0格式) 添加前缀0x或0 0xcafe
$ 指定要格式化的参数索引(例如:,%1dd%1dx 将以十进制数和十六进制数的格式打印第一个参数) 159 9F
< 格式化前面说明的数值(例如:,%d%<x 将以十进制数和十六进制数的格式打印第一个参数) 159 9F

3.7.3 文件输入与输出

读取一个文件,需要构造一个 Scanner 对象。在构造器中,需要提供文件名和字符编码

Scanner sc = new Scanner(Path.of("a.txt"), StandardCharsets.UTF_8);

就像从控制台输入数据一样,使用 next等方法读取文件数据

记得读完数据后关闭流

System.out.println(sc.nextLine());
sc.close();

要想写入文件,就需要构造一个 PrintWriter 对象。在构造器中,需要提供文件名和字符编码

PrintWriter pw = new PrintWriter("a.txt",StandardCharsets.UTF_8);

像使用System.out一样调用print等其他方法,向文件中写入数据。

写完数据后关闭流

pw.println("help!");
pw.close();

当调用相对路径时,不确定到底是在项目文件夹下还是模块文件夹下时,可以使用

System.out.println(System.getProperty("user.dir"));

打印处当前运行文件的路径,进而确定相对路径的位置

3.8 控制流程

3.8.1 块作用域

块,即复合语句

  • 由若干条 Java 语句组成的语句,并用一对大括号括起来
  • 块确定了变量的作用域
  • 一个块可以嵌套在另一个块中
  • 不能在嵌套的两个块中声明同名的变量

3.8.2 条件语句

if语句

if(布尔表达式)
{//如果布尔表达式为true将执行的语句
}

if (yourSales >= target) {performance = "Satisfactory";bonus = 100;
}

if…else语句

if(布尔表达式){//如果布尔表达式的值为true
}else{//如果布尔表达式的值为false
}

if (yourSales > target) {performance = "Satisfactory";bonus = 100 + 0.01 * (yourSales - target);
} else {performance = "Unsatisfactory";bonus = 0;
}

if…else if…else语句

if(布尔表达式 1){//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){//如果布尔表达式 3的值为true执行代码
}else {//如果以上布尔表达式都不为true执行代码
}

if (yourSales >= 2 * target) {performance = "Excellent";bonus = 1000;} else if (yourSales >= 1.5 * target) {performance = "Fine";bonus = 500;
} else if (yourSales >= target) {performance = "Satisfactory";bonus = 100 + 0.01 * (yourSales - target);
} else {System.out.println("You're fired");
}

3.8.3 循环

while

while( 布尔表达式 ) {//循环内容
}

do…while

do {//代码语句
}while(布尔表达式);

3.8.4 确定性循环

for(初始化; 布尔表达式; 更新) {//代码语句
}

在循环中,检测两个浮点数是否相等需要格外小心。for (double x=0; x!= 10;x+= 0.1)可能永远不会结束。

由于舍入的误差,可能永远达不到精确的最终值。

例如,在上面的循环中,因为0.1无法精确地用二进制表示,所以,x将从9.999 999 999 999 98跳到10.099 999 999 999 98

3.8.5 块作用域switch语句

经典格式

switch(expression){case value ://语句break; //可选case value ://语句break; //可选//你可以有任意数量的case语句default : //可选//语句
}

新格式

switch(expression){case value ->//语句case value ->//语句//你可以有任意数量的case语句default -> //可选//语句
}

switch 语句将从与选项值相匹配的 case 标签开始执行,直到遇到 break 语句,或者执行到switch 语句的结束处为止。

如果没有相匹配的 case 标签,而有 default 子句,就执行这个子句。

case后面的value可以是

  • 类型为 char、byte、short 或 int 的常量表达式
  • 枚举常量。
  • 字符串字面量
  • 多个字符串,用逗号隔开

3.8.6 中断控制流程语句

break

  • break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。
  • break 跳出最里层的循环,并且继续执行该循环下面的语句。

continue

  • continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。
  • 在 for 循环中,continue 语句使程序立即跳转到更新语句。
  • 在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。

3.9 大数

如果基本的整数和浮点数精度不能够满足需求,那么可以使用 java.math 包中两个很有用的类:BigInteger 和 BigDecimal。

  • 这两个类可以处理包含任意长度数字序列的数值。
  • BigInteger类实现任意精度的整数运算
  • BigDecimal 实现任意精度的浮点数运算。

使用静态的 valueof 方法可以将普通的数值转换为大数

BigInteger a = BigInteger.valueOf(100);
BigInteger b = BigInteger.valueOf(10);

对于更大的数,可以使用一个带字符串参数的构造器

BigInteger bigInteger = new BigInteger("222232244629420445529739893461909967206666939096499764990979600");

大数中的一些常量

BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger ten = BigInteger.TEN;
BigInteger two = BigInteger.TWO;//Java9之后增加的BigInteger.TWO

不能使用人们熟悉的算术运算符(如:+和*)处理大数,而需要使用大数类中的add和multiply方法

BigInteger c = a.add(b);//c = a + b
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2)));//d = c * (b + 2)

BigInteger常用API

BigDecimal常用API

3.10 数组

3.10.1 声明数组

数组是一种数据结构,用来存储同一类型值的集合。通过一个整型索引 (index,或称下标)可以访问数组中的每一个值。

  • 例如,如果 a 是一个整型数组,a[i] 就是数组中索引为i的整数。

在声明数组变量时,需要指出数组类型(数据元素类型紧跟[])和数组变量的名字。 int[] a;

初始化数组int[] arr = new int[100];(可以存储 100个整数的数组)

数组长度不要求是常量

一旦创建了数组,就不能再改变它的长度(不过,当然可以改变单个的数组元素)。

声明数组的两种形式

int[] arr = new int[100];
int arr[] = new int[100];

在Java中,提供了一种创建数组对象并同时提供初始值的简写形式(不需要使用new,不需要指定长度)

int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

声明一个匿名数组,这会分配一个新数组并填入大括号中提供的值。它会统计初始值个数,并相应地设置数组大小。

可以使用这种语法重新初始化一个数组而无须创建新变量。

int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};a = new int[] {2,4,2,1,5,6,10,11};

在Java中,允许有长度为0的数组。

在编写一个结果为数组的方法时,如果碰巧结果为空,这样一个长度为0的数组就很有用。

长度为0的数组与null并不相同

3.10.2 访问数组元素

数组元素从0开始编号,最后一个合法的索引值为数组长度减1

一旦创建数组,就可以在数组中添加元素

int[] arr = new int[100];
for (int i = 0; i < arr.length; i++) {arr[i] = i;
}
  • 数字数组的元素会初始化为0。
  • boolean 数组的元素会初始化为 false。
  • 对象数组的元素会初始化为一个特殊值 null

如果创建了一个100个元素的数组,并且试图访问元素a[100](或在0~99之外的任何下标),就会引发“array index out of bounds”数组越界异常。

可以使用length方法获取数组长度

System.out.println(arr.length);//100

3.10.3 for each循环(增强for)

增强 for循环的语句格式

for (variable : collection) statement
  • 它定义一个变量用于暂存集合中的每一个元素(variable),并执行相应的语句(statement)(当然,也可以是语句块)。
  • collection 表达式必须是一个数组或者是一个实现了 Iterable 接口的类对象
for (int i : arr) {System.out.println(i);//循环打印数组元素
}

for each 循环语句的循环变量将会遍历数组中的每个元素,而不是索引值

有一个更加简单的方式可以打印数组中的所有值,即利用Arrays类的 toString方法。调用Arrays.toString(a),返回一个包含数组元素的字符串

int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println(Arrays.toString(a));//  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

3.10.4 数组拷贝

在 Java 中,允许将一个数组变量拷贝到另一个数组变量。这时,两个变量将引用同一个数组:

int[] luckyNumber =smallPrimes;
luckyNumber[5] = 12;

如果希望将一个数组的所有值拷贝到一个新的数组中去,就要使用Arrays类的copyof方法

int[] d = Arrays.copyOf(luckyNumber, luckyNumber.length);

第2个参数是新数组的长度。这个方法通常用来增加数组的大小:

luckyNumber = Arrays.copyof(luckyNumber,2 * luckyNumber.length);

3.10.5 命令行参数

3.10.6 数组排序

使用Arrays类中的sort 方法(从小到大)

int[] sort = new int[]{2, 4, 2, 1, 5, 6, 10, 11};
Arrays.sort(sort);
System.out.println(Arrays.toString(sort));//[1, 2, 2, 4, 5, 6, 10, 11]

3.10.7 多维数组

声明二维数组

//方法一
double[][] balances = new double[10][10];
//方法二
int[][] magicSquare ={{16, 3, 2, 13},{5, 10, 1, 8},{9, 6, 7, 12},{4, 15, 14, 1}};

打印二维数组

for (int i = 0; i < magicSquare.length; i++) {for (int j = 0; j < magicSquare[i].length; j++) {System.out.print(magicSquare[i][j]+ " ");}System.out.println();
}

foreach循环语句不能自动处理二维数组的每一个元素。

它会循环处理行,而这些行本身就是一维数组。要想访问二维数组a的所有元素,需要使用两个嵌套的循环

for (int[] ints : magicSquare) {for (int anInt : ints) {System.out.print(anInt + " ");}System.out.println();
}

快速打印二维数组可以使用Arrays类的deepToString方法

System.out.println(Arrays.deepToString(magicSquare));

3.10.8 不规则数组

到目前为止,我们看到的数组与其他程序设计语言中提供的数组没有多大区别。但在底层实际存在着一些细微的差异,有时你可以充分利用这一点: Java 实际上没有多维数组,只有一维数组。多维数组被解释为“数组的数组”。

《Java核心技术》(第12版)笔记(二)相关推荐

  1. 《Java核心技术 卷Ⅰ》读书笔记一

    Java核心技术·卷 I(原书第10版) 作者: [美] 凯.S.霍斯特曼(Cay S. Horstmann) 出版社: 机械工业出版社 原作名: Core Java Volume I - Funda ...

  2. 《Java核心技术卷一》读书笔记

    <Java核心技术卷一>读书笔记 对象与类 类 类是构造对象的模板.蓝图.由类构造对象的过程称为类的实例. 对象的数据叫做实例域,操作数据的过程叫做方法 对于每个特定的类实例(对象)都要一 ...

  3. 《Java 核心技术 卷1》 笔记 第五章 继承(3)

    5.1.6 抽象类 有时候我们无法说出具体是什么,只能用于标识一个类型,比如图形,就可作为抽象类.虽然无法具体描述图形,但是图形通常都有面积.周长.这种时候就可用抽象类标识. 抽象类使用abstrac ...

  4. Java核心技术·卷二·第一章笔记

    Java核心技术·卷二·笔记 第一章:Java8的流库 Java8引入的用来以"做什么而非怎么做"的方式的处理集合 1.1 从迭代到流的操作 package com.package ...

  5. 《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试

    出现不可预计的问题时,需要进行如下处理: 报告错误 保存操作结果 允许用户退出 本章解决的问题: 验证程序正确性 记录程序错误 调试技巧 11.1 处理异常 程序出现错误时应该: 返回安全状态,能让用 ...

  6. Java核心技术第10版原书笔记(卷一 第4章)

    第4章 Java程序设计概述 4.1 面向对象程序设计概述 1.面向对象程序设计(简称OOP)是当今主流的程序设计范型,它已经取代了20世纪70年代的"结构化"过程化程序设计开发技 ...

  7. core java第十版_java核心技术第十版 笔记

    1.java区分大小写 2.类名是以大写字母开头 (驼峰) 3.http://docs.oracle.com/javase/specs  java语言规范 4. /* */ 注释不能嵌套 5. Jav ...

  8. 牛客java面试题总结版(二)

    6.Java中的方法覆盖(Overriding)和方法重载(Overload)是什么意思? 官方版:Java中的方法重载发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况.与此相对,方 ...

  9. Java面试题库,java核心技术第十版下载

    阿里巴巴篇 1.扎实的计算机专业基础,包括算法和数据结构,操作系统,计算机网络,计算机体系结构,数据库等2.具有扎实的Java编程基础,理解IO.多线程等基础框架3.熟练使用Linux系统的常用命令及 ...

  10. Java核心技术卷1心得笔记1---Java程序设计概述

    第一章 Java程序设计概述 本章主要介绍了Java程序设计平台,Java关键术语,Java applet,Java发展史以及常见几个易误解的概念. 主要了解下Java关键术语,Java applet ...

最新文章

  1. 中国研制出首款搭载寒武纪AI芯片的人工智能服务器
  2. 主机信息收集技术 -Nmap
  3. 在最美好的年华里,不要辜负最美的自己
  4. apmserv mysql密码_apmserv中修改mysql的root与phpmyadmin密码方法介绍_PHP教程
  5. Python-----学了今天,忘了昨天.
  6. 新的一年babel了解一下
  7. mssql 无法启动调试器 数据为空_Windows无法启动:如何利用PE拯救桌面重要数据?...
  8. php dir()函数的用法
  9. 中国企业人工智能应用之道——从“浅尝试”到“规模化”.pdf(附下载链接)...
  10. iOS换肤功能的简单处理框架
  11. Mugeda(木疙瘩)H5案例课—房地产楼书H5制作-岑远科-专题视频课程
  12. 期货公司开户实力经纪业务的规模
  13. BIOS的两种引导模式
  14. python 比较运算符列表_python基础-列表,文件,运算符
  15. nginx中的超时设置,请求超时、响应等待超时等
  16. Python实现“维基百科六度分隔理论“之基础爬虫
  17. 神经网络neural network
  18. CSS3线性渐变与径向渐变
  19. opencv学习4——图像缩放
  20. poj1737 Connected Graph(计数,组合数学,递推,高精)

热门文章

  1. IEC104通信流程
  2. 关于使用QT在ARM上实现ffmpeg播放视频的思路
  3. JAVA操作图片/合成/电子盖章等
  4. 西安电子科技大学-电磁场与电磁波大作业-生活中的电磁场与电磁波
  5. javaweb项目报告(吃货联盟)
  6. 【设计模式--->结构型】叩心自问 :桥接设计模式
  7. 换新网络后,群辉NAS如何手动更换为新静态IP
  8. 什么是域名劫持和域名污染
  9. 民航局:春运期间10个大型机场将延长国内航班运行时间
  10. win10 64位操作系统写注册表失败 VS C++