数据类型
在java中一共有8种基本类型,其中有4种整型,2种浮点类型,1种字符类型, 1种布尔类型。
- 整型
整型用于表示没有小数部分的数值,允许是负数。
- int 4 字节 -2 147 483 648 ~ 2 147 483 647 (刚刚超过20亿)
- short 2 字节 -32 768 ~ 32 767
- long 8 字节 -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807
- byte 1 字节 -128 ~ 127
- 浮点类型
浮点类型用于表示有小数部分的数值。
- float 4 字节 大约 +/- 3.402 823 47E+38F (有效位数6~7位)
- double 8 字节 大约 +/- 1.797 693 134 862 315 70E+308 (有效位数为15位)
float类型的数值有一个后缀F或f(3.14F), 没有后缀F的浮点数值(3.14)总是默认位double类型。
浮点类型中有三个特殊的浮点数值表示溢出和出错的情况:
- 正无穷大 (Double.POSITIVE_INFINITY),
- 负无穷大 (Double.NEGATIVE_INFINITY),
- NaN 非数字 (Double.NaN)
-
char 类型
用于表示Unicode编码的代码单元, 在java种,char类型描述了UTF-16编码种的一个代码单元。
建议不要在代码种使用char类型,最好将字符串作为抽象数据类型处理。 -
boolean类型
boolean类型有两个值: false 和 true,用来判定逻辑条件。整型值和布尔值之间不能进行相互转换。
变量
- 申明变量
在java中每个变量都有一个类型,在申明变量时,先指定变量类型,然后是变量名。
double salary;
int vacationDays;
long earthPopulation;
boolean done;
- 变量初始化
声明变量之后,必须用赋值语句对变量进行显示初始化,使用未初始化的变量值,java编译器会报错。
- 对已声明的变量进行初始化赋值
int vacationDays;
vacationDays = 12;
- 声明变量和初始化在一行中
int vacationDays = 12;
double salary = 65000.0;
常量
使用关键字final指示常量,表示这个变量只能被赋值一次,之后就不能再更改了,习惯上常量名使用全大写。
- 使用final在类方法中定义常量
public class Constants
{public static void main(String[] args){final double CM_PRE_INCH = 2.54;double paperWidth = 8.5;double paperHeight = 11;System.out.println("Paper size in centimeters: " + paperWidth * CM_PRE_INCH + " by " + paperHeight * CM_PRE_INCH);}
}
- 使用static final在类中定义类常量
public class Constants2
{public static final double CM_PRE_INCH = 2.54;public static void main(String[] args){double paperWidth = 8.5;double paperHeight = 11;System.out.println("Paper size in centimeters: " + paperWidth * CM_PRE_INCH + " by " + paperHeight * CM_PRE_INCH);}
}
枚举类型
变量的取值在一个有限额集合内时就可以自定义枚举类型来声明变量。
// 自定义枚举类型
enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };// 声明枚举变量, 只能为Size中的某个值,或者null
Size s = Size.MEDIUM;
运算符
- 算术运算符 + - * /
- 当参与/运算的两个操作数都是整数时,表示整数除法;否则表示浮点除法。
- 整数的求余操作用%表示。
- 数学函数
使用Math类中的方法进行数学计算。
// 计算平方根
double x = 4;
double y = Math.sqrt(x);
System.out.println(y); // prints 2.0// 数学常量
Math.PI
Math.E
- 数值类型之间的转换
当用一个二元运算符连接两个值时,先要将两个操作数转换为同一种类型,然后再进行计算。
- 如果两个操作数中有一个是double类型,另一个操作数就会转换为double类型。
- 否则,如果其中一个操作数是float类型,另一个操作数将会转换为float类型。
- 否则,如果其中一个操作数是long类型,另一个操作数将会被转换为long类型。
- 否则,两个操作数抖将被转换为int类型。
- 强制类型转换
- 将浮点数转换为整数
// 舍去浮点位
double x = 9.997;
int nx = (int) x; // prints 9// 使用四舍五入
double x = 9.997;
int nx = (int) Math.round(x); // prints 10;
- 结合赋值与自增自减运算符
- 在赋值中使用二元运算符
x += 4;
// 等价于
x = x + 4;
- 自增自减
int m = 7;
int n = 7;
int a = 2 * ++m; // a is 16, m is 8
int b = 2 * n++; // b is 14, n is 8
- 关系和布尔运算符
-
关系运算符
相等: ==
不等: !=
小于: <
大于: >
小于等于: <=
大于等于: >= -
布尔运算符
逻辑与运算符:&&
逻辑或运算符:|| -
三元操作符 ?:
x < y ? x : y
-
位运算符
位与:&
位或:|
异或:^
取反:~
左移:<<
右移:>> -
括号与运算符优先级
如果不使用括号,就按照给出的运算符优先级次序进行计算,同一个级别的运算符按照从左到右的次序进行计算(但右结合运算符除外)
a && b || c 等价于 (a && b) || c
a += b += c 等价于 a += (b += c)
字符串
java字符串就是Unicode字符序列。java没有字符串类型,而是在标准类库中提供了一个预定义类String。每个用双引号括起来的字符串都是String类型的一个实例。
String e = ""; // empty string
String greeting = "Hello";
- 子串
String greeting = "Hello";
String s = greeting.substring(0, 3); // s is "Hel"
- 拼接
String expletive = "Expletive";
String PG13 = "deleted";
String message = expletive + PG13; // message is "Expletivedeleted"int age = 13;
String rating = "PG" + age; // rating is "PG13"String all = String.join(" / ", "S", "M", "L", "XL"); // all is "S / M / L / XL"
String repeated = "java".repeat(3); // repeated is "JavaJavaJava"
- 不可变字符串
String类没有提供修改字符串中某个字符的方法, String类型对象被称为是不可变的。
// 通过拼接替换字符串
String greeting = "Hello";
greeting = greeting.substring(0,3) + "p!"; // greeting is "Help!"
- 检测字符串是否相等
不要使用 == 检测字符串相等,因为 == 只能确定两个字符串是否存放在同一个位置上。
String s = "s";
String t = "t";
s.equals(t); // falseString greeting = "Hello";
"Hello".equals(greeting); // true;// 不区分大小写进行比较
"Hello".equalsIgnoreCase("hello"); // true;
- 空串与Null串
空串""是长度位0的字符串, 检测字符串为空的方法:
if(str.length() == 0) 或 if(str.equals(""))
null表示目前没有任何对象与该变量关联,检测一个字符串是否位null:
if(str == null)
检测一个字符串既不是null, 也不是空串:
if(str != null && str.length() != 0)
- 构建字符串
如果需要用许多小段的字符串构建一个字符串则使用字符串构建器更高效
StringBuilder builder = new StringBuilder();
builder.append(ch); // appends a single character
builder.append(str) // appends a string
String completedString = builder.toString(); // 构建完成时,调用toString方法得到字符串对象
输入与输出
- 读取输入
// 构造与标准输入流System.in 关联的Scanner对象
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.nextInt();// 使用Console类读取密码
Console cons = System.console();
String username = cons.readLine("User name: ");
char[] passwd = cons.readPassword("Password: ");
- 格式化输出
double x = 10000.0 / 3.0;
System.out.print(x); // 3333.3333333333335
System.out.printf("%8.2f", x) // 3333.33
// 提供多个参数
System.out.printf("Hello, %s. Next year, you'll be %d", name, age);
// 打印时间
System.out.printf("%tc", new Date());
格式说明符:
- d 十进制整数
- x 十六进制整数
- f 定点浮点数
- e 指数浮点数
- s 字符串
- c 字符
- tx 日期时间
- 文件输入与输出
// 读入文件
Scanner in = new Scanner(Path.of("myfile.txt"), StandardCharsets.UFT_8);
// 写入文件
PrintWriter out = new PrintWriter("myfile.txt", StandardCharsets.UFT_8);
控制流程
- 块作用域
块是由若干条java语句组成的语句,并用一对大括号括起来。
- 块确定了变量的作用域
- 一个块可以嵌套在另一个块中
- 不能在嵌套的两个块中声明同名的变量。
- 条件语句
- if 语句: if (condition) statement
- if else 语句: if(condition) statement1 else statement2
- if else if 语句: if(condition1) statement1 else if(condition2) statement2
- 循环语句
- while (condition) statement
- do statement while (condition)
- for (int i = 1; i <= 10; i++) System.out.println(i);
- switch 语句
case 标签可以是以下类型:
- char, byte, short 或 int 的常量表达式
- 枚举常量
- 字符串字面量
Scanner in = new Scanner(System.in);
System.out.print("Select an option (1, 2, 3, 4) ");
int choice = in.nextInt();
switch (choice) {case 1:...break;case 2:...break;case 3:...break;default:// bad input...break;
}
- 中断控制流程语句
- break 语句
用于跳出当前循环,或者跳到指定的label
while (year <= 100) {balance += payment;double interest = balance * interestRate / 100;balance += interest;if (balance >= goal) break;years++;
}
- continue 语句
用于跳过本次循环,到循环首部继续进行下一次循环
Scanner in = new Scanner(System.in);
for (count = 1; count <= 100; count++)
{System.out.print("Enter a number, -1 to quit:");n = in.netInt();if(n < 0) continue;sum += n;
}
大数
如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中两个类:BigInteger 和 BigDecimal
- valueOf 将普通数值转化为大数
BigInteger a = BigInteger.valueOf(100);
- new BigInteger 将字符串类型的参数转换为大数
BigInteger reallyBig = new BigInteger("2222322343454545656565676767676700")
- 大数运算: add, subtract, multiply, divide, mod, sqrt, compareTo
// 使用add 方法进行求和运算
BigInteger c = a.add(b); // c = a + b;
// 使用multiply 方法进行乘法运算
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2))); // d = c * (b+2)
数组
数组是一种数据结构,用来存储同一类型值的集合。
- 声明数组
// 声明整型数组 a
int[] a;// 声明并初始化一个可以存储100个整数的数组
int[] a = new int[100];
var a = new int[100];// 创建数组并同时提供初始值
int[] smallPrimes = {2, 3, 5, 7, 11, 13};
String[] authors = {"James Gosling","Bill Joy","Guy Steele",
};//使用匿名数组重新初始化变量
smallPrimes = new int[] {17, 19, 23, 29, 31, 37};// 创建长度为0的数组
int[] a = new int[0];
int[] b = new int[] {};
- 访问数组元素
创建一个数字数组时,所有元素都初始化为0, boolean数组的元素会初始化为false, 对象数组的元素则初始化为一个特殊值null,
表示这些元素还未放任何对象。
- 通过for循环访问数组元素
int[] a = new int[100];
for (int i = 0; i < 100; i++){a[i] = i; // fill the array with numbers 0 to 99
}// 将字符串数组初始化未空串
String[] names = new String[10];
for (int i = 0; i < 10; i++) names[i] = "";// 使用array.length 获得数组中元素个数
int[] a = new int[100];
for (int i = 0; i < a.length; i++) {System.out.println(a[i]);
}
- for each 循环访问数组
int[] a = {1, 2, 3, 4, 5};
for (int element : a) {System.out.println(element);
}
- 数组拷贝
- 两个数组变量引用同一个数组
int[] smallPrimes = {17, 19, 23, 29, 31, 37};
int[] luckyNumbers = smallPrimes;
luckyNumbers[5] = 12; // now smallPrimes[5] also 12
- 拷贝数组的值到新数组中
int[] luckyNumbers = {17, 19, 23, 29, 31, 37};
// 实现数组值的全部复制
int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length);
// 扩容数组
luckyNumbers = Arrays.copyOf(luckyNumbers, 2 * luckyNumbers.length);
// 裁切数组
luckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length-2);
- 命令行参数
每一个java应用程序都有一个带String arg[]参数的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].equals("-g")){System.out.print("Goodbye,")}// print other command line argumentsfor (int i = 1; i < args.length; i++){System.out.print(" " + args[i]);}System.out.println("!");}
}
=> java Message -g cruel world // print: Goodbye, cruel world!
- 数组常用静态方法
- static String toString(xxx[] a) 返回包含a中元素的一个字符串,如"[1, 2, 3, 4]"
- static void sort(xxx[] a) 使用优化的快速排序算法对数组进行排序
- static xxx[] copyOf(xxx[] a, int end) 返回与a类型相同的一个数组
- static xxx[] copyOfRange(xxx[] a, int start, in end) 返回从数组索引start开始到end结束,不包括end的新数组。
- static void fill(xxx[] a, xxx v) 将数组的所有数据元素设置为v
- static boolean equals(xxx[] a, xxx[] b) 如果两个数组大小相同,并且下标相同的元素都对应相等,返回true。
- static int binarySearch(xxx[] a, xxx v) 使用二分查找算法在有序数组中查找值v,如果找到值v,则返回相应的下标,否则返回一个负数值r。
- 多维数组
- 声明和初始化二维数组
double[][] balances;
balances = new double[10][10];int[][] magicSquare = {{16, 3, 2, 13},{5, 10, 11, 8},{9, 6, 7, 12},{4, 15, 14, 1}
};
- 访问二维数组
// 通过下标访问
int a = magicSquare[1][2];// for each 循环
for (double[] row : a) {for (double value : row){// do something with value}
}
// 打印二维数组内容
System.out.println(Arrays.deepToString(a));