目录
输入输出
读取输入
import java.util.*;
// 构造标准输入流对象
Scanner in = new Scanner(System.in);
// 读取一行
System.out.print("What is your name? ");
String name = in.nextLine();
// 读取一个单词
String firstName = in.next();
// 读取整数
System.out.print("How old are you? ");
int age = in.nextlnt();
// Console 对象
Console cons = System.console();
String username = cons.readLine("User name: ");
char[] passwd = cons.readPassword("Password:");
Scanner
类定义在java.util
包中。 当使用的类不是定义在基本java.lang
包中时,一定要使用import
指示字将相应的包加载进来。Console
类可用于密码输入,相比显式的Scanner
更为安全。但是采用Console
对象处理输入不如采用Scanner
方便。每次只能读取一行输入, 而没有能够读取一个单词或一个数值的方法。
常用方法:
Scanner(InputStream in)
:用给定的输人流创建一个Scanner
对象。Scanner.nextLine()
:读取输入的下一行内容。Scanner.next()
:读取输入的下一个单词(以空格作为分隔符。Scanner.nextInt()
或Scanner.nextDouble()
:读取并转换下一个表示整数或浮点数的字符序列。Scanner.hasNext()
:检测输人中是否还有其他单词。Scanner.hasInt()
或Scanner.hasDouble
:检测是否还有表示整数或浮点数的下一个字符序列。System.console()
:如果有可能进行交互操作, 就通过控制台窗口为交互的用户返回一个 Console 对象,否则返回 null。对于任何一个通过控制台窗口启动的程序, 都可使用 Console 对象。否则, 其可用性将与所使用的系统有关。Console.readPassword(String prompt, Object...args)
或Console.readLine(String prompt, Object...args)
:显示字符串 prompt 并且读取用户输入,直到输入行结束。args 参数可以用来提供输人格式。
格式化输出
在 printf
中,可以使用多个参数,每一个以 % 字符开始的格式说明符都用相应的参数替换。格式说明符尾部的转换符将指示被格式化的数值类型:f 表示浮点数,s 表示字符串,d 表示十进制整数。
转换符 | 类型 | 举例 |
---|---|---|
d | 十进制整数 | 159 |
x | 十六进制整数 | 9f |
o | 八进制整数 | 237 |
f | 定点浮点数 | 15.9 |
e | 指数浮点数 | 1.59e+01 |
g | 通用浮点数 | — |
a | 十六进制浮点数 | 0x1.fccdp3 |
s | 字符串 | Hello |
c | 字符 | H |
b | 布尔 | True |
h | 散列码 | 42628b2 |
% | 百分号 | % |
n | 与平台有关的行分隔符 | — |
另外,还可以给出控制格式化输出的各种标志。
标志 | 目的 | 举例 |
---|---|---|
+ | 打印正数和负数的符号 | +33.33 |
空格 | 在正数之前添加空格 | | 33.3| |
0 | 数字前面补 0 | 033.33 |
- | 左对齐 | |33.3 | |
( | 将负数括在括号内 | (33.3) |
, | 添加分组分隔符 | 3,333.3 |
# | 对于 f 格式:包含小数点 对于 x 或 0 格式:添加前缀 0x 或 0 | 3,333. 0xcafe |
$ | 给定被格式化的参数索引。例如,%1$d,%1$x 将以十进制和十六进制格式打印第 1 个参数 | 159 9F |
< | 格式化前面说明的数值。例如,%d%<x 以十进制和十六进制打印同一个数值 | 159 9F |
参数索引值从 i 开始,而不是从 0 开始,%1$..
对第 1 个参数格式化这就避免了与 0 标志混淆。
文件输入输出
// 文件读入
import java.util.*;
Scanner in = new Scanner(Paths.get("niyflle.txt"), "UTF-8");
// 文件写入
PrintWriter out = new Printlulriter("myfile.txt", "UTF-8");
要想对文件进行读取,就需要一个用 File 对象构造一个 Scanner
对象。如果文件名中包含反斜杠符号,需要使用转义符,即"\\",例:“c:\\mydirectory\\myfile.txt”。
要想写入文件,就需要构造一个 PrintWriter
对象。在构造器中,只需要提供文件名。如果文件不存在,创建该文件。 可以像输出到 System.out
一样使用 print
、 println
以及 printf
命令。
常用方法:
Scanner(File f)
:构造一个从给定文件读取数据的 Scanner。注意,文件不能直接用文件名的字符串表示,需使用Paths.get(String pathname)
方法。Scanner(String data)
:构造一个从给定字符串读取数据的 Scanner。PrintWriter(String fileName)
:构造一个将数据写入文件的 PrintWriter。文件名由参数指定。Paths.get(String pathname)
:根据给定的路径名构造一个Path
。
控制流程
条件判断
// 单分支
if (condition)
{
statement;
}
if (condition)
{
statement1;
}
else
{
statement2;
}
// 多分支
if (condition1)
{
statement1;
}
else if (condition2)
{
statement2;
}
else
{
statement3;
}
循环
// while 循环
while (condition)
{
statement;
}
// do...while 循环
do
{
statement;
}
while (condition);
// for 循环
for (int i = 1; i <= 10; i++)
{
System.out.println(i);
}
while
循环和do-while
循环要在循环体中更新条件判断变量,从而保证在有限次循环后能够跳出循环,否则一旦进入循环将陷入死循环。do-while
循环最后需要加;
。for
循环的 3 个部分应该对同一个计数器变量进行初始化、检测和更新。for
循环的计数器变量不能在循环外使用。- 在判断循环条件时,注意浮点数的舍入误差,以免陷入死循环。
多重选择(switch)
switch (choise):
{
case 1:
{
statement1;
break;
}
case 2:
{
statement2;
break;
}
case 3:
{
statement3;
break;
}
default:
{
statement4;
break;
}
}
在处理多个选项时,使用 if-else
结构显得有些笨拙。switch
语句将从与选项值相匹配的 case
标签处开始执行直到遇到 break
语句,或者执行到 switch
语句的结束处为止。如果没有相匹配的 case
标签,而有 default
子句,就执行这个子句。
注意:若在 case
的结尾不加 break
,则程序会继续执行下一个 case
分支,从而产生错误。
case
标签支持:
- 类型为
char
、byte
、int
、short
的常量表达式 - 枚举常量
- 从 Java SE 7开始,
case
标签还可以是字符串字面量。
continue 和 break
continue
:跳过此轮循环的剩余部分,并直接进入下一轮循环。break
:退出当前的循环块,或退出当前switch
语句块。- 带标签的
continue
:程序将跳到与标签匹配的循环首部。 - 带标签的
break
:程序跳转到带标签的语句块末尾。 - 对于任何使用
break
语句的代码都需要检测循环是正常结束,还是由break
跳出。
// 带标签的 break
Scanner in = new Scanner(System.in);
int n;
read_data:
while (...) // this loop statement is tagged with the label
{
...
for (...) // this inner loop is not labeled
{
Systen.out.print("Enter a number >= 0: ");
n = in.nextlnt();
if (n < 0) // should never happen-can’t go on
break read.data;
// break out of readjata loop
...
}
}
// this statement is executed immediately after the labeled break
if (n < 0) // check for bad situation
{
// deal with bad situation
}
else
{
// carry out normal processing
}
大数值类
如果基本的整数和浮点数精度不能够满足需求, 那么可以使用java.math
包中的两个很有用的类:Biglnteger
和 BigDecimal
。 这两个类可以处理包含任意长度数字序列的数值。Biglnteger
类实现了任意精度的整数运算,BigDecimal
实现了任意精度的浮点数运算。
// 普通数值转换为大数值
Biglnteger a = Biglnteger.valueOf(100);
// c = a + b
Biglnteger c = a.add(b);
// d = c * (b + 2)
Biglnteger d = c.nul tipi y(b.add(Biglnteger.valueOf(2)));
常用方法:
Biglnteger.valueOf(long x)
:返回值等于 x x x 的大整数。Biglnteger.add(Biglnteger other)
Biglnteger.subtract(Biglnteger other)
Biglnteger.multiply(Biginteger other)
Biglnteger.divide(Biglnteger other)
Biglnteger.mod(Biglnteger other)
- 返冋这个大整数和另一个大整数 other 的和、差、积、商以及余数。
BigInteger.compareTo(Biglnteger other)
:如果这个大整数与另一个大整数 other 相等,返回 0;如果这个大整数小于另一个大整数 other,返回负数;否则,返回正数。
BigDecimal.valueOf(long x)
或BigDecimal.valueOf(long x, int scale)
:返回值为 x x x 或 x / 1 0 s c a l e x / 10^{scale} x/10scale 的一个大实数。BigDecimal.add(BigDecimal other)
BigDecimal.subtract(BigDecimal other)
BigDecimal.multiply(BigDecimal other)
BigDecimal.divide(BigDecimal other RoundingMode mode)
- 返回这个大实数与另一个大实数 other 的和、差、积、商。要想计算商,必须给出舍入方式(rounding mode) 。
RoundingMode.HALF_UP
是四舍五入方式(即,数值 0 到 4 舍去,数值 5 到 9 进位)。它适用于常规的计算。有关其他的舍入方式请参看 API 文档。 BigDecimal.compareTo(BigDecimal other)
:如果这个大实数与另一个大实数相等,返回 0;如果这个大实数小于另一个大实数,返回负数;否则,返回正数。
数组
数组是一种数据结构, 用来存储同一类型值的集合。通过一个整型下标可以访问数组中的每一个值。例如, 如果 a 是一个整型数组, a[i] 就是数组中下标为 i 的整数。
在声明数组变量时, 需要指出数组类型(数据元素类型紧跟 [])和数组变量的名字,使用 new 运算符创建数组。例:int[] a = new int[100];
。数组一旦被创建,大小就不能再改变,在访问数组元素时,注意下标不能越界(0~n-1)。
- 数字数组元素自动初始化为 0
boolean
数组元素自动初始化为false
- 对象数组元素自动初始化为
null
for-each 循环
// 打印数组中所有的元素
for (int element : a)
{
System.out.println(element);
}
匿名数组
// 不使用 new,自动初始化数组
int[] smallPrimes = { 2, 3, 5, 7, 11, 13 };
// 匿名数组:等号右边部分为匿名数组,直接返回一个已初始化的数组
smallPrimes = new int[] { 17, 19, 23, 29, 31, 37 };
注意:在 Java 中,允许数组长度为 0。在编写一个结果为数组的方法时,如果碰巧结果为空,则这种语法形式就显得非常有用。数组长度为 0 与 null
不同。
数组拷贝
在 Java 中,允许将一个数组变量拷贝给另一个数组变量。这时, 两个变量将引用同一个数组。
int[] luckyNumbers = smallPrimes;
luckyNumbers[5] = 12; // now smallPrimes[5] is also 12
如果希望将一个数组的所有值拷贝到一个新的数组中去,就要使用 Arrays 类的 copyOf
方法:
int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers, LuckyNumbers.length);
命令行参数
每一个 Java 应用程序都有一个带 String args[]
参数的 main 方法。这个参数表明 main
方法将接收一个字符串数组,也就是命令行参数。
public class Message
{
public static void main(String[] args)
{
if (args.length == 0 || args[0].equals("-h"))
System.out.print(Hello,");
else if (args[0].equa1s("-g"))
System.out.print("Goodbye ,");
// print the other command-line arguments
for (int i = 1; i < args.length; i ++)
System.out.print(" " + args[i]);
System.out.println("!");
}
}
/**
* 用如下方式运行该程序
* java Message -g cruel world
* 输出结果为:
* Goodbye, cruel world!
*/
Arrays 方法
java.util.Arrays
Arrays.toString(type[] a)
:返回包含 a 中数据元素的字符串,这些数据元素被放在括号内,并用逗号分隔。- 参数
a
:类型为 int、long、short、char、byte、boolean、float 或 double 的数组。
- 参数
Arrays.copyOf(type[] a, int length)
或Arrays.copyOfRange(type[] a, int start, int end)
:返回与 a 类型相同的一个数组,其长度为 length 或者 end-start,数组元素为 a 的值。- 参数
a
:类型为 int、long、short、char、byte、boolean、float 或 double 的数组。 - 参数
start
:起始下标(包含这个值)。 - 参数
end
:终止下标(不包含这个值)。这个值可能大于 a.length。在这种情况下,结果为 0 或 false。 - 参数
length
:拷贝的数据元素长度。如果 length 值大于 a.length,结果为 0 或 false;否则,数组中只有前面 length 个数据元素的拷贝值。
- 参数
Arrays.sort(type[] a)
:采用优化的快速排序算法对数组进行排序。- 参数
a
:类型为 int、long、short、char、byte、boolean、float 或 double 的数组。
- 参数
Arrays.binarySearch(type[] a, type v)
或Arrays.binarySearch(type[] a, int start, int end, type v)
:采用二分搜索算法查找值 v。如果查找成功,则返回相应的下标值;否则,返回一个负数值 r。-r-1 是为保持 a 有序 v 应插入的位置。- 参数
a
:类型为 int、long、short、char、byte、boolean、float 或 double 的数组。 - 参数
start
:起始下标(包含这个值)。 - 参数
end
:终止下标(不包含这个值)。 - 参数
v
:同 a 的数据元素类型相同的值。
- 参数
Arrays.fill(type[] a , type v)
:将数组的所有数据元素值设置为 v。- 参数
a
:类型为 int、long、short、char、byte、boolean、float 或 double 的数组。 - 参数
v
:同 a 的数据元素类型相同的值。
- 参数
Arrays.equals(type[] a, type[] b)
:如果两个数组大小相同,并且下标相同的元素都对应相等,返回 true。- 参数
a
、b
:类型为 int、long、short、char、byte、boolean、float 或 double 的数组。
- 参数
不规则数组
多维数组的创建、遍历等规则均与一维数组类似,而实际多维数组的存储结构如下:
Java 实际上没有多维数组,只有一维数组。最内层的数组存放实际的数据值数组的首地址,而次内层存放各个下一层数组的首地址,这些首地址作为次内层数组的元素,以此类推,从而实现多维数组。
这个特点使得 Java 数组还能构造不规则数组,以上图二维数组为例:只需保证“中间”的数组元素为一个一维数组的首地址即可,而对于“更内层”的一维数组具体大小,没有限制。
参考资料:
- 《Java核心技术 卷1 基础知识》