注释
- 单行注释://
- 多行注释:/* */
- 文档注释:/** */
标识符
组成:下划线(_),美元符($)以及字母和数字 规则:不能以数字开头,且区分大小写,不能包含空格,不能是Java关键字和保留字,
命名建议:
-
类、接口等命名标识符——大驼峰命名法
- 第一个单词的首字母大写,从第二个单词开始,首字母都要大写
-
变量、方法的命名标识符——小驼峰命名法
- 第一个单词的首字母小写,从第二个单词开始,首字母都要大写
-
常量的命名标识符——全部大写,多个单词之间用下划线(_)隔开
数据类型
基本数据类型(四类八种)
数据类型 | 关键字 | 字节长度 | 取值范围 |
---|---|---|---|
整数类型 | byte | 1 | -128 到 127 |
short | 2 | -32768 到 32767 | |
int(默认) | 4 | -2^31 到 2^31-1 | |
long | 8 | -2^63 到 2^63-1 | |
浮点类型 | float | 4 | -3.403E38 到 3.404E38(有效位数7-8位) |
double(默认) | 8 | -1.798E308 到 1.798E308(有效数字16-17位) | |
字符类型 | char | 2 | 0 到 65535 |
布尔类型 | boolean | 1 | true,false |
注意:根据JVM规范,在内存中boolean当作int处理,占4个字节,boolean数组当成byte数组处理,一个boolean元素占1个字节
引用数据类型
目前仅需知道String类型就可以
String
-
以""给出的字符串,只要内容相等,jvm都只会建立一个String对象,并在字符串常量池中维护
-
new出来的string即使内容一样,地址也不同
-
使用"+"拼接字符串时,底层会创建一个StringBuilder对象,再调用方法拼接,再调用toString转换为String
String s1 = "abc"; String s2 = "ab"; String s3 = s2 + "c"; String s4 = "a"+"b"+"c"; System.out.println(s1 == s3); //结果为false System.out.println(s1 == s4); //存在常量优化机制,结果为true
数据类型间的转换
隐式转换(自动转换)
- 取值范围小的数据可以给范围大的直接赋值
- (byte→short),(char)→int→long→float→double
- 计算时,小的提升大的再计算
- byte,short,char三种数据运算时,都会先提升为int,再计算
强制转换
//强制转换的语法:目标数据类型 变量名 = (目标数据类型)(被转换的变量变量名);
int a = 10;
byte m = (byte)a;
//注意:在进行计算时,byte会先转换为int再计算
byte a = 3; byte b = 4;
byte c = a + b; //报错
byte c = (byte)a + (byte)b; //报错
byte c = (byte)(a+b); //正确写法
//整数默认为int类型,即使其值超过int,系统也不会把其转为long类型,
//所以如果希望把其当作long类型处理,需要加L后缀
long num = 123456789123456789L;
//小数形式则默认为double,如果希望把其当作float类型处理,需要加F后缀
float num = 58.0F;
常量优化机制
在给一个变量赋值的时候,如果“=”的右边全部是常量那么在编译阶段会把右边的结果赋值给左边的变量; 如果范围不超过左边的变量类型的范围(或者说属于左边的范围)那么就会赋值成功如果超过就会赋值失败; 右边如果存在变量,则不会触发常量优化机制。
//编译时,会将3+4计算出结果,并且会自动判断该结果是否在类型取值范围内。在则编译成功,不在则编译失败
byte num = 3 + 4;
运算符
算数运算符
-
四则运算:+,-,*,/
-
取余:%
//整数操作只能得到整数,要想得到小数,必须有浮点数参与运算。
System.out.println(10 / 3); // 输出结果为3
System.out.println(10 /3.0); // 输出结果为3.333...
-
字符与字符串的"+"操作
字符:做加法操作时,是其对应的ASCII码增加,从而改变字符 字符串:做加法操作时,不是算数运算,而是字符串之间做拼接操作
-
自增自减 ++,--
如果放在变量的后边,先拿变量参与操作,再拿变量做++或者--。 如果放在变量的前边,先拿变量做++或者--,再拿变量参与操作。
int x = 10; int y = x++; System.out.println("x:" + x + ", y:" + y); // x:11,y:10 int m = 10; int n = ++m; System.out.println("m:" + m + ", n:" + n); // m:11,n:11
赋值运算符
-
基本赋值运算符:=
-
扩展赋值运算符(自带强转类型的功能):+=,-=,*=,/=,%=
short s = 1; s = s + 1 //会报错,因为运算中s提升为int类型,运算结果int赋值给short可能损失精度 s += 1 //不报错,因为隐含了强制类型转换,相当于 s = (short) (s + 10);
关系运算符
- ==,!=,>,<,>=,<=
逻辑运算符
-
普通逻辑运算符:&(与),|(或),!(非),^(异或)
与:当且仅当两个操作数都为真,条件才为真。
或:如果任何两个操作数任何一个为真,条件为真。
非:true时为false,false时为true。
异或:相同时为false,不同时为true。
-
短路逻辑运算符:&&,||
短路时,若第一个表达式已经能够决定表达式的值了,后面就都不算了
三目运算符
- ①?②:③ (若①对,则②,若①错,则③。)
位运算
- ~:按位取反,包括符号位
- :按位异或,两位相同为0,不同为1,aa→0,0^a→a
- &:按位与,两位都是1,结果才为1
- | :按位或,两位都是0,结果才是0
进制表达与转换
进制表达
- 二进制:0b开头
- 八进制:0开头
- 十六进制:0x开头
进制转换
- 多进制转十进制:次幂相加
- 十进制转多进制:大除法,然后余数倒写
- 二进制转八进制(3位对应一位)
- 二进制转十六进制(4位对应一位)
原码,反码,补码
- 原码:符号位(正数为0,负数为1),其余位表示大小用二进制
- 反码:正数反码为本身,负数反码符号位不变,其余取反
- 补码(储存方式):正数补码为本身,负数补码符号位不变,其余取反再加一
控制流程
If
if (条件语句){…}
if (条件语句){…} else {…}
if (条件语句){…} else if (条件语句){…}else{…}
Switch
switch(表达式){
case 值1: 语句块1; break;
…
case 值n: 语句块n; break;
default: 语句块n+1; break; //所有值都不匹配则执行default语句体部分
}
//需要注意的是:如果switch语句中,case省略了break语句, 就会开始case穿透.
//当开始case穿透,后续的case就不会具有匹配效果,内部的语句都会执行
//直到看见break,或者将整体switch语句执行完毕,才会结束。
switch(week){
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("工作日");
break;
case 6:
case 7:
System.out.println("休息日");
break;
default:
System.out.println("您的输入有误");
break;
}
For
//1.先执行初始化语句,
//2.再执行条件判断语句,
//3.如果是false,则循环结束,如果是true,则执行循环体语句,再执行循环控制语句,最后回到第2步继续循环
for(初始化语句 ; 条件判断语句(布尔表达式); 循环控制语句) {
//循环体语句
}
While
//1.先执行初始化语句,
//2.再执行条件判断语句,
//3.如果是false,则循环结束,如果是true,则执行循环体语句,再回到第2步继续循环
初始化语句;
while(条件判断语句){
循环体语句;
(循环控制语句)
}
Do...While
//1.先执行初始化语句,再执行循环体语句
//2.再执行条件判断语句,
//3.如果是false,则循环结束,如果是true,则执行循环体语句,再回到第2步继续循环
初始化语句;
do{
循环体语句;
(循环控制语句)
} while(条件判断语句);
跳转控制语句
-
break
中断当前循环
-
continue
结束本次循环
-
return
结束方法,并返回一定内容
数组
数组的声明
//一维数组
数据类型[] 数组名;
数据类型 数组名[]; //不建议使用
//二维数组
数据类型[][] 二维数组名;
数据类型 二维数组名[][]; //废弃,不要使用
数据类型[] 二维数组名[]; //废弃,不要使用
数组的初始化
静态初始化
指定数组中每个元素的初始值,数组的长度由系统决定
int[] arr1 = new int[]{1,2,3};
int[] arr2 = {1,2,3}; //简化的形式必须跟在声明之后,不能后续赋值
int[][] arr3 = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
int[][] arr3 = {{1,2,3},{4,5,6},{7,8,9}};
动态初始化
只是指定数组的长度,数组中每个元素的初始值由系统决定
int[] arr1 = new int[3];
int[][] arr2 = new int[3][3];
int[][] arr3 = new int[3][];
//第二维的长度可以动态给出,但是手动初始化一维数组时,不能使用简化版的一维数组静态初始化
int[][] arr = new int[5][]; //五行
for(int i=0; i<arr3.length; ++i){
arr3[i]=new int[i+1]; //列的长度每次都变化。每次都要重新申请空间(长度)
for(int j=0; j<arr3[i].length; ++j)
arr3[i][j]= i+j;
}
数组的遍历
for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]) }
for (int a : arr) { System.out.print(a); }
方法
方法的定义
[修饰符列表] 返回值类型 方法名 (形式参数列表){
//方法体
}
//没有返回值类型时,使用void
方法的重载
定义:一个类中存在多个方法名相同,但是形参列表不同的方法,它们就构成方法的重载, 所以,尽管他们方法名相同,但是它们表示不同的方法
需要注意的是:形参的名字不同,返回值类型不同,修饰符列表不同都无法构成方法的重载
- 形参数量不同
- 形参数量相同时,但形参的数据类型不同
- 形参数量和数据类型都相同,但是形参数据类型的顺序不同
方法的可变参数
public static int sum(int a,int b,int... arr) { //arr为可变参数
return a + b;
}
- 适用于参数个数不确定,类型确定的情况,Java会自动把可变参数当作数组处理
- 一个方法只能有一个可变长参数,并且这个可变长参数必须是该方法的最后一个参数
方法的递归
-
我们把方法在运行时调用自身的情况,称之为递归,又叫做递归调用
-
注意事项
- 要有递归出口,不能无限制的递归下去,否则会发生栈溢出错误
- 即便是有出口的递归,递归的深度也不能超过栈空间的大小,否则仍然会报错
-
优点
- 递归的代码会非常简洁
- 人在解决问题时都会下意识的分解问题,递归的思想很符合人的思维,递归的思路容易理解‘
-
缺点
- 递归调用多个方法,占用大量栈内存,且效率非常低
- 递归分解小问题时,可能存在重复计算
- 递归很危险,容易栈溢出