Java是面向对象的语言,一个程序的基本单位就是class。在class内部,可定义若干方法。
类名要求:
- 类名必须以英文字母开头,后接字母,数字和下划线的组合
- 习惯以大写字母开头
方法名要求:
- 方法名必须以英文字母开头,后接字母,数字和下划线的组合
- 习惯以小写字母开头
(二)变量和数据类型
在Java中,变量分为基本类型的变量和引用类型的变量。
例如:int x = 1; //定义了一个整型int类型的变量,名为x,初始值为1
变量的一个特点是可以重新赋值,也可以赋值给其他变量。值得注意的是,在第一次定义变量时需要指定变量类型,而第二次重新赋值时,该变量已经存在了,不用再指定变量类型。
基本数据类型
- 整数类型:byte, short, int, long
- 浮点数类型:float, double
- 字符类型:char
- 布尔类型:boolean
计算机内存的最小存储单元是字节(byte),一个字节就是一个8位二进制数,即8个bit,字节的二进制表示范围为00000000~11111111,换算成二进制是0~255,换算成十六进制是00~ff。
Java基本数据类型占用的字节数
类型 | byte | short | int | long | float | double | char |
字节 | 1 | 2 | 4 | 8 | 4 | 8 | 2 |
定义基本数据类型时的注意事项
- 整型最高位的bit表示符号位(0表示正数,1表示负数)
- long型的结尾需要加L(int l = 9000000000000000000L;)
- float型的结尾需要加f(float f = 3.14f;)
- char类型使用单引号‘ ’,且仅有一个字符,字符串使用双引号“ ”
引用类型
- 常量:定义变量的时候,如果加上final修饰符,这个变量就变成了常量。常量名通常全部大写
- var关键字:省略变量类型可使用var关键字
(三)整数运算
Java的整数运算遵循四则运算规则,可以使用任意嵌套的小括号。四则运算规则和初等数学一致。
溢出
整数由于存在范围限制,如果计算结果超出了范围,就会产生溢出,但溢出不会出错,需特别注意
自增/自减
- ++n表示先加1再引用n
- n++表示先引用n再加1
移位运算
左移实际上就是不断地乘2,右移实际上就是不断地除以2
例如:对整数7左移一位得到整数14 int n = 7; int a = n << 1;
对整数-28右移一位得到整数-14 int n = -28; int a = n >> 1;
值得注意的是
- >>>为无符号的右移运算,它的特点是不管符号位,因此对一个负数进行>>>右移,它会变成正数
- 对byte和short类型进行移位时,会首先转换为int再进行位移。
位运算
位运算就是按位进行与、或、非和异或的运算。
- 与运算(&):必须两个数同时为1,结果才为1
- 或运算(|):只要任意一个为1,结果就为1
- 非运算(~):0和1互换
- 异或运算(^):如果两个数不同,结果为1,否则为0
类型自动提升与强制转型
在运算过程中,如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。
也可以将结果强制转型,即将大范围的整数转型为小范围的整数,例如int i = 12345; short s = (short) i;但超出范围的强制转型会得到错误的结果。
(四)浮点数运算
浮点数只能进行加减乘除这些数值运算,不能做位运算和移位运算。
虽然浮点数表示的范围大,但浮点数无法精确表示,所以浮点数运算通常会产生误差。因此在比较两个浮点数是否相等时,正确的比较方法是判断两个浮点数之差是否小于一个很小的数。
类型提升
如果参与运算的两个数其中一个是整型,那么整型可以自动提升到浮点型
溢出
整数运算在除数为0时会报错,而浮点数运算在除数为0时不会报错,但会返回几个特殊值:
- NaN表示Not a Number
- Infinity表示无穷大
- -Infinity表示负无穷大
强制转型
可以将浮点数强制转型为整数,在转型时,浮点数的小数部分会被丢掉,如果转型后超过了整数能表示的最大范围,将返回整型的最大值。如果要进行四舍五入,可以对浮点数加上0.5再强制转型。
(五)布尔运算
对于布尔类型boolean,永远只有true和false两个值。
布尔运算包括以下几类:
- 比较运算符:>, >=, <, <=, ==, !=
- 与运算:&&
- 或运算:||
- 非运算:!
短路运算
如果一个布尔运算的表达式能提前确定结果,则后续的计算不再执行,直接返回结果。因为false && x的结果总是false;对于true运算,只要确定第一个值为true,直接返回true
三元运算符
b?x:y,首先计算b,如果b为true,则只计算x,否则只计算y。且x和y的类型必须相同,因为返回值是x和y之一。
(六)字符和字符串
字符类型
字符类型char是基本数据类型,一个char保存一个Unicode字符,占两个字节。
要显示一个字符的Unicode编码,只需要将char类型直接赋值给int类型即可。
字符串类型
字符串类型String是引用类型,用双引号“ ”来表示字符串,一个字符串可存储0个到任意个字符。
常见的转义字符包括:
- \"表示字符"
- \'表示字符'
- \\表示字符\
- \n表示换行符
- \r表示回车符
- \t表示Tab
- \u####表示一个Unicode编码的字符
字符串连接
可以使用+连接任意字符串和其他类型数据,如果用+连接字符串和其他类型数据,会将其他类型数据先自动转型为字符串,再连接。
多行字符串
用"""..."""表示多行字符串,例如:
String s = """ aaa bbbbbbbb cc""";
不可变特性
字符串不可变,但变量名称可改变指向。
空值null
空值null表示不存在,即该变量不指向任何对象;
空字符串" "是一个有效的字符串对象,不等于null。
(七)数组类型
定义一个数组类型的变量,采用类型[]方式,例如int[ ]。但数组遍历初始化必须初始化大小,例如int[ ] ns = new int[5],必须使用new int[5]创建一个可容纳5个int元素的数组。
Java数组特点:
- 数组所有元素初始化为默认值,整型都是0,浮点型是0.0,布尔型是false
- 数组一旦创建后,大小就不可改变。
值得注意的是,
- 可以通过数组索引访问数组中的某个元素,5个元素的数组,索引范围是0~4,如果索引超出范围运行时将报错;
- 可以修改数组中的某一个元素,使用赋值语句,例如ns[1] = 79;
- 可以用数组变量.length获取数组大小;
- 可以在定义数组时直接指定初始化元素,这样就不必写出数组大小,例如int[ ] ns = new int[ ]{68,79,91,85,62};也可以简写成int[ ] ns = {68,79,91,85,62};
- 数组元素也可以不是数据类型,而是引用类型,比如字符串数组
(一)输入和输出
输出
System.out.println();//输出并换行 System.out.print();//输出后不换行
格式化输出
格式化输出使用System.out.printf(),通过使用占位符%?,printf()可以把后面的参数格式化成指定格式
占位符
%d 格式化输出整数
%x 格式化输出十六进制整数
%f 格式化输出浮点数
%e 格式化输出科学计数法表示的浮点数
%s 格式化字符串
由于%表示占位符,因此,连续两个%%表示一个%字符本身
//把一个整数格式化成十六进制,并用0补足8位 int n = 12345000; System.out.printf("hex=%08x",n);
输入
首先创建Scanner对象并传入System.in,代表标准输入流,同样的,System.out代表标准输出流。
读取字符串使用scanner.nextLine();读取整数使用scanner.nextInt();等等。
Scanner scanner = new Scanner(System.in);//创建Scanner对象 System.out.print("input your name:"); String name = scanner.nextLine();//读取一行输入并获取字符串 System.out.print("input your age:"); int age = scanner.nextInt();//读取一行输入并获取整数
例如,输入上次考试成绩(int)和本次考试成绩(int),然后输出成绩提高的百分比,保留两位小数位
import java.util.Scanner; public class Test{ public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入上次考试成绩:"); int grade1 = scanner.nextInt(); System.out.print("请输入本次考试成绩:"); int grade2 = scanner.nextInt(); float percent = (float)(grade2 - grade1)/ grade1*100; System.out.printf("%.2f%%\n",percent); } }
(二)if判断
if语句的基本语法是
if(条件){ //条件满足时执行,可以是多条语句 } else{ //条件判断为false时,执行语句 }
else不是必须的,也可以使用多个if...else if串联。
使用多个if时,要特别注意判断顺序,同时还要注意边界条件。
判断引用类型相等
- ==表示“引用是否相等”,是否指向同一个对象
- equals()判断引用类型的变量内容是否相等
-
例如
if (s1.equals(s2)){ System.out.println("s1 equals s2"); }
但如果变量s1为null,会报NullPointerException,为了避免此类错误,可以利用短路运算符&&
if (s1.equals(s2)){ System.out.println("s1 equals s2"); }
练习:计算体制指数BMI,并打印结果
import java.util.Scanner; public class Test{ public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("身高:"); float height = scanner.nextFloat(); System.out.print("体重:"); float weight = scanner.nextFloat(); float BMI = weight/(height*height); if(BMI > 32) { System.out.print("非常肥胖"); } else if(BMI > 28 && BMI <= 32) { System.out.print("肥胖"); } else if(BMI > 25 && BMI <= 28) { System.out.print("过重"); } else if(BMI > 18.5 && BMI <= 25) { System.out.print("正常"); } else { System.out.print("过轻"); } } }
(三)switch多重选择
- switch语句根据switch表达式计算的结果,跳转到匹配的case结果,然后继续执行后续语句,直到遇到break结束执行;
- switch的计算结果必须是整型、字符串或枚举类型;
- 不要漏写break和default。
-
练习:石头剪刀布游戏
import java.util.Scanner; public class Test{ public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入选项:"); String option = scanner.nextLine(); switch(option) { case "剪刀和石头": System.out.print("剪刀和石头,石头赢"); break; case "剪刀和布": System.out.print("剪刀和布,剪刀赢"); break; case "石头和布": System.out.print("石头和布,布赢"); break; default: System.out.print("错误"); break; } } }
(四)while循环
while循环的基本用法是先判断循环条件再执行循环,条件满足时继续循环,条件不满足时退出循环。
while(条件表达式){ 循环语句 }
编写循环时要注意循环条件,并避免死循环。while可能一次循环都不执行。
(五)do while循环
do while循环的基本用法是,先执行循环,再判断条件,条件满足时继续循环,条件不满足时推出循环。
do{ 执行循环语句 }while(条件表达式);
do while至少会执行一次循环。
(六)for循环
for循环的用法是
for(初始条件;循环检测条件;循环后更新计数器){ //执行语句 }
for循环还可以缺少初始化语句,循环条件和每次循环更新语句。
for each循环可以用来遍历数组,例如
public class Main { public static void main(String[] args) { int[] ns = { 1, 4, 9, 16, 25 }; for (int n : ns) { System.out.println(n); } } }
(七)break和continue
break
语句可以跳出当前循环;break
语句通常配合if
,在满足条件时提前结束整个循环;break
语句总是跳出最近的一层循环;continue
语句可以提前结束本次循环;continue
语句通常配合if
,在满足条件时提前结束本次循环。(一)遍历数组
for循环
public class Main{ public static void main(String[] args){ int[] ns = {1, 4, 9, 16, 25}; for (int i=0; i<ns.length; i++){ int n = ns[i]; System.out.println(n); } } }
for each循环
public class Main { public static void main(String[] args) { int[] ns = { 1, 4, 9, 16, 25 }; for (int n : ns) { System.out.println(n); } } }
打印数组内容
import java.util.Arrays; public class Main{ public static void main(String[] args){ int[] ns = {1, 1, 2, 3, 5, 8}; System.out.println(Arrays.toString(ns)); } }
(二)数组排序
冒泡排序
import java.util.Arrays; public class Main{ public static void main(String[] args){ int[] ns ={1, 4, 2, 8, 6}; //排序前 System.out.println(Arrays.toString(ns)); for(int i = 0; i<ns.length - 1; i++){ for(int j = 0; i<ns.length-i-1; j++){ if (ns[j] > ns[j+1]){ //交换ns[j]和ns[j+1] int temp = ns[j]; ns[j] = ns[j+1]; ns[j+1] = temp; } } } //排序后 System.out.println(Arrays.toString(ns)); }
实际上,可以采用Arrays.sort()实现排序,例如
int[] ns = {2, 5, 1, 3, 4}; Arrays.sort(ns); System.out.println(Arrays.toString(ns));
(三)多维数组
二维数组
二维数组就是数组的数组,定义一个二维数组如下
int[][] ns = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12} };
二维数组的每个数组元素的长度并不要求相同,访问二维数组的一个元素使用array[row][col],打印二维数组可以使用Arrays.deepToString()。
三维数组
三维数组就是二维数组的数组,定义一个三维数组如下
int[][][] ns = { { {1,2,3}, {4,5,6}, {7,8,9} }, { {10,11},{12,13} }, { {14,15,16},{17,18} } };
(四)命令行参数
Java程序的入口是main方法,而main方法可以接受一个命令行参数,它是一个String[]数组,这个命令行由JVM接收用户输入并传给main方法。
- 数组元素也可以不是数据类型,而是引用类型,比如字符串数组