文章目录
一、关键字与标识符
1.1 关键字
- 定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词)
- 特点:关键字中所有字母都为小写
1.2 保留字
- 定义:现有Java版本尚未使用,但以后版本可能会作为关键字使用。自己命名标识符时要避免使用这些保留字,如:goto 、const
1.3 标识符
1. 定义
- 对各种变量、方法和类等要素命名时使用的字符序列称为标识
2. 命名规则
- 由26个英文字母大小写,0-9 ,_或 $ 组成
- 不可以数字开头
- 不可以使用关键字和保留字,但能包含关键字和保留字
- 严格区分大小写,长度无限制
- 不能包含空格
3. 命名规范
- 包名:通常全部使用小写字母组成
- 类名、接口名:所有单词首字母大写(大驼峰)
- 变量名、方法名:第一个单词首字母小写,之后单词首字母大写(小驼峰)
- 常量名:所有字母都大写
注意:java采用unicode字符集,因此标识符也可以使用汉字声明,但是不建议使用。
1.4 变量
1. 概述
- 变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值
- 内存中的一个存储区域
- 该区域的数据可以在同一类型范围内不断变化
- 用于在内存中保存数据
2. 使用规范
- 变量必须先声明后使用
- 可以通过变量名来访问数据
- 同一作用域内变量名不能重复,变量只有在作用域内才有效
3. 语法格式
class Variable {
public static void main(String[] args) {
//变量的定义
int age = 12;
//变量的使用
System.out.println(Age);
//编译错误:使用name之前并未定义过name
//System.out.println(name);
//变量的声明
int name;
//编译错误:使用number之前并未赋值过number
//System.out.println(number);
//变量的赋值
number = 1001;
//不可以在同一个作用域内定义同名的变量
//int age = 22;
//编译不通过,不能直接使用作用域外的变量
//System.out.println(count);
}
public void method(){
int count = 1;
}
}
4. 变量的分类
按数据类型分类按声明位置
基本数据类型 | 占用存储空间 | 取值范围 | 默认初始化值 |
---|---|---|---|
byte | 1字节 = 8位(bit) | -128~127 | 0 |
short | 2字节 | 0 | |
int | 4字节 | 0 | |
long | 8字节 | 0L | |
float | 4字节 | 0.0F | |
double | 8字节 | 0.0 | |
boolean | 1字节 | false | |
char | 2字节 | \u0000(表现为空) |
class Variable {
public static void main(String[] args) {
//1. 整型:byte(1字节=8bit) \ short(2字节) \ int(4字节) \ long(8字节)
//① byte范围:-128 ~ 127
byte b1 = 12;
byte b2 = -128;
//b2 = 128;//编译不通过
System.out.println(b1);
System.out.println(b2);
// ② 声明long型变量,必须以"l"或"L"结尾
// ③ 通常,定义整型变量时,使用int型。
short s1 = 128;
int i1 = 1234;
long l1 = 3414234324L;
System.out.println(l1);
//2. 浮点型:float(4字节) \ double(8字节)
//① 浮点型,表示带小数点的数值
//② float表示数值的范围比long还大
double d1 = 123.3;
System.out.println(d1 + 1);
//③ 定义float类型变量时,变量要以"f"或"F"结尾
float f1 = 12.3F;
System.out.println(f1);
//④ 通常,定义浮点型变量时,使用double型。
//3. 字符型:char (1字符=2字节)
//① 定义char型变量,通常使用一对'',内部只能写一个字符
char c1 = 'a';
//编译不通过
//c1 = 'AB';
System.out.println(c1);
char c2 = '1';
char c3 = '中';
char c4 = 'ス';
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
//② 表示方式:1.声明一个字符 2.转义字符 3.直接使用 Unicode 值来表示字符型常量
char c5 = '\n';//换行符
c5 = '\t';//制表符
System.out.print("hello" + c5);
System.out.println("world");
char c6 = '\u0043';
System.out.println(c6);
//4.布尔型:boolean
//① 只能取两个值之一:true 、 false
//② 常常在条件判断、循环结构中使用
boolean bb1 = true;
System.out.println(bb1);
boolean isflag = true;
if(isflag){
System.out.println("hello");
}else{
System.out.println("world");
}
}
}
6. 基本数据类型转换
- 自动类型提升
容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:
byte / short / char–>int–>long–>float–>double
- byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。
- boolean类型不能与其它数据类型运算。
- 当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。
- 强制类型转换
- 自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符:(),但可能造成精度降低或溢出,格外要注意。
- 通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。
class Variable {
public static void main(String[] args) {
byte b1 = 2;
int i1 = 129;
//自动类型提升
int i2 = b1 + i1;
long l1 = b1 + i1;
System.out.println(i2); //131
float f = b1 + i1;
System.out.println(f); //131.0
short s1 = 123;
double d1 = s1;
System.out.println(d1);//123.0
char c1 = 'a';//97
int i3 = 10;
int i4 = c1 + i3;
System.out.println(i4);
//强制类型转换(存在精度损失)
byte b2 = (byte) (b1 + i1);
System.out.println(b2); //-125
short s2 = 10;
char c2 = (char) (c1 + s2);
System.out.println(c2); //k
byte b3 = 10;
char c3 = (char) (c1 + b3);
System.out.println(c3); //k
short s3 = (short) (b2 + s2);
System.out.println(s3); //-115
short s4 = (short) (b1 + b3);
System.out.println(s4); //12
byte b = 12;
float f1 = (float) (b + 12.3);
System.out.println(f1); // 24.3
}
}
1.5、注释
1、单行注释和多行注释
① 对所写的程序进行解释说明,增强可读性。方便自己,方便别人
② 调试所写的代码
③单行注释和多行注释,注释了的内容不参与编译。换句话说,编译以后生成的.class结尾的字节码文件中不包含注释掉的信息
④多行注释不可以嵌套使用
//注释内容(单行注释)
/*(多行注释)
注释内容
*/
/**(文档注释注释)
*@Description:
*@Author:
*@Version:
*@Date:
*/
2、文档注释(java特有)
注释内容可以被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。
二、运算符
1、算术运算符
class AriTest {
public static void main(String[] args) {
//整除:/ 乘:*
int num1 = 12;
int num2 = 5;
int result1 = num1 / num2;
System.out.println(result1);//2
int result2 = num1 / num2 * num2;
System.out.println(result2);//10
double result3 = num1 / num2;
System.out.println(result3);//2.0
double result4 = num1 / num2 + 0.0;//2.0
double result5 = num1 / (num2 + 0.0);//2.4
double result6 = (double)num1 / num2;//2.4
double result7 = (double)(num1 / num2);//2.0
System.out.println(result5);
System.out.println(result6);
// %:取余运算
//结果的符号与被除数的符号相同
int m1 = 12;
int n1 = 5;
System.out.println("m1 % n1 = " + m1 % n1);//2
int m2 = -12;
int n2 = 5;
System.out.println("m2 % n2 = " + m2 % n2);//-2
int m3 = 12;
int n3 = -5;
System.out.println("m3 % n3 = " + m3 % n3);//2
int m4 = -12;
int n4 = -5;
System.out.println("m4 % n4 = " + m4 % n4);//-2
//(前)++ :先自增1,后运算
//(后)++ :先运算,后自增1
int a1 = 10;
int b1 = ++a1;
System.out.println("a1 = " + a1 + ",b1 = " + b1);
int a2 = 10;
int b2 = a2++;
System.out.println("a2 = " + a2 + ",b2 = " + b2);
int a3 = 10;
++a3;//a3++;
int b3 = a3;
//注意点:
short s1 = 10;
//s1 = s1 + 1;//编译失败
//s1 = (short)(s1 + 1);//正确的
s1++;//自增1不会改变本身变量的数据类型
System.out.println(s1);
byte bb1 =127;
bb1++;
System.out.println("bb1 = " + bb1);//-128
//(前)-- :先自减1,后运算
//(后)-- :先运算,后自减1
int a4 = 10;
int b4 = a4--;//int b4 = --a4;
System.out.println("a4 = " + a4 + ",b4 = " + b4);
}
}
2.比较运算符
class CompareTest {
public static void main(String[] args) {
int i = 10;
int j = 20;
System.out.println(i == j);//false
System.out.println(i = j);//20
boolean b1 = true;
boolean b2 = false;
System.out.println(b2 == b1);//false
System.out.println(b2 = b1);//true
}
}
3. 逻辑运算符
class LogicTest {
public static void main(String[] args) {
//区分& 与 &&
//相同点1:& 与 && 的运算结果相同
//相同点2:当符号左边是true时,二者都会执行符号右边的运算
//不同点:当符号左边是false时,&继续执行符号右边的运算。&&不再执行符号右边的运算。
boolean b1 = true;
b1 = false;
int num1 = 10;
if(b1 & (num1++ > 0)){
System.out.println("true");
}else{
System.out.println("false");
}
System.out.println("num1 = " + num1);//11
boolean b2 = true;
b2 = false;
int num2 = 10;
if(b2 && (num2++ > 0)){
System.out.println("true");
}else{
System.out.println("false");
}
System.out.println("num2 = " + num2);//10
// 区分:| 与 ||
//相同点1:| 与 || 的运算结果相同
//相同点2:当符号左边是false时,二者都会执行符号右边的运算
//不同点3:当符号左边是true时,|继续执行符号右边的运算,而||不再执行符号右边的运算
//开发中,推荐使用||
boolean b3 = false;
b3 = true;
int num3 = 10;
if(b3 | (num3++ > 0)){
System.out.println("true");
}else{
System.out.println("false");
}
System.out.println("num3 = " + num3);//11
boolean b4 = false;
b4 = true;
int num4 = 10;
if(b4 || (num4++ > 0)){
System.out.println("true");
}else{
System.out.println("false");
}
System.out.println("num4 = " + num4);//10
}
}
4. 位运算符
对于整数,有四种表示方式:
- 二进制(binary):0,1 ,满2进1.以0b或0B开头。
- 十进制(decimal):0-9 ,满10进1。
- 八进制(octal):0-7 ,满8进1. 以数字0开头表示。
- 十六进制(hex):0-9及A-F,满16进1. 以0x或0X开头表示。此处的A-F不区分大小写。
class BitTest {
public static void main(String[] args) {
int i = 21;
System.out.println("i << 2 :" + (i << 2));//84
System.out.println("i << 3 :" + (i << 3));//168
System.out.println("i << 27 :" + (i << 27));//
int m = 12;
int n = 5;
System.out.println("m & n :" + (m & n));//4 (相同位都为1才为1,否则为0)
System.out.println("m | n :" + (m | n));//13 (相同位都为0才为0,否则为1)
System.out.println("m ^ n :" + (m ^ n));//9 (相同位都不相同为1,否则为0)
//练习:交换两个变量的值
int num1 = 10;
int num2 = 20;
System.out.println("num1 = " + num1 + ",num2 = " + num2);
//方式一:定义临时变量的方式
//推荐的方式
int temp = num1;
num1 = num2;
num2 = temp;
//方式二:好处:不用定义临时变量
//弊端:① 相加操作可能超出存储范围 ② 有局限性:只能适用于数值类型
//num1 = num1 + num2;
//num2 = num1 - num2;
//num1 = num1 - num2;
//方式三:使用位运算符
//有局限性:只能适用于数值类型
//num1 = num1 ^ num2;
//num2 = num1 ^ num2;
//num1 = num1 ^ num2;
System.out.println("num1 = " + num1 + ",num2 = " + num2);
}
}
结论:
- 位运算符操作的都是整型的数据
- (<<):在一定范围内,每向左移1位,相当于 * 2
(>>) :在一定范围内,每向右移1位,相当于 / 2- 计算机底层都是以补码的形式存储数据
① 正数的原码,反码,补码都是相同
② 负数原码等于负数绝对值的原码,负数原码和反码的相互转换:符号位不变,数值位按位取反。
③ 负数反码补码的相互转换:补码 = 反码 + 1
④ 负数原码和补码的相互转换:符号位不变,数值位按位取反,末位再加1
如:-6
原码:1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
反码:1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
补码:1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0
6. 三元运算
格式:
格式:(条件表达式) ? 表达式一 : 表达式二;
① 条件表达式的结果为boolean类型
② 根据条件表达式真或假,决定执行表达式1,还是表达式2.
如果表达式为true,则执行表达式1。
如果表达式为false,则执行表达式2。
③ 表达式1和表达式2要求数据类型是一致的。
④ 三元运算符可以嵌套使用
⑤ 凡是可以使用三元运算符的地方,都可以改写为if-else反之,不成立。
class SanYuanTest {
public static void main(String[] args) {
//获取两个整数的较大值
int m = 12;
int n = 5;
int max = (m > n)? m : n;
System.out.println(max);
double num = (m > n)? 2 : 1.0;//自动类型提升
//(m > n)? 2 : "n大";//编译错误
//**************************
n = 12;
String maxStr = (m > n)? "m大" : ((m == n)? "m和n相等" : "n大");
System.out.println(maxStr);
//*****************************
//获取三个数的最大值
int n1 = 12;
int n2 = 30;
int n3 = -43;
int max1 = (n1 > n2)? n1 : n2;
int max2 = (max1 > n3)? max1 : n3;
System.out.println("三个数中的最大值为:" + max2);
//不建议
//int max3 = (((n1 > n2)? n1 : n2) > n3)? ((n1 > n2)? n1 : n2) : n3;
System.out.println("三个数中的最大值为:" + max3);
}
}
三、流程控制
1. 顺序结构
定义:程序从上到下逐行地执行,中间没有任何判断和跳转。
2. 分支结构
定义:根据判断条件,选择性地执行某段代码。
//方式一:
if(条件表达式){
}
//方式二:
if(条件表达式){
}else{
}
//方式三:
if(条件表达式){
}else if(条件表达式){
}else{
}
//方式四:
switch(表达式){
case 常量1:
执行语句1;
//break;
case 常量2:
执行语句2;
//break;
...
default:
执行语句n;
//break;
}
① 根据switch表达式中的值,依次匹配各个case中的常量。一旦匹配成功,则进入相应case结构中,调用其执行语句。
当调用完执行语句以后,则仍然继续向下执行其他case结构中的执行语句,直到遇到break关键字或此switch-case结构末尾结束为止。
② break,可以使用在switch-case结构中,表示一旦执行到此关键字,就跳出switch-case结构
③ switch结构中的表达式,只能是如下的6种数据类型之一:
byte 、short、char、int、枚举类型(JDK5.0新增)、String类型(JDK7.0新增)
④ case 之后只能声明常量。不能声明范围。
⑤ break关键字是可选的。
⑥ default:相当于if-else结构中的else. default结构是可选的,而且位置是灵活的。
⑦ 都可以嵌套使用
3. 循环结构
定义:根据循环条件,重复性地执行某段代码。
//方式一:
for(初始化部分;循环条件;迭代部分){
循环体部分
}
//方式二:
初始化部分
while(循环条件){
循环体部分
迭代部分
}
//方式三:
初始化部分
do{
循环体部分
迭代部分
}while(循环条件)
- 循环条件部分为boolean类型表达式,当值为false时,退出循环
- 初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔
- 迭代部分可以有多个变量更新,用逗号分隔
- 可以嵌套使用
4. break、continue和return语句
关键字 | 适用范围 | 作用 |
---|---|---|
continue | 循环结构中 | 结束当次循环,跳过其所在循环语句块的一次执行,继续下一次循环 |
break | switch-case 和循环结构中 | 结束当前循环,终止某个语句块的执行 |
return | 方法内 | 结束一个方法 |
continue和break语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳到哪一层循环
四、数组
数组(Array):是储存相同类型数据按一定顺序排列的集合。
4.1、数组的基本属性
1、数组的特点:
- 数组是有序排列的
- 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
- 创建数组对象会在内存中开辟一整块连续的空间
- 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
- 数组的长度一旦确定,就不能修改。
- 我们可以直接通过下标(或索引)的方式调用指定位置的元素。
- java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。
2、数组的分类
① 按照维数:一维数组、二维数组、三维数组…等
② 按照数组元素的类型:基本数据类型元素的数组、引用数据类型元素的数组
4.2、一维数组
1、数组的声明和初始化
- 数组必须先声明之后才能初始化,数组一旦初始化完成,其长度就确定了。
//数组的声明:Java语言中声明数组时不能指定其长度(数组中元素的个数)
数据类型[] 数组名,如:int[] arr1;
//数组的初始化
//静态初始化:数组的初始化和数组元素的赋值操作同时进行
数组名 = new 数据类型[]{元素1,元素2,...};
如: arr1 = new int[]{1,2,3,4};
//动态初始化:数组的初始化和数组元素的赋值操作分开进行
数组名 = new 数据类型[数组长度];
如: arr1 = new int[3];
arr1[0] = 1;
arr1[1] = 2;
arr1[2] = 3;
//声明的同时初始化数组,如:
int[] arr2 = new int[]{1,2,3,4};
int[] arr3 = new int[3];
arr3[0] = 1;
arr3[1] = 2;
arr3[2] = 3;
2、数组的使用
- 数组初始化后,才可以引用数组中的每个元素;
- 数组元素的引用,获取数组指定位置的元素:数组名[数组元素下标];
- 数组元素下标从0开始;长度为 n 的数组合法下标取值范围: 0 —>n-1;
- 每个数组都有一个属性length指明它的长度,例如:a.length 指明数组a的长度(元素个数);
//数组的引用
public class ArrayTest {
public static void main(String[] args) {
//1. 一维数组的声明和初始化
int[] arr1;//声明
//1.1 静态初始化:数组的初始化和数组元素的赋值操作同时进行
arr1 = new int[]{1001,1002,1003,1004};
//1.2动态初始化:数组的初始化和数组元素的赋值操作分开进行
String[] arr2 = new String[5];
/* 错误的写法:
int[] arr1 = new int[];
int[5] arr2 = new int[5];
int[] arr3 = new int[3]{1,2,3};
*/
//正确的写法:
int[] arr4 = {1,2,3,4,5};//类型推断
//2.调用数组的指定位置的元素:通过角标的方式调用。
//数组的角标(或索引)从0开始的,到数组的长度-1结束。
arr2[0] = "路飞";
arr2[1] = "陈赫";
arr2[2] = "周杰伦";
arr2[3] = "刘德华";
arr2[4] = "吴彦祖";
//3.获取数组的长度。
//数组名.length
System.out.println(arr1.length);//4
System.out.println(arr2.length);//5
//4.遍历数组
/*
System.out.println(names[0]);
System.out.println(names[1]);
System.out.println(names[2]);
System.out.println(names[3]);
System.out.println(names[4]);
*/
for(int i = 0;i < names.length;i++){
System.out.println(names[i]);
}
}
}
3、数组元素的默认初始化值
数组元素是整型:0
数组元素是浮点型:0.0
数组元素是char型:0或’\u0000’,而非’0’
数组元素是boolean型:false *
数组元素是引用数据类型:null
public class ArrayTest1 {
public static void main(String[] args) {
//数组元素的默认初始化值
int[] arr = new int[4];
System.out.println(arr[0]);// 0
System.out.println("**********");
short[] arr1 = new short[4];
System.out.println(arr1[0]);// 0
System.out.println("**********");
float[] arr2 = new float[5];
System.out.println(arr2[0]);// 0.0
System.out.println("**********");
char[] arr3 = new char[4];
System.out.println("----" + arr3[0] + "----"); //---- ----
if(arr3[0] == 0){
System.out.println("hello Array!");
}
System.out.println("**********");
boolean[] arr4 = new boolean[5];
System.out.println(arr4[0]);// false
System.out.println("**********");
String[] arr5 = new String[5];
System.out.println(arr5[0]);// null
}
}
4.3、二维数组
- 对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。
- 其实,从数组底层的运行机制来看,其实没有多维数组。
1、声明和初始化
//声明 + 初始化:Java语言中声明数组时不能指定其长度(数组中元素的个数)
数据类型[][] 数组名 = new 数据类型{数组1,数组2,...};
如: int[][] arr = new int{{1,2},{3,4},{5,6}};
数据类型[][] 数组名 = new 数据类型[元素个数][元素个数];
如: int[][] arr = new int[2][3];
数据类型[][] 数组名 = new 数据类型[元素个数][];
如: int[][] arr = new int[2][];
public class ArrayTest2 {
public static void main(String[] args) {
//1.二维数组的声明和初始化
int[] arr = new int[]{1,2,3};//一维数组
//静态初始化
int[][] arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}};
//动态初始化1
String[][] arr2 = new String[3][2];
//动态初始化2
String[][] arr3 = new String[3][];
/* 错误写法
String[][] arr4 = new String[][4];
String[4][3] arr5 = new String[][];
int[][] arr6 = new int[4][3]{{1,2,3},{4,5},{6,7,8}};
*/
//正确的写法:
int[] arr4[] = new int[][]{{1,2,3},{4,5,9,10},{6,7,8}};
int[] arr5[] = {{1,2,3},{4,5},{6,7,8}};//自动类型推断
//2.调用数组的指定位置的元素
System.out.println(arr1[0][1]);//2
System.out.println(arr2[1][1]);//null
arr3[1] = new String[4];
System.out.println(arr3[1][0]);
//3.获取数组的长度
System.out.println(arr4.length);//3
System.out.println(arr4[0].length);//3
System.out.println(arr4[1].length);//4
//4.如何遍历二维数组
for(int i = 0;i < arr4.length;i++){
for(int j = 0;j < arr4[i].length;j++){
System.out.print(arr4[i][j] + " ");
}
System.out.println();
}
}
}
- 注意特殊写法情况:int[] x,y[]; x是一维数组,y是二维数组。
- Java中多维数组不必都是规则矩阵形式
4.4、数组中涉及的常见算法
- 数组元素的赋值(杨辉三角、回形数等)
- 求数值型数组中元素的最大值、最小值、平均数、总和等
- 数组的复制、反转、查找(线性查找、二分法查找)
- 数组元素的排序算法(内部排序和外部排序)
* 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
* 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。