以上整理来自《Java核心技术 卷I》
- 注释
- 数据类型
- 变量与常量
- 运算符
- 字符串
- 输入输出
- 控制流
- 大数
- 数组
** 一个简单的Java应用程序**
- 访问修饰符:用于控制程序的其他部分对这段代码的访问级别。
- 类名:以大写字母开头
- 源代码的文件名必须与公共类的名字相同,并用.java作为扩展名
- 运行已编译的程序时,Java虚拟机总是从指定类中的main方法的代码开始执行,因此为了代码能够执行,在类的源文件中必须包含一个main方法。
- 一对大括号表示方法体的开始和结束;每个语句必须以";"结束。
- 点号(.)用于调用方法。通用语句为:
object.method(parameters)
注释
- //
- /* */ 多用于更长的注释,但是不可以嵌套
- /** */ 可用来自动生成文档
数据类型
共有8种:4种整型、2种浮点类型、1种字符类型char、1种用于表示真值的布尔类型boolean
1. 整型
类型 | 存储需求 | 取值范围 | 应用场景 |
---|---|---|---|
int | 4字节 | -2147483648 ~ 2147483647 | 最常用 |
short | 2字节 | -32768 ~ 32767 | 特定应用场景:底层文件处理或存储空间很宝贵的大数组 |
long | 8字节 | -9223372036854775808 ~ 9223372036854775808 | 数量级大 |
byte | 1字节 | -128 ~127 | 特定应用场景:底层文件处理或存储空间很宝贵的大数组 |
长整型(long)数值后有一个后缀L或l
2. 浮点类型
类型 | 存储需求 | 取值范围 | 应用场景 |
---|---|---|---|
float | 4字节 | 有效位数6 ~ 7 位 | 应用少,一般为需要单精度数的库、需要存储大量数据 |
double | 8字节 | 有效位数 15 位 | 常用 |
float类型的数值有一个后缀F或f,没有后缀F的默认为double,double后也可以添加D或d。
溢出和出错情况的三个特殊的浮点数值:
- 正无穷大————常量 Double.POSITIVE_INFINITY
- 负无穷大————常量 Double.NEGATIVE_INFINITY
- NaN(非数字)————常量:Double.NaN
非数值的值都认为不相同的
**舍入误差:浮点数值无法精确表示分数1/10,可使用BigDecimal类 **
3. char类型
“ ”——字符串
‘ ’——字符
常见转义字符:
转义序列 | 名称 | Unicode值 |
---|---|---|
\b | 退格 | \u0008 |
\t | 制表 | \u0009 |
\n | 换行 | \u000a |
\r | 回车 | \u000d |
* | 双引号 | \u0022 |
\‘ | 单引号 | \u0027 |
\ | 反斜杠 | \u005c |
4. boolean类型
boolean类型有两个值:false 和 true ,用来判定逻辑条件。
整型值和布尔值之间不能进行相互转换
变量与常量
1. 声明变量
每一个变量都有一个类型,在声明变量时,先指定变量的类型,然后是变量名,以分号;结束语句。
2. 变量初始化
声明一个变量后,必须用赋值语句对变量进行显式初始化,不能使用未初始化的变量值。
错误:
int num;
System.out.println(num);
正确:
int num = 12;
System.out.println(num);
在Java种,变量的声明尽可能靠近变量第一次使用的地方
3. 常量
final: Java中利用关键字final指示常数
关键字final表示这个变量只能被赋值一次,一旦被赋值后就不能够再更改。
习惯上变量名使用全大写
public class Constant
{
{
final doubel CH_PER_INCH = 2.54; //常量
double Width = 10.1;
double Heiht = 11;
System.out.println("It's width is " + width + "and is height is " +
Height);
}
}
static/public final:
类常量(class constant):可再一个类的多个方法中使用
常变量定义在方法外部,若被声明为public则其他类的方法也可以使用这个常量
public class Constant
{
public static final double CH_PER_INCH = 2.54; //类常量
{
double Width = 10.1;
double Heiht = 11;
System.out.println("It's width is " + width + "and is height is " +
Height);
}
}
4.枚举类型
有时候变量的取值只在一个有限的集合内。
enum Size{SMALL,MEDIUM,LARGE,EXTRA_LARGE};
Size类型的变量只能存储在这个类型声明中给定的某个枚举值,或者特殊值null,null表示这个变量没有设置任何值。
运算符
运算符用于连接值。
算术运算符
- 当参与 / 运算的两个操作数都是整数时,表示证书除法,否则为浮点除法。
- 整数的求余操作(取模)用 % 表示。
整数被0除将会产生一个异常,而浮点数被0除将会得到无穷大或NaN结果
数学函数与常量
静态方法——Math.sqrt(求平方根)
代码 | 方法 |
---|---|
Math.sqrt(x) | 求平方根 |
Math.pow(x,a) | 求x的a次幂 |
floorMod(x,a) | 使x%a的结果>=0 |
Math.sin\cos\tan... | 三角函数 |
Math.exp | e为底的指数函数 |
Math.log\log10 | 以10为底的对数 |
Math。PI | Π |
Math.E | e常量 |
不必在数学方法名和常量名前添加前缀"Math“的方法:
import static java.lang.Math.*;
System.out.println("The squart root of \u30C0 is " + sqrt(PI));
数值类型之间的转换
----------实线箭头为无信息丢失的转换,虚线箭头为有精度损失的转换-----------
当用一个二元运算符连接两个值时,先要将两个操作数转换为同一种类型,然后再进行计算。
- 若有一个为double,则另一个转换为double
- 有float/long 为 float/long
- 否则都为 int
强制类型转换
强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟带转换的变量名。
如浮点型转换为整型:
double x = 9.79;
int nx = int(x);//直接截断小数部分
int mx = (int)Math.round(x);//进行舍入计算
如果试图将一个数值从一种类型强制转换为另一种类型,而且超出目标类型的表示范围,结果会截断成一个完全不同的值。
结合赋值和运算符
x += 4 => x = x +4
一般来说,要把运算符放在=号左边
自增与自减运算符
运算符要改变的是变量的值,所以不能应用在数值本身
前缀形式会先完成+1;
后缀形式会使用变量原来的值;
关系与boolean运算符
与 | && |
---|---|
或 | |
非 | != |
三元 | 条件?真结果:假结果 |
位运算符
处理整型类型时,可以直接对组成整数的各个位完成操作。这意味着可以使用掩码技术得到整数的各个位。
位运算符:
and | & |
---|---|
or | |
xor | ^ |
not | - |
位模式右移 | >> |
位模式左移 | << |
0填充高位 | >>> |
括号与运算符级别
括号优先
Java不使用逗号运算符
字符串
从概念上讲,Java字符串就是Unicode字符序列。java没有内置字符串类型,但是提供一个String预定义类。每个用双引号括起来的字符串都是String类的一个实例。
子串
String类的substring方法可以从一个较大的字符串提取一个子串:
String greeting = "Hello";
String s = greeting.substring(0,3);
结果为 s = “Hel”
substring的一个优点:容易计算子串的长度。
拼接
String str1 = "What";
String str2 = "ever";
String str3 = str1 + str2;
运行结果为:“Whatever” (拼接间没有空格,需要自行在字符串内添加)
且当将一个字符串和一个非字符串的值拼接时,后者会转换成字符串
如果需要把多个字符串放在一起,用一个界定符分隔,可以使用静态join方法:
String all = String.join("/","S","M","L","XL");
输出结果为:“S / M / L / XL"
如果需要重复某段字符串,可以使用repeat:
String repeated = "Java".repeat(3);
//repeated is "JavaJavaJava"
不可变字符串
直接修改字符串的方法:子串 + 拼接
例如:把“Hello”改成“Help!"
greeting = greeting.substring(0,3) + "p!";
不可修改Java字符串中的单个字符,所以在Java文档中将String类对象称为不可变的,但是可以修改字符串变量。
- 不可变变量的优势:编译器可以让字符串共享
- Java字符串大致类似与char* 指针
检测字符串是否相等
可以使用equals方法检测两个字符串是否相等。
检测s与t是否相等:
s.equals(t) //区分大小写
若相等返回true,否则返回false;s和t可以是字符串或变量。
"Hello".equalsIgnoreCase("hello");//不区分大小写
注意:不要用 == 运算检测两个字符串是否相等
空串与Null串
空串:为长度为0的字符串,有自己的串长度(0)和内容(空)
检查是否为空串:
if (str.length() == 0);
or
if (str.equals(""));
null:表示目前没有任何对象与该变量关联
检查是否为null:
if (str == null)
检查既不是null也不是空串:
if (str != null && str.length() != 0);
码点与代码单元 ?!
码点是指一个编码表中的某个字符对应的代码值。Unicode的码点分为17个代码级别,第一个级别是基本的多语言级别,码点从U+0000——U+FFFF,其余的16个级别从U+10000——U+10FFFF,其中包括一些辅助字符。
代码单元:基本的多语言级别,每个字符用16为表示代码单元,而辅助字符采用连续的一对连续代码单元进行编码。
StringAPI
API:Java应用编程接口,每一个API的注释都以类名开始,如 java.LANG.String。类名之后是一个或多个方法的名字、解释和参数描述。
构建字符串
当有时需要由较短的字符串构建字符串,若采用字符串拼接的方式来达到这个目的,效率会比较低。此时可以使用StringBulider类:
- 首先,构建一个空的字符串构建器
StringBulider = new StringBulider();
- 每当需要添加一部分内容时,就调用append方法
bulider.append(ch);
bulider.append(str);
- 在字符串构建完成时就调用toString方法,可以得到一个String对象,其中包含了构建器中的字符序列。
构建器(bulider): 构建器是一种设计模式,通常用于创建复杂对象。它允许你通过设置不同的属性来构建一个对象,而不需要在构造函数中传递大量的参数。构建器模式通常包含以下部分:
- Builder 接口:定义了用于创建复杂对象的方法。
- ConcreteBuilder 类:实现了 Builder 接口,并提供了存储内部表示的方法。
- Director 类:负责使用 Builder 接口来创建对象。
- Product 类:表示被构建的复杂对象。
使用构建器模式可以使得代码更加清晰,并且易于维护。例如,如果你有一个包含多个属性的对象,使用构建器可以避免构造函数参数列表过长的问题。
字符序列: 字符序列通常指的是一个字符的序列,例如字符串。在Java中,String 类和 StringBuilder 类都是字符序列的实现。字符序列可以包含任意数量的字符,并且可以进行各种操作,如连接、比较、搜索等。
- String 类:是一个不可变的字符序列,一旦创建就不能修改。每次修改操作都会生成一个新的字符串对象。
- StringBuilder 类:是一个可变的字符序列,可以修改其内容而不生成新的对象,因此对于频繁修改字符串内容的场景更加高效。
输入与输出
读取输入
标准输入流:System.in
- 首先需要构造一个与”标准输入流“System.in关联的Scanner对象。
Scanner in = new Scanner(System.in);
- 现在可以使用Scanner类(定义在java.util包中) 的各种方法读取输入
*当使用的类不是定义在基本java.lang包中,一定要使用import指令导入相应的包。
String name = in.nextline(); //读取一行输入
String firstname = in.next(); //读取一个单词,以空白符作为分隔符
int age = in.nextInt();//读取一个整数
double height = in.nextDouble();//读取一个浮点数
- 补充:因为输入是可见的,所以Scanner类不适用于从控制台读取密码。可使用Console类来实现。
Console cons = System.console();
String username = cons.readLine("User name:");
char[] passwd = cons.readPassword("Password:");//安全起见,返回的密码存放在一个字符数组中
//对密码处理完成后应该立马用一个填充值覆盖数组元素
// Console对象必须每次读取一行输入,而没有能够读取单个单词或数组的方法,不如Scanner方便。
格式化输出
标准化输出:System.out.println
-
用于printf的转换符
-
printf方法中日期与时间的格式化选项
(略) -
printf格式说明符的语法图
文件输入与输出 ?!
- 想读取一个文件,需要先构造一个Scanner对象
Scanner in = new Scanner(Path.of("mafile.txt"),StandardCharsets.UTF_8);
现在就可以利用Scanner方法对文件进行读取
- 写入文件就需要构造一个PrintWriter对象。在构造器中需要提供文件名和字符编码。
PrintWriter out = new PrintWriter("myfile.txt",StandCharsets.UTF_8);
//如果文件不存在,则创建该文件
//可以像输出到System.out一样使用print、println以及printf命令。
如果用一个不存在的文件构造一个Scanenr,或者用一个无法创建的文件名构造一个PrintWriter,就会产生异常。Java编译器认为这些异常笔”被零除“异常更严重。
控制流程
快作用域
块:即复合语句,是指由若干条Java语句组成的语句,并用一对大括号括起来。块确定了变量的作用域。一个块可以嵌套在另一个块中。
但是不能在嵌套的两个块中声明同名的变量。
条件语句
if (condition){
statement1;
statement2;
}
if(condition1){
statement1;
statement2;
}
if (condition2)4{
statement3;
}
else //else子句与最邻近的if构成一组,与第二个if配对
{
statement;
}
循环
while (condition) statement
如果循环条件为false,则一次都不执行
do statement while (condition)
至少执行一次
确定循环
for (初始化;退出条件;如何更新计数器);
循环内容;
多重选择:switch语句
使用场景:处理多个选项
switch(choice)
{
case 1:
//类型可以是char、byte、short、int的常量表达式
//也可以是枚举常量、字符串字面量
...
break;
case 2:
...
break;
...
default:
...
break;
}
switch语句将从选项值相匹配的case标签开始执行,直到遇到break语句,或者执行到switch语句的结束为止。如果没有相匹配的case标签,而由default子句,则执行default语句。
- 中断控制流程的语句
break:跳出循环
continue:将控制转移到最内层循环的首部
大数
如果基本的整数和浮点数精度不能满足需求,则可以使用java.math包中的两个类:BigInteger和BigDecimal。这两个类可以处理任意长度数字序列的数值。
- BigInteger可以实现任意精度的整数运算
- BigDecimal可以实现任意精度的浮点数运算
**不能使用熟悉的算术运算符(+或*)处理大数,而是使用大数类中的add和multipy方法。
数组
声明数组
数组是一种数据结构,存储相同类型值的序列。通过下标(index,索引)可以访问数组中的每一个值。
int[] a; //声明变量——整型数组a,但是没有将a初始化为真正的数组
int[] a = new int[n];//声明并初始化了一个可以存储n个整数的数组
一旦创建数组就不能改变他的长度,但可以改变单个数组元素。
数据列表——可扩展数组的大小
创建数组对象并同时提供初始值:
in[] smallPrimes = {2,3,4,5,6,7};
声明匿名数组:
new int[]{2,3,4,5}
这会分配一个新数组填入大括号中提供的值,会统计初始值个数,并相应地设置数组大小。还可以使用这种语法重新初始化一个数组而无需创建新变量。
·smallPrimes = new int[]{2,3,4,5,6,7};
在java中允许由长度为0的数组。
访问数组元素
创建一个数字数组时,所有元素都初始化为0;Boolean数组的元素会初始化为false;对象数组的元素初始化为一个特殊值null,表示这些元素还未放任何对象,若希望这个数组包含空船,必须为元素指定空串('')。
array.length //获得数组的元素个数
for each循环
for each循环用来依次处理数组(或者其他元素集合)中的每个元素,而不必考虑指定下标。
//for (variable:collection) statement
//collection这一集合表达式必须是一个数组或者时一个实现Iterable接口的类对象
for (int element : a)
System.out.println(element);
补充:打印数组中的所有值——调用Arrays.toString(a):
System.out.println(Arrays.toString(a));
数组拷贝
在Java中允许将一个数组变量拷贝到另一个数组变量。这时,两个变量将引用同一个数组。
int[] luckyNumber = smallPrimes;
luckyNumber[5] = 12; //此时smallPrimes[5]也为12
若要将一个数组的所有值拷贝到一个新的数组中,则使用Arrays类的copyOf方法:
int[] copyNumber = Arrays.copyOf(luckyNumber,luckyNumber.length);
//第二个参数是新数组的长度,可用来增加数组大小:
luckyNumber = Arrays.copyOf(luckyNumber,2*luckyNumber.length);
如果数组元素是数值型,则额外的元素将被赋值为0;如果是布尔型,则将赋值为false;若长度小于原始数组的长度,则只拷贝前面的值。
命令行参数 ?!
数组排列
对数值型数组进行排列——Arrays类的sort方法
Arrays.sort(a)
补充:
生成随机数:Math.random方法将返回一个0到1之间(包含0,不包含1)的随机浮点数,用n乘以这个浮点数就可以得到从0到n-1之间的一个随机数。
多维数组:数组的数组
多维数组将使用多个下标访问数组元素,适用于表示表格或更加复杂的排列形式。
二维数组balances
初始化:
balances = new double[NYEARS][NRATES];
若知道数组元素则可以不用调用new,直接使用简写形式对多维数组进行初始化。
for each循环语句不能自动处理二维数组的每一个元素,需要两个嵌套循环
for (doubel[] row:a)
for(double value :row)
do something with value
快速打印二维数组的数据元素列表:
System.out.println(Arrays.deepToString(a));