一个简单的Java应用程序
public class FirstSimple{
public static void main(String[] args){
System.out.println("Hello World!");
}
}
数据类型
Java中共有8种基本类型,其中有4种整型、2种浮点类型、1种字符类型和1种用于表示真值的boolean类型
整型
类型 | 存储需求 | 取值范围 |
---|---|---|
int | 4字节 | -2 147 483 648 ~ 2 147 483 647(刚好超过20亿) |
short | 2字节 | -32768 ~ 32767 |
long | 8字节 | -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 808 |
byte | 1字节 | -128 ~ 127 |
- byte和short类型用于特定的应用场合,例如,底层的文件处理或者存储空间很宝贵时的大数组
- 数字字面量可以加下划线让人易读,如1_000_000(或0b1111_0100_0010)编译时会去除下划线
浮点类型
类型 | 存储需求 | 取值范围 |
---|---|---|
float | 4字节 | 大约±3.402 823 47E+38F(有效位数为6~7位) |
double | 8字节 | 大约±1.797 693 134 862 315 70E+308(有效位数为15位) |
- 浮点数值不适用于无法接受舍入误差的金融计算,例如System.out.println(2.0-1.1)将打印出0.8999999999999999,此时应该使用BigDecimal类
- 没有后缀f的浮点数(如3.14)默认为double类型
char类型
原用于表示单个字符,现在有些Unicode字符可以用一个char值描述,一些Unicode需要两个char值
转义序列 | \b | \t | \n | \r | \“ | \‘ | \\ |
---|---|---|---|---|---|---|---|
名称 | 退格 | 制表 | 换行 | 回车 | 双引号 | 单引号 | 反斜杠 |
Unicode值 | \u0008 | \u0009 | \u00a | \u00d | \u0022 | \u0027 | \u005c |
- 不建议在程序中使用char类型,除非确实需要处理UTF-16代码单元
- 转义序列\u可以出现在加引号的字符串外,例如
main(String \u005B\u005D args)
就等于main(String[] args)
- 字符串
\u0022+\u0022
会转换为""+""
,是一个空串// \u000a is a newline
会产生一个语法错误,因为读程序时\u00a0
会替换为一个换行符- 与上面类似,
//C:\users
也会产生错误,因为\u
后面并没有跟着4个16进制数
boolean类型
Boolean(布尔)类型有两个值:false和true,用于判定逻辑条件。整型值和布尔值之间不能进行相互转换。
变量与常量
变量声明
- 变量名必须以字母开头并由字母或数字构成,java中的’字母’和’数字’的范围比大多数语言范围更大。字母包括表示字母的任何Unicode字符。
变量名长度基本没有限制 - 可以使用Character类的
isJavaIdentifierStart
和isJavaIdentifierPart方法来检查
哪些Unicode字符输入Java中的’字母’ - 尽管$是一个合法的Java字符,但不要在自己的代码中使用它。它只用在Java编译器或其他工具生成的名字中
- 不能使用单下划线’_’和Java保留字作为变量名
变量初始化
- Java中可以将变量声明放在代码中的任何地方,但尽可能靠近变量第一次使用的地方
从Java10开始,对于局部变量,如果可以从变量的初始值推断它的类型,就不再需要声明类型,只需要使用关键字var而无需指定类型:
var vacationDays = 12; //vacationDays是int类型的数据
var greeting = "Hello"; //greeting是String类型的数据
常量
利用关键字final
指示常量,例如final double PI = 3.14;
。final
表示变量只能被赋值一次,赋值后不能被更改。常量一般使用全大写。
枚举类型
详细内容见5.6
运算符
运算符优先级
运算符 | 结合性 |
---|---|
[] . ()(方法调用) | → |
! ~ ++ — +(一元运算) -(一元运算) ()(强制类型转换) new | ← |
* / % | → |
+ - | → |
<< >> >>> | → |
< <= > >= instanceof | → |
== != | → |
& | → |
^ | → |
∣ | → |
&& | → |
∣∣ | → |
?: | ← |
= += -= *= /= %= &= ∣= ^= <<= >>= >>>= | ← |
数学函数与常量
Math类 API文档
Math类提供了一些方法使整数有更好的安全性,比如10亿乘以3(1,000,000,000*3)的结果是-1294967296,如果调用方法Math.multiplyExact(1000000000,3)
,就会产生一个异常。这样就可以捕获异常或让程序终止,而不是用错误的结果继续运行下去。
数值类型转换
Math.round
可以对浮点数进行舍入运算,以便得到最接近的整数int x; x += 3.5;
是合法的,相当于(int)(x+3.5)
- 不要在boolean类型与任何数值类型进行强制类型转换,防止发生一些常见的错误。用到时可以使用条件表达式
b?1:0
字符串 String API
检测字符串是否相等
- 可以使用
equals
方法检测两个字符串是否相等:s.equals(t)
- 不区分大小写可以使用
equalIgnoreCase
:HeLlo.equalIgnoreCase("hello")
- 一定不要使用==运算符检测两个字符串是否相等
空串与Null串
如果判断一个字符串既不是null也不是空串,需要用以下条件:if( str != null && str.length() != 0 )
首先要检查str不为null,如果在null值上调用按方法,会出现错误。String常用API
| 方法声明 | 功能描述 | | :—-: | :—-: | |char charAt(int index)
| 返回给定位置的代码单元。除非对底层的代码单元感兴趣,否则不需要调用这个方法 | |int codePointAt(int index)
5
| 返回从给定位置开始的码点 | |int offsetByCodePoints(int startIndex, int cpCount)
5
| 返回从startIndex开始,cpCount个码点后的码点索引 | |int compareTo(String other)
| 按照字典顺序,如果字符串位于other之前,返回一个负数;如果字符串位于other之后,返回一个正数;如果两个字符串相等,返回0 | |IntStream codePoints()
8
| 将这个字符串的码点作为一个流返回。调用toArray将它们放在一个数组中 | |new String(int[] codePoints, int offset, int count)
5
| 用数组中从offset开始的count个码点构造一个字符串 | |boolean empty()
| 如果字符串为空或者由空格组成,返回true | |boolean blank()
11
| | |boolean equals(Object other)
| 如果字符串与other相等,返回true | |boolean equalsIgnoreCase(String other)
| 如果字符串与other相等(忽略大小写),返回true | |boolean startsWith(String prefix)
| 如果字符串以prefix开头或以suffix结尾,则返回true | |boolean endsWith(String suffix)
| | |int indexOf(String str)
| 返回与字符串str或码点cp匹配的第一个子串的开始位置。从索引0或fromIndex开始匹配。如果在原始字符串中不存在str,则返回-1 | |int indexOf(String str, int fromIndex)
| | |int indexOf(int cp)
| | |int indexOf(int cp, int fromIndex)
| | |int lastIndexOf(String str)
| 返回与字符串str或码点cp匹配的最后一个子串的开始位置。从原始字符串末尾或fromIndex开始匹配 | |int lastIndexOf(String str, int fromIndex)
| | |int lastIndexOf(int cp)
| | |int lastIndexOf(int cp, int fromIndex)
| | |int length()
| 返回字符串代码单元的个数 | |int codePointCount(int startIndex, int endIndex)
5
| 返回startIndex和endIndex-1之间的码点个数 | |String replace(CharSequence oldString, CharSequence newString)
| 返回一个新字符串。这个字符串用newString代替原始字符串中所有的oldString。可以用String或StringBuilder对象作为CharSequence参数 | |String substring(int beginIndex)
| 返回一个新字符串。这个字符串包含原始字符串中从beginIndex到字符串末尾或endIndex-1的所有代码单元 | |String substring(int beginIndex, int endIndex)
| | |String toLowerCase()
| 返回一个新字符串。这个字符串将原始字符串中的大写字母改为小写,或将原始字符串中的所有小写字母改成大写字母 | |String toUpperCase()
| | |String trim()
| 返回一个新字符串。这个字符串将删除原始字符串头部和尾部小于等于U+0020的字符(trip)或空格(strip) | |String strip()
11
| | |String join(CharSequence delimiter, CharSequence... elements)
8
| 回一个新字符串,用给定的定界符连接所所有元素 | |String repeat(int count)
11
| 返回一个字符,将当前字符串重复count次 |
构建字符串 StringBuilder
有时需要由较短的字符串构建字符串,如果采用字符串拼接的方式,效率会比较低。每次拼接字符串时,都会构建一个新的String对象,既耗时又浪费空间。使用StringBuilder类可以避免这个问题的发生。
如果需要用许多小段的字符串来构建一个字符串,首先要构建一个空的字符串构建器:StringBuilder builder = new StringBuilder();
调用append方法添加内容builder.append("hello").append("world");
构建字符串完成时调用toString方法,就可以得到包含构建器中字符序列的String对象String completedString = builder.toString();
StringBuilder类在Java5中引入。这个类的前身是StringBuffer,它的效率有些低,但允许多线程的方式添加或删除字符。如果所有字符串编辑操作都在单个线程中执行(通常都是这样),则应该使用StringBuilder。这两个类的API是一样的。
下面的API注释包含了StringBuilder类中的重要方法
方法名 | 说明 |
---|---|
StringBuilder() |
构造一个空的字符串构建器 |
int length() |
返回构建器中的代码单元数量 |
StringBuilder append(String str) |
追加一个字符串并返回this |
StringBuilder append(char c) |
追加一个代码单元并返回this |
StringBuilder appendCodePoint(int cp) |
追加一个码点,并将其转换为一个或两个代码单元并返回this |
void setCharAt(int i, char c) |
将第i个代码单元设置为c |
StringBuilder insert(int offset, String str) |
在offset位置插入一个字符串并返回this |
StringBuilder insert(int offset, char c) |
在offset位置插入一个代码单元并返回this |
StringBuilder delete(int startIndex, int endIndex) |
删除偏移量从startIndex到endIndex-1的代码单元并返回this |
String toString() |
返回一个与构建器或缓冲器内容相同的字符串 |
输入与输出
读取输入 Scanner
首先构造一个与“标准输入流”System.in关联的Scanner对象:Scanner in = new Scanner(System.in);
Scanner类中常用方法:
方法名 | 说明 |
---|---|
String nextLine() |
读取输入的下一行内容 |
String next() |
读取输入的下一个单词(以空格作为间隔符) |
int nextInt() |
读取并转换下一个表示整数的字符序列 |
double nextDouble() |
读取并转换下一个表示浮点数的字符序列 |
boolean hasNext() |
检测输入中是否还有其他单词 |
boolean hasNextInt() |
检测是否还有下一个表示正数的字符序列 |
boolean hasNextDouble() |
检测是否还有下一个表示浮点数的字符序列 |
从控制台读取密码:
Console cons = System.console(); //Java6引入了Console类
String username = cons.readLine("User name:");
char[] passwd = cons.readPassword("Password:");
格式化输出
转换符 | 类型 | 示例 | 转换符 | 类型 | 示例 | |
---|---|---|---|---|---|---|
d | 十进制整数 | 159 | s | 字符串 | hello | |
x | 十六进制整数 | 9f | c | 字符 | H | |
o | 八进制整数 | 237 | b | 布尔 | true | |
f | 定点浮点数 | 15.9 | h | 散列码 | 42628b2 | |
e | 指数浮点数 | 1.59e+01 | tχ或Tχ | 日期时间(T强制大写) | 已过时,应使用java.time 类 |
|
g | 通用浮点数(e和f中较短的一个) | - | % | 百分号 | % | |
a | 十六进制浮点数 | 0x1.fccdp3 | n | 与平台有关的行分隔符 | - |
标识 | 目的 | 示例 |
---|---|---|
+ |
打印正数和负数的符号 | +3333.33 |
空格 |
在正数之前添加空格 | 丨 3333.33丨 |
0 |
数字前面补0 | 003333.33 |
- |
左对齐 | 丨3333.33 丨 |
( |
将负数括在括号内 | (3333.33) |
, |
添加分组间隔符 | 3,333.33 |
#(f格式) |
包含小数点 | 3,333. |
#(x或0格式) |
添加前缀0x或0 | 0xcafe |
$ |
指定要格式化的参数索引,如%1$d %1$x 按对应进制打印第一个参数 |
159 9F |
< |
格式化前面说明的数值,如%d%<x 将以十进制和十六进制打印同一个数值 |
159 9F |
可以使用printf
输出格式化后的内容,如System.out.printf("name:%s,age:%d",name,age)
也可以使用静态的String.format
创建格式化后的字符串,而不输出,如String message = String.format("name:%s,age:%d",name,age)
文件输入与输出
要读取文件,需要构造一个Scanner对象:Scanner in = new Scanner(Paths.of("D:\\myfile.txt"),StandardCharsets.UTF_8);
要写入文件,需要构造一个PrintWriter对象:PrintWriter out = new PrintWriter("myfile.txt",StandardCharsets.UTF_8);
数组
Java内存划分
- 栈(Stack):存放方法中的局部变量,方法一定在栈中运行
- 堆(Heap):new出来的都在堆中
- 方法区(Method Area):存储.class相关信息,包含方法的信息
- 本地方法栈(Native Method Area):与操作系统相关
- 寄存器(PC Register):与CPU相关