Java基础之数据类型、标识符、运算符、程序流程控制结构
一、Java的注释
在Java开发中注释分为三种:
① 单行注释:
//this is 单行commentaries
② 多行注释:
/*这是多行注释,用在方法的外部,提示方法的使用*/
Public void show(){
代码块
}
③ 文档注释:
/**
* 文档注释
* 作者
* 最后的修改时间
*/
二、标识符
1.标识符概念:
用来表示类名,变量名,方法名,类型名,数组名,文件名的有效字符序列称为标识符。
通俗一点讲,凡是可以由自己命名的地方都称为修饰符(标识符).例: 项目名 ,包名 ,类名 .方法名,常量名
2.标识符命名规则
- (1) 由字母、数字、下划线、$组成,不能以数字开头。
- (2) 大小写敏感。
- (3) 不得使用java中的关键字和保留字。
关键字:都是小写的,jdk1.2多了strictfp(经准浮点型),关键字 jdk1.4多了assert(断言)关键字,jdk1.5多了enum(枚举) 关键字。
Java采用Unicode字符集,因此标识符也可以用汉字命名,但非常不建议用!!
标识符命名时应该要“见名知意”
Java关键字:
定义:被Java语言赋予了特俗含义,用作特殊用途的字符串(单词)
特点:都是小写
java保留字:现有Java版本尚未使用,但以后版本可能会作为关键字使用(goto,const)
Java变量必须先赋值再使用
3.标识符命名规范
1、项目名全部小写.
2、包名全部小写.
3、类名首字母大写,其余组成词首字母依次大写.
4、变量名,方法名首字母小写,如果名称由多个单词组成,除首字母外的每个单词的首字母都要大写.
5、常量名全部大写.
三、Java数据类型
1、基本数据类型
整型:byte、short、int、long (在计算机中以二进制补码格式存储)
浮点型:float、double (在计算机中以IEEE754格式存储)
字符型:char (在计算机中以unicode码格式存储)
布尔型:boolean (只有true和false两个值)
- byte:一个字节,8位,最大存储数据量是255,存放的数据范围是-128~127之间。
- short:二个字节,16位,最大数据存储量是65536,数据范围是-32768~32767之间。
- int:四个字节,32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。
- long:八个字节,64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。
- float:四个字节,32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
- double:八个字节,64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
- boolean:只有true和false两个取值。
- char:一个字符,二个字节,16位,存储Unicode码,用单引号赋值。
float范围比long还大
基本数据类型变量之间自动类型提升运算规则:
byte,short,char——>int——>long——>float——>double
String不是基本数据类型,只能有连接运算,只有基本数据类型可以做加减乘除运算
基本数据类型之间数据类型强制转换规则和强转可能出现的问题:
容量大——>容量小,用强转符()
可能会损失精度
原码,补码,反码:
正数:三码合一
负数:反码:原码最高位(符号位)为1,其他位取反
补码:反码+1
2、引用数据类型
类(String),接口,数组
四、运算符
1、算术运算符
运算符 | 运算 | 示例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | a=4;-a | -4 |
+ | 加法 | 5+5 | 10 |
- | 减法 | 6-4 | 2 |
* | 乘法 | 2*3 | 6 |
/ | 除法 | 6/3 | 2 |
% | 余数/取余/取模 |
a=7%5;b=5%7 |
a=2;b=5 |
++ ++ |
自增(前):先运算后取值 自增(后):先取值后运算 |
a=2;b=++a a=2;b=a++ |
a=3;b=3 a=3;b=2 |
-- -- |
自减(前):先运算后取值 自减(后):先取值后运算 |
a=2;b=--a a=2;b=a-- |
a=1;b=1 a=1;b=2 |
+ | 字符串连接 | "He"+"llo" | Hello |
2、赋值运算符
运算符 | 运算 | 示例 | 结果 |
= | 赋值 | a=2 | a=2 |
+= | 加法分配 | a=2;a+=2 | a=4 |
-= | 减法分配 | a=5;a-=2 | a=3 |
*= | 乘法分配 | a=2;a*=3 | a=6 |
/= | 分配分配 | a=6;a/=2 | a=3 |
%= | 模量分配 | a=6;a%=4 | a=2 |
注:赋值运算符不会改变变量本身的数据类型
public class TestDemo { public static void main(String[] args){ short s = 3; // s = s + 3; // 编译失败 s += 3; System.out.println(s); } }
举例:
public class TestDemo { public static void main(String[] args){ int n = 10; n += (n++) + (++n); // n = n + (n++) + (++n) 10+10+12 System.out.println(n); // n = 32 } }
3、比较运算符/关系运算符
运算符 | 运算 | 示例 | 结果 |
---|---|---|---|
== | 等于 | 2==3 | false |
!= | 不等于 | 2!=3 | true |
> | 大于 | 2>3 | false |
< | 小于 | 2<3 | true |
>= | 大于或等于 | 2>=3 | false |
<= | 小于或等于 | 2<=3 | true |
instanceof | 检查是否是类的对象 | "Hello" instanceos String | true |
注:比较运算符的运算结果都是布尔值
4、逻辑运算符
&——逻辑与 |——逻辑或 !——逻辑非
&&——短路与 ||——短路或 ^——逻辑异或
a | b | a&b | a&&b | a|b | a||b | !a | a^b |
true | true | true | true | true | true | false | false |
true | false | false | false | true | true | false | true |
false | true | false | false | true | true | true | true |
false | false | false | false | false | false | true | false |
a&b/a&&b:a和b都是true时为true,其余为false
a|b/a||b:a、b都是false时未false,其余为true
a^b:a、b相同为false,不同为true
注:逻辑运算符都是布尔类型的变量
①区分单与(&)与双与(&&):
相同点:
1、&与&&运算结果都是相同的
2、当符号左边为true时,都会执行符号右边的运算
不同点:当符号左边为false时,&会继续执行符号右边的运算,&&不会再执行符号右边的运算(相当于短路了)
public class TestDemo { public static void main(String[] args){ // 区分单与(&)与双与(&&) boolean b1 = false; int num1 = 10; if (b1 & (num1++ > 0)){ System.out.println("我现在在杭州"); }else { System.out.println("我现在在合肥"); } System.out.println("num1 = " + num1); System.out.println("-------------------------"); boolean b2 = false; int num2 = 10; if (b2 && (num2++ > 0)){ System.out.println("我现在在杭州"); }else { System.out.println("我现在在合肥"); } System.out.println("num2 = " + num2); } }
此时虽然运算结果都一样,但num的值是不一样的
我现在在合肥 num1 = 11 ------------------------- 我现在在合肥 num2 = 10 Process finished with exit code 0
②区分单或(|)与双或(||):
相同点:
1、|与||运算结果都是相同的
2、当符号左边为false时,都会执行符号右边的运算
不同点:当符号左边为true时,&会继续执行符号右边的运算,&&不会再执行符号右边的运算(相当于短路了)
public class TestDemo { public static void main(String[] args){ // 区分单或(|)与双或(||) boolean b1 = true; int num1 = 10; if (b1 | (num1++ > 0)){ System.out.println("我现在在杭州"); }else { System.out.println("我现在在合肥"); } System.out.println("num1 = " + num1); System.out.println("-------------------------"); boolean b2 = true; int num2 = 10; if (b2 || (num2++ > 0)){ System.out.println("我现在在杭州"); }else { System.out.println("我现在在合肥"); } System.out.println("num2 = " + num2); } }
此时虽然运算结果是一样的,但num的值不一样
我现在在杭州 num1 = 11 ------------------------- 我现在在杭州 num2 = 10 Process finished with exit code 0
在实际开发中,推荐使用&&和||
5、位运算符
运算符 | 运算 | 举例 | 细节 |
---|---|---|---|
~ | 取反运算(按位一元NOT) | ~6=7 |
正数取反:各二进制码按补码各位取反(含符号位) 负数取反:各二进制码按补码各位取反(含符号位) |
& | 与运算(按位AND) | 6&3=2 |
二进制位进行&运算,只有1&1时结果是1,否则是0 |
| | 或运算(按位或) | 6|3=7 | 二进制位进行|运算,只有0&0时结果是0,否则是1 |
^ | 异或运算(按位异或) | 6^3=5 |
相同二进制位进行^运算,结果是0,1^1=0,0^0=0 不同二进制位进行^运算,结果是1,1^0=1,0^1=1 |
>> | 右移 | 3>>1=1 --> 3/2=1 |
被移位的二进制最高位是0,空缺位补0; 被移位的二进制最高位是1,空缺位补1 |
>>> | 无符号右移(右移零填充) | 3>>>1=1 --> 3/2=1 | 被移位的二进制最高位无论是0或1,空缺位都补0 |
<< | 左移 | 3<<2=12 --> 3*2*2=12 | 被移除的高位丢弃,空缺位补0 |
位运算是直接对整数的二进制进行运算
注:无<<<
1、位运算符操作的都是整形的数据
2、<<:在一定范围内,每向左移一位,相当于 * 2
>>:在一定范围内,每向右移一位,相当于 / 2
最高效的计算2 * 8?2<<3
public class TestDemo { public static void main(String[] args) { int i = 21; System.out.println("i << 2 = " + (i << 2)); // i << 2 = 84 System.out.println("i << 3 = " + (i << 3)); // i << 3 = 168 System.out.println("i << 27 = " + (i << 27)); // i << 27 = -1476395008 System.out.println("12 & 5 = " + (12 & 5)); // 12 & 5 = 4 System.out.println("12 | 5 = " + (12 | 5)); // 12 | 5 = 13 System.out.println("12 ^ 5 = " + (12 ^ 5)); // 12 ^ 5 = 9 System.out.println("~6 = " + (~6)); // ~6 = -7 } }
交换2个变量的值
public class TestDemo { public static void main(String[] args) { // 交换2个变量的值 int num1 = 10; int num2 = 20; // 方法一:定义临时变量 int temp = num1; num1 = num2; num2 = temp; System.out.println("num1 = "+ num1 +",num2 = "+ num2); // 方法二:①可能相加后超出存储范围;②有局限性:只能适用于数值类型 // num1 = num1 + num2; // num2 = num1 - num2; // num1 = num1 - num2; // System.out.println("num1 = "+ num1 +",num2 = "+ num2); // 方法三:使用位运算符,有局限性:只能适用于数值类型 // num1 = num1 ^ num2; // num2 = num1 ^ num2; // num1 = num1 ^ num2; // System.out.println("num1 = "+ num1 +",num2 = "+ num2); } }
6、三元(目)运算符
格式:(条件表达式)?表达式1:表达式2;
条件表达式为true,运算表达式1;
条件表达式为false,运算表达式2;
注:表达式1与表达式2为要求为一直的,可以统一为一个类型
三元运算符与if-else的联系与区别:
1)三元运算符可简化if-else语句
2)三元运算符要求必须返回一个结果
3)if后的代码块可有多个语句
4)如果程序既可以使用三元运算符,又可以使用if-else语句,优先选择三元运算符(三元效率比if-else高)
public class TestDemo { public static void main(String[] args) { // 获取2个整数的最大值 int num1 = 10; int num2 = 20; int max = (num1 < num2) ? num2 : num1; // 声明的变量类型取决于表达式 System.out.println(max); //20 } }
三元运算符可嵌套使用
public class TestDemo { public static void main(String[] args) { // 获取2个整数的最大值 int num1 = 20; int num2 = 20; String maxnum = (num1 < num2) ? "num2大" : ((num1 == num2)? "num1=num2" : "num1大"); // 声明的变量类型取决于表达式 System.out.println(maxnum); // num1=num2 } }
五、程序流程控制
1、分支结构
1)if-else结构(条件判断结构)
三种结构
①、if(布尔表达式) { //如果布尔表达式为true将执行的语句 } ②、二选一 if(布尔表达式){ //如果布尔表达式的值为true }else{ //如果布尔表达式的值为false } ③、多选一 if(布尔表达式){ //执行表达式1 }else if{ //执行表达式2 }else if{ //执行表达式3 } ... else{ //执行表达式n }
if-else语句可以嵌套
if-else执行表达式中若只有一行执行语句,对应的{}可以省略,但不建议省略
补充:Sacnner类使用方法:
import java.util.Scanner; // 导包 public class TestDemo { public static void main(String[] args) { // 从键盘获取输入值 Scanner scan = new Scanner(System.in); // Scanner实例化 System.out.println("请输入你的姓名:"); String name = scan.next(); // 调用Scanner类的相关方法 System.out.println(name); System.out.println("请输入你的芳龄:"); int age = scan.nextInt(); System.out.println(age); // scan没有提供char型获取方法,只能获取字符串 System.out.println("请输入你的性别:"); String gender = scan.next(); char genderChar = gender.charAt(0); System.out.println(genderChar); System.out.println("请输入你的体重:"); double weight = scan.nextDouble(); System.out.println(weight); System.out.println("你是否相中我了呢?(true/false):"); boolean isLove = scan.nextBoolean(); System.out.println(isLove); } }
生成随机数
import java.lang.Math; public class TestDemo { public static void main(String[] args) { // 取随机数[10,99] // random() ——> [0,1) int num = (int) (Math.random() * 90 + 10); // [0,1)——>[10,100)-->[10,99] System.out.println(num); // 公式:[a,b]:(int) (Math.random() * (b-a+1) + a) } }
2)switch-case 语句
switch(expression){ case value : //语句 break; //可选 case value : //语句 break; //可选 //你可以有任意数量的case语句 default : //可选,位置灵活 //语句 }
switch结构中的表达式,必须是一下6种类型:byte,short,char,int,枚举类型(JDK5.0新增),String类型(JDK7.0新增)。 不能为boolen值
case后只能为常量,不能为范围值
如果多个case中的结果相同,可以合并
public class TestDemo { public static void main(String[] args) { int score = 78; switch (score / 10){ case 0: case 1: case 2: case 3: case 4: case 5: System.out.println("不及格"); break; case 6: case 7: case 8: case 9: case 10: System.out.println("及格"); } // 输出:及格 } }
总结:
1、能用switch-case写的,都可以转换能if-else语句,反之不行
2、当2者都可用时,优先使用switch-case (效率高)
2、循环结构
循环结构四部分
①初始化条件
②循环条件(必须为布尔值)
③循环体
④迭代条件
按顺序执行
1)for循环
for(①初始化; ②布尔表达式; ④更新) { //③代码语句 }
for循环的循环条件必须是布尔类型
例题
1、遍历100以内的偶数,输出所有偶数之和与偶数个数
public class TestDemo { public static void main(String[] args) { // 遍历100以内的偶数,输出所有偶数之和与偶数个数 int sum = 0; int count = 0; for(int i=1;i<=100;i++){ if (i % 2 == 0){ sum += i; count++; } } System.out.println("所有偶数之和:" + sum); System.out.println("偶数个数:" + count); } } //所有偶数之和:2550 //偶数个数:50
2、计算2个数的最大公约数和最小公倍数
import java.util.Scanner; public class TestDemo { public static void main(String[] args) { // 计算2个数的最大公约数和最小公倍数 Scanner scan = new Scanner(System.in); System.out.println("请输入第一个正整数m:"); int m = scan.nextInt(); System.out.println("请输入第二个正整数n:"); int n = scan.nextInt(); int min = (m <= n) ? m : n; for (int i = min; i >= 1; i--) { if (m % i == 0 && n % i == 0) { System.out.println("m,n的最大公约数为:" + i); break; } } int max = (m >= n) ? m : n; for (int i = max; i <= m * n; i++) { if (i % m == 0 && i % n == 0) { System.out.println("m,n的最小公倍数为:" + i); break; } } } }
3、输出所有水仙花数,水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)。
public class TestDemo { public static void main(String[] args) { // 输出所有水仙花数 for (int i = 100; i < 1000; i++) { int ge = i % 10; int shi = i / 10 % 10; // int shi = i % 100 / 10; int bai = i / 100; int j = ge * ge * ge + shi * shi * shi + bai * bai * bai; if (i == j) { System.out.println(i); } } } }
2、while 循环
① while( ②布尔表达式 ) { //循环内容③④ }
说明,while千万不能少了迭代条件,避免死循环!
注:for循环和while循环可以相互转换
区别:for循环和while循环初始化条件作用域不同
举例:遍历100以内的偶数,输出所有偶数之和与偶数个数
public class TestDemo { public static void main(String[] args) { // 遍历100以内的偶数,输出所有偶数之和与偶数个数 int sum = 0; int count = 0; // for(int i=1;i<=100;i++){ // if (i % 2 == 0){ // sum += i; // count++; // } // } int i = 1; // 初始化条件作用域为全局 while (i <= 100) { i++; //迭代条件 if (i % 2 == 0) { sum += i; count++; } } System.out.println("所有偶数之和:" + sum); System.out.println("偶数个数:" + count); } }
3、do-while循环
① do { //代码语句③④ }while(②布尔表达式);
do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
public class TestDemo { public static void main(String[] args) { // 遍历100以内的偶数,输出所有偶数之和与偶数个数 int sum = 0; int count = 0; // for循环 // for(int i=1;i<=100;i++){ // if (i % 2 == 0){ // sum += i; // count++; // } // } // while循环 // int i = 1; // 初始化条件作用域为全局 // while (i <= 100) { // i++; //迭代条件 // if (i % 2 == 0) { // sum += i; // count++; // } // } // do-while循环 int i = 1; do { i++; if (i % 2 == 0) { sum += i; count++; } } while (i <= 100); System.out.println("所有偶数之和:" + sum); System.out.println("偶数个数:" + count); } }
循环结构嵌套举例
1)、打印如图所示图形
public class TestDemo { public static void main(String[] args) { for (int i = 1; i <= 5; i++) { for (int j = 1; j <= i; j++) { System.out.print('*'); } System.out.println(); } for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 5 - i; j++) { System.out.print('*'); } System.out.println(); } } } * ** *** **** ***** **** *** ** *
2)、打印菱形
public class TestDemo { public static void main(String[] args) { // 打印上半部 for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 5 - i; j++) { System.out.print(" "); } for (int j = 1; j <= i; j++) { System.out.print("* "); } System.out.println(); } // 打印下半部 for (int i = 1; i <= 5; i++) { for (int j = 1; j <= i; j++) { System.out.print(" "); } for (int j = 1; j <= 5 - i; j++) { System.out.print("* "); } System.out.println(); } } } * * * * * * * * * * * * * * * * * * * * * * * * *
3)、打印九九乘法表
public class TestDemo { public static void main(String[] args) { for (int i = 1; i <= 9; i++) { for (int j = 1; j <= i; j++) { System.out.print(j + " * " + i + " = " + i * j + "\t"); } System.out.println(); } } }
4)、打印100以内的质数
质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
public class TestDemo { public static void main(String[] args) { // 质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。 for (int i = 2; i <= 100; i++) { boolean isPrime = true; for (int j = 2; j < i; j++) { if (i % j == 0) { isPrime = false; break; } } if (isPrime) { System.out.println(i); } } } }
优化版本
public class TestDemo { public static void main(String[] args) { // 质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。 boolean isPrime = true; long start = System.currentTimeMillis(); for (int i = 2; i <= 100; i++) { for (int j = 2; j <= Math.sqrt(i); j++) { if (i % j == 0) { isPrime = false; break; } } if (isPrime) { System.out.println(i); } isPrime = true; } long end = System.currentTimeMillis(); System.out.println("所花费时间:"+(end-start)); } }
break和continue
使用范围 | 循环中作用 | |
break |
switch-case 循环结构 |
结束当前循环 |
continue | 循环结构 | 结束当次循环 |
break和continue只就近跳出或结束一层循环,不会结束外层循环,且后面不能再声明执行语句
public class TestDemo { public static void main(String[] args) { for (int i = 1; i < 10; i++) { if (i % 4 == 0) { // break; // 123 continue; // 1235679 } System.out.print(i); } } }
若需要跳出或结束外层循环,需在要要跳出的循环上加上标签
public class TestDemo { public static void main(String[] args) { label:for (int i = 1; i < 10; i++) { // label标签 for(int j=1;j<10;j++){ if (j % 4 == 0) { // break label; // 1:1 1:2 1:3 continue label; // 1:1 1:2 1:3 2:1 2:2 2:3 3:1 3:2 3:3 4:1 4:2 4:3 5:1 5:2 5:3 6:1 6:2 6:3 7:1 7:2 7:3 8:1 8:2 8:3 9:1 9:2 9:3 } System.out.print(i+":"+j+"\t"); } System.out.println(); } } }
基于此,先前计算质数的语法可优化为:
public class TestDemo { public static void main(String[] args) { // 质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。 int count = 0; long start = System.currentTimeMillis(); label:for (int i = 2; i <= 100; i++) { for (int j = 2; j <= Math.sqrt(i); j++) { if (i % j == 0) { continue label; } } System.out.println(i); count++; } long end = System.currentTimeMillis(); System.out.println("共有"+count+"个质数,所花费时间:"+(end-start)); } }