2 Java 基础
2.1 变量与数据类型
变量
-
按被声明的位置划分:
- 局部变量:方法或语句块内部定义的变量
- 成员变量:方法外部、类的内部定义的变量
注意:类的外面不能有变量的声明
-
按数据类型划分:
- 基本数据类型变量
-
引用数据类型变量
基本数据类型
类型 | 占用内存 (byte) | 取值范围 | 默认值 |
---|---|---|---|
整数型 int | 4 | [-2^31, 2^31-1] (20亿) | 0 |
短整数型 short | 2 | [-2^15, 2^15-1] | 0 |
长整数型 long | 8 | [-2^63L, 2^63-1L] | 0 |
字节型 byte | 1 | [-128, 127] | 0 |
浮点型 float | 4 | [-3.40292347E+38, 3.40292347E+38] | 0.0f |
双精度型 double | 8 | [-1.79769313486231570E+308, 1.79769313486231570E+308] | 0.0d |
布尔型 boolean | 1 | true, false | false |
字符型 char | 2 | ‘\u0000 - \uffff’ | ‘\u0000’ |
注意:
-
float
类型,需要加上f/F
后缀 -
long
类型,需要加上l/L
后缀 -
浮点数比较方法:判断差的绝对值是否小于一个很小的数
double r = Math.abs(x - y); // 再判断绝对值是否足够小: if (r < 0.00001) { // 可以认为相等 // ... } else { // 不相等 // ... }
引用数据类型
- 字符串 String
- 数组 array
- 类 class
- 接口 interface
类型转换
-
自动类型转换:小->大
byte, short, int -> float -> long -> double
注意:byte,short,int 不会互相转换,三者在计算时会转换成 int 类型
-
强制类型转换:大->小,要加上强制转换符,可能造成精度降低/数据溢出
long l = 100L; int i = (int) l;
-
int, char, unicode
// 字母'A'的Unicodde编码是65 int i = 'A'; char c1 = 'A'; char c2 = 65; char c3 = '\u0041'; // 十六进制0041 = 十进制65 System.out.println(i); // 65 System.out.println(c1); // A System.out.println(c2); // A System.out.println(c3); // A
二进制
计算机内的二进制数值是以补码形式表示的:
- 正数的补码:和原码形式相同
- 负数的补码是:将该数绝对值的二进制形式,按位取反再加 1
=> 最高位是符号位:0 表示正数;1 表示负数
使用补码原因:
- 可以将符号位和其它位统一处理
- 减法也可按加法来处理
- 如果最高位(符号位)有进位,则进位被舍弃 (溢出?)
e.g., 10 = 00000000 00000000 00000000 00001010
-10 = 11111111 11111111 11111111 11110110
八进制与十六进制
-
Java中的八进制要以 0 开头
-
Java中的十六进制要以 0x 或 0X 开头
ASCII码
- 空格 - 32
- ‘0’ - 48
- ‘A’ - 65
- ‘a’ - 97
可以用 \八进制数字
来表示,e.g.,
System.out.println("\142"); // a=97(10)=1100001(2)=142(8)
2.2 权限修饰符
权限修饰符 | 同类 | 同包 | 子类 | 不同包,非子类 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
2.3 运算符
-
算术运算符:+, -, *, /, %, ++, –
注意:++/–为变量后缀时,先执行当前语句的其他操作,再对此变量加 1
-
赋值运算符:=, +=, -=, *=, /=, %=
-
关系运算符:==, !=, <, >, <=, >=
-
逻辑运算符:&, |, !, ^(异或), &&(短路与), ||(短路或)
-
三目运算符:[boolean 类型表达式] ? [表达式1 for true] : [表达式2 for false]
-
字符串连接运算符:+
String s1 = "1"+2+3); // 123 String s2 = 1+2+"3"; // 33
-
位移运算符:
- << 左移运算符:左移,右补0
- >> 右移运算符:右移,左补符号位
- >>> 无符号右移运算符:右移,左补0
注:n是偶数时,
n<<1
相当于n*2
,n>>1
相当于n/2
2.4 程序执行结构
顺序结构
分支结构
-
if
-
switch
switch (表达式) { case 取值1: // 取值必须为常量 语句块1; break; // 跳出switch;如果没有则继续向下执行 case 取值n: 语句块n; break; default: // 可选 语句块n+1; break; }
注:表达式的返回值只能是:
int, byte, char, short,String
(不作用于long
)
循环结构
-
for
-
while
-
do-while
while
循环和do-while
循环的区别:while
先判断条件;如果条件满足,再执行循环操作do while
先执行一遍循环操作,再判断条件;如果条件满足,继续执行循环操作
练习:图形打印
- 实心三角形
看成左右两部分:
* | ---*
*** | --***
***** | -*****
******* | *******
外层循环 控制行数:4
内层循环1 控制空格列数:3 2 1 0
内层循环2 控制*号列数: 1 3 5 7
public static void printTri(int row_n) {
for(int i=0; i<row_n; i++) {
for (int j=0; j<row_n-i-1; j++) {
System.out.print(" ");
}
for (int k=0; k<2*i+1; k++) {
System.out.print("*");
}
System.out.println();
}
}
- 实心菱形
看成左右两部分:
* | ---*
*** | --***
***** | -*****
******* | *******
***** | -*****
*** | --***
* | ---*
分为上下两部分,上下相反:
上半部分: 下半部分:
外层 行:(7+1)/2+1=4 外层 行:7-4=3
内层1 列:3 2 1 0 内层1 列:1 2 3
内层2*列:1 3 5 7 内层2*列:5 3 1
public static void printRhomb(int row_n) {
int half = (row_n+1)/2;
for (int i=0; i<half; i++) {
for (int j=0; j<half-i-1; j++)
System.out.print(" ");
for (int k=0; k<2*i+1; k++)
System.out.print("*");
System.out.println();
}
for (int i=row_n-half-1; i>=0; i--) {
for (int j=0; j<half-i-1; j++)
System.out.print(" ");
for (int k=0; k<2*i+1; k++)
System.out.print("*");
System.out.println();
}
}
- 实心菱形
同样分为左右两部分,右侧头*尾*(但第一行只需一个*)
* | ---*
* * | --*-*
* * | -*---*
* * | *-----*
* * | -*---*
* * | --*-*
* | ---*
public static void printHollowRhomb(int row_n) {
int half = (row_n+1)/2;
// 上半部
for (int i=0; i<half; i++)
loopInside(i, half);
// 下半部
for (int i=row_n-half-1; i>=0; i--)
loopInside(i, half);
}
public static void loopInside(int i, int half) {
for (int j=0; j<half-i-1; j++)
System.out.print(" ");
System.out.print("*");
for (int k=1; k<2*i; k++)
System.out.print(" ");
if (i==0) System.out.println();
else System.out.println("*");
}
2.5 数组
元素按线性顺序排列;长度在创建时就固定了
创建格式
int[] arr = new int[n];
int[] arr = {1,2,3};
int[] arr;
(只创建了数组引用名,并未在内存创建数组空间)int arr = new arr[] {1,2,3};
二维数组
二维数组
int[][] arr = new int[n][];
for (int i=0; i<n; i++) {
arr[i] = new int[m];
}
// 遍历
for (int i=0; i<arr.length; i++) {
for (int j=0; j<arr.length[i]; j++) {
//...
}
}
数组常见算法
冒泡排序
升序排列口诀:
N个数字来排队
两两相比小靠前
外层循环length-1
内层循环length-i-1
public static void bubbleSort(int[] arr) {
for (int i=0; i < arr.length-1; i++) {
for (int j=0; j < arr.length-i-1; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
二分查找
要求数组数据必须采用顺序存储结构有序排列
public static int binarySearch(int[] arr, int key) {
int low = 0, high = arr.length-1;
while (low <= high) {
int mid = low + (high-low)/2;
if (arr[mid] == key) return mid;
if (arr[mid] > key) high = mid-1;
else low = mid + 1;
}
return -1;
}