Java SE 01

目录

  • Java SE 01
  • 一、计算机与Java语言概述
  • 1. 计算机的体系结构
  • 2. Java语言的概述
  • 二、变量和数据类型
  • 1. 变量
  • 2. 数据类型
  • 三、运算符
  • 1. 运算符分类
  • 2. 运算符优先级
  • 四、流程控制
  • 1. 分支结构
  • 2. 循环结构
  • 五、数组
  • 1. 内存结构
  • 2. 一维数组
  • 3. 二维数组

一、计算机与Java语言概述

1. 计算机的体系结构

Java 如何通过变量获取枚举值名称 java 获取变量类型_System

2. Java语言的概述

  • JDK 、JRE、javac.exe、java.exe
  • Java开发工具包( Java Development Kit),Java开发人士需要下载和安装JDK

JDK目录结构:

• bin目录 - 该目录下主要存放JDK的各种工具命令。

• conf目录 - 该目录下主要存放jdk的相关配置文件。

• include目录 - 该目录下主要存放了一些平台的头文件。

• jmods目录 - 该目录下主要存放了JDK的各种模块。

• legal目录 - 该目录下主要存放了JDK各模块的授权文档。

• lib目录 - 该目录下主要存放了JDK工具的一些补充jar包和源代码。

  • Java SE运行时环境(Java SE Runtime Environment),提供了运行Java应用程序所必须的软件环境等。无论是开发还是运行Java应用都必须安装。
  • JDK包括JRE和编译器等开发工具
  • JRE包括运行类库和JVM
  • javac.exe - 编译器,主要用于将高级Java源代码翻译成字节码文件
  • java.exe - 解释器,主要用于启动JVM对字节码文件进行解释并执行
  • 注释
  • 注释用于进行代码说明,是给程序员看的文字描述,编译器会忽略注释。
  • 基本分类
// 单行注释 ,从 // 开始,到本行结束,都是注释。 
/* */ 多行注释,从/* 开始,到*/结束,中间所有都是注释。 
/** */ 多行/文档注释,从/**开始,到*/结束,是一种支持提取的注释

多行注释不允许嵌套使用!

  • Java跨平台的原理
    Java字节码可以通过JVM翻译为具体平台能够执行的机器指令。由于Sun定义了JVM规范,而且不同的操作系统大多提供了JVM实现,才使得相同的一个字节码文件可以在不同的系统上运行,从而使Java赢得了“一次编译,到处使用”的美名。

二、变量和数据类型

1. 变量

  1. 变量的声明方式
    数据类型 变量名 = 初始值;

其中=初始值可以省略,但;不可以省略

  1. 标识符的命名规则
  • 由数字、字母、下划线以及$等组成,其中数字不能开头
  • 不能使用Java关键字
  • 区分大小写,长度没有限制但不宜过长
  • 尽量做到见名知易,支持中文但不推荐使用
  • 标识符可以给类、变量、属性、方法、包起名字
  1. 示例Code:变量声明注意事项
public class VarTest {	
	public static void main(String[] args) {
		// 1.声明一个变量并初始化   数据类型 变量名 = 初始值;
        int age = 18;
		// 2.打印变量的数值   + 字符串连接符  用于将两边的内容拼接/连接起来结果还是字符串
		System.out.println("age = " + age); // age = 18
		
		System.out.println("-----------------------------------------------------");
		// 3.使用变量的注意事项
		// 3.1 使用变量之前需要声明
		// System.out.println("name = " + name); // 错误: 找不到符号 
		// 3.2 使用变量之前需要初始化
		//String name;
		//System.out.println("name = " + name); // 错误: 可能尚未初始化变量name
		String name = "奇点";
		System.out.println("name = " + name); // name = 奇点
		// 3.3 变量不能重复声明
		//int age = 17; // 错误: 已在方法 main(String[])中定义/声明了变量 age
		
        //int aGe = 17;
		//int fjakjf3fjdlakjfa7987jfkdajlkf2427897fdjafjalkl89809fdjafjlj = 10;//变量名长度不限制,但不宜过长
		//int 年龄 = 16;//Java中可以使用中文声明变量和初始化
	}
}

2. 数据类型

  1. Java数据类型分为两大类
  • 基本数据类型
    byte、short、int、long 、float、double、boolean、char
  • 引用数据类型
    数组、类、接口、枚举、注解
  1. 常用的进制和进制转换
  1. 十进制-45转换为二进制的结果是
    十进制45转换为二进制:0010 1101
    按位取反:1101 0010
    再加1:1101 0011

负十进制转二进制:十进制绝对值转换为二进制,然后按位取反再加1

  1. 负二进制11010011转换为十进制的结果是-45
    先减1:1101 0010
    按位取反:0010 1101
    转换为十进制:45
    添加负号:-45

负二进制转十进制:先减1再按位取反,合并为十进制数后添加负号

  1. 基本数据类型表示的整数范围
  • 字节:在计算机中单个字节表示八位二进制位,其中最高位(最左边)代表符号位,使用0代表非负数,使用1代表负数,具体表示的整数范围如下:
  • 非负数表示范围:0000 0000 ~ 0111 1111 => 0 ~ 127 => 0 ~ 2^7-1
  • 负数表示范围:1000 0000 ~ 1111 1111 => -128 ~ -1 => -2^7 ~ -2^0
  • 单个字节表示的整数范围是:-2^7 ~ 2^7-1,也就是-128 ~ 127.
  • 整形: Java语言中描述整数数据的类型有:byte、short、int、long,荐int类型
  • byte类型在内存空间中占1个字节,表示范围是:-2^7 ~ 2^7-1.
  • short类型在内存空间中占2个字节,表示范围是:-2^15 ~ 2^15-1.
  • int类型在内存空间中占4个字节,表示范围是:-2^31 ~ 2^31-1.
  • long类型在内存空间中占8个字节,表示范围是:-2^63 ~ 2^63-1.

在Java程序中直接写出的整数数据叫做直接量/字面值/常量,默认为int类型。若希望表达更大的直接量,则在直接量的后面加上l或者L,推荐L

long类型的方法intValue():可以实现将long类型数转换为int

  • 示例Code
public class IntTest {
	public static void main(String[] args) {
		// 1.声明一个byte类型的变量并初始化
		byte b1 = 25;
		//byte b1 = 250;     // 错误: 不兼容的类型: 从int转换到byte可能会有损失  250这样直接写出的整数数据叫做直接量/常量/字面值 默认为int类型 
		// 2.打印变量的数值
		System.out.println("b1 = " + b1); // b1 = 25
		
		System.out.println("---------------------------------------------");
		// 3.声明一个short类型的变量并初始化
		short s1 = 250;
		//short s1 = 250250;  // 错误:不兼容的类型:从int转换到short可能会有损失
		System.out.println("s1 = " + s1); // s1 = 250
		
		System.out.println("---------------------------------------------");
		// 4.声明一个int类型的变量并初始化
		int i1 = 250250;
		//int i1 = 2502505006; // 错误: 整数太大   默认为int类型,这个数据自身已经出错,无法表示
		//int i1 = 2502505006L;  // 错误:不兼容的类型:从long转换到int可能会有损失
		System.out.println("i1 = " + i1); // i1 = 250250
		
		System.out.println("---------------------------------------------");
		// 5.声明一个long类型的变量并初始化,若描述比long类型还大的数据则使用java.math.BigInteger类型
		long g1 = 2502505006L;
		System.out.println("g1 = " + g1); // g1 = 2502505006
		
		System.out.println("---------------------------------------------");
		// 6.请问下面的代码是否有错误?若有请指出并说明原因
		//int i2 = 25;
		//byte b2 = i2;  // 错误: 不兼容的类型: 从int转换到byte可能会有损失
		//System.out.println("b2 = " + b2);
		
	}
}
  • 浮点类型: Java语言中用于描述小数数据的类型:float 和 double,推荐double类型
  • float类型在内存空间占4个字节,叫做单精度浮点数,可以表示7位有效数字,范围:-3.403E38~3.403E38。
  • double类型在内存空间占8个字节,叫做双精度浮点数,可以表示15位有效数字,范围:-1.798E308~1.798E308。

Java程序中直接写出的小数数据叫做直接量,默认为double类型,若希望表达float类型的直接量,则需要在直接量的后面加上f或者F.

  • 示例Code
public class DoubleTest {
	
	public static void main(String[] args) {
		
		// 1.声明一个float类型的变量并初始化
		//float f1 = 3.1415926;   // 错误: 不兼容的类型: 从double转换到float可能会有损失   小数数据叫做直接量,默认为double类型
		float f1 = 3.1415926f;
		// 2.打印变量的数值
		System.out.println("f1 = " + f1); // f1 = 3.1415925     一般是7位有效数字
		
		System.out.println("---------------------------------------------------------");
		// 3.声明一个double类型的变量并初始化
		double d1 = 3.1415926;
		System.out.println("d1 = " + d1); // d1 = 3.1415926     一般是15位有效数字
		
		System.out.println("---------------------------------------------------------");
		// 4.笔试考点
		System.out.println(0.1 + 0.2);  // 0.30000000000000004  运算时可能会有误差,若希望实现精确运算则借助java.math.BigDecimal类型 
	}
}
  • 布尔:Java语言中用于描述真假信息类型有:boolean,数值只有:true 和 false。
  • 布尔类型在内存空间中所占大小没有明确的规定,可以认为是1个字节。
  • 字符: Java语言中用于描述单个字符的数据类型:char类型。如:'a'、'中'等。
  • char类型在内存空间中占2个字节并且没有符号位,表示的范围是:0 ~ 65535,由于现实生活中很少有数据能够被单个字符描述,因此以后的开发中更多的使用由多个字符串起来组成的字符串,使用String类型加以描述,如:“hello”、“奇点”等。

字符类型不能直接存储,所以使用了ASCII表中的编号 ,将编号存储起来

常见的编号:'0' - 48 'A' - 65 'a' - 97 空格 - 32 换行符 - 10

Java字符类型采用Unicode字符集编码。Unicode是世界通用的定长字符集,所有的字符都是16位

常见的转义字符:\n -> 换行符\" -> "\' -> ' \\ -> \\t -> 制表符

  • 示例Code
public class CharTest {
	public static void main(String[] args) {
		// 1.声明一个char类型的变量并初始化
		char c1 = 'a';
		// 2.打印变量的数值
		System.out.println("c1 = " + c1); // c1 = a   
		System.out.println("对应的编号是:" + (int)c1); // 表示将char类型的c1强制转换为int类型并打印   97 
		
		System.out.println("-------------------------------------------------------------------------");
		// 2.声明一个char类型的变量并初始化
		char c2 = 98;
		System.out.println("c2 = " + c2); // c2 = b   
		System.out.println("对应的编号是:" + (int)c2); // 98
		
		System.out.println("-------------------------------------------------------------------------");
		// 3.使用Unicode字符集来表示一下我的名字   奇点  对应的编号是: \u5947\u70b9
		char c3 = '\u5947';
		char c4 = '\u70b9';
		System.out.println("最终的结果是:" + c3 + c4); // 奇点
		
		System.out.println("-------------------------------------------------------------------------");
		// 4.特殊字符的使用   双引号本身有2个含义:a.字符串的开头和结尾标志    b.双引号自身    \ 转义就是转换原有的含义
		System.out.println("我想过过\"过过过过的生活!");   //  \"  - "
		System.out.println("我想过过\'过过过过的生活!");
		System.out.println("我想过过\\过过过过的生活!");
		System.out.println("我想过过\t过过过过的生活!");
		System.out.println("我想过过\n过过过过的生活!");
	}
}
  1. 基本数据类型之间的转换
  • 自动类型转换:自动类型转换主要指从小类型到大类型之间的转换
  • 强制类型转换:其中强制类型转换主要指从大类型到小类型之间的转换
    目标类型 变量名 = (目标类型)源类型变量名;

大类型中存储的数据范围超过小类型的范围,大转小会数据溢出

  • 示例Code
public class TransformTest {
	
	public static void main(String[] args) {
		
		// 1.声明两个变量并初始化
		byte b1 = 10;
		short s1 = 20;
		// 2.打印变量的数值
		System.out.println("b1 = " + b1); // b1 = 10
		System.out.println("s1 = " + s1); // s1 = 20
		
		System.out.println("----------------------------------------------");
		// 3.实现自动类型转换的使用
		// 表示将变量b1的数值赋值给变量s1,并覆盖变量s1中原来的数值,相当于从byte类型到short类型的转换,小到大  自动转换
		s1 = b1;
		System.out.println("b1 = " + b1); // b1 = 10
		System.out.println("s1 = " + s1); // s1 = 10
		
		System.out.println("----------------------------------------------");
		// 4.实现强制类型转换的使用
		// 表示将变量s1的数值赋值给变量b1,并覆盖变量b1中原来的数值,相当于从short类型到byte类型的转换,大到小  强制转换
		//b1 = s1;   // 错误: 不兼容的类型: 从short转换到byte可能会有损失
		s1 = 128;    // 故意加该行代码      128:0000 0000 1000 0000  => 1000 0000 => 0111 1111 => 1000 0000 => 128 => -128
		b1 = (byte)s1;
		System.out.println("b1 = " + b1); // b1 = 10   -128 
		System.out.println("s1 = " + s1); // s1 = 10   128
	}
}

三、运算符

1. 运算符分类

  1. 算术运算符
  • +-*\%
  • 示例Code
public class ArithmeticTest {
	public static void main(String[] args) {
		// 1.声明两个int类型的变量并初始化
		//int ia = 6, ib = 2;       // 表示声明两个int类型的变量ia和ib,不推荐使用
		int ia = 6;                 // 推荐该方式,提高了代码的可读性
		int ib = 2;
		System.out.println("ia = " + ia); // ia = 6
		System.out.println("ib = " + ib); // ib = 2
		
		System.out.println("----------------------------------------");
		// 2.使用上述变量实现算术运算符的使用   +  -  *  /  %
		// 表示声明变量ic来记录ia与ib的和
		int ic = ia + ib;
		System.out.println("ic = " + ic); // ic = 8
		// 其中ia+ib这个整体叫做表达式  ia、ib叫做操作数   +叫做操作符/运算符
		System.out.println(ia + ib);  // 8
		System.out.println(ia - ib);  // 4
		System.out.println(ia * ib);  // 12
		System.out.println(ia / ib);  // 3
		System.out.println(ia % ib);  // 0
		
		System.out.println("----------------------------------------");
		// 3.注意事项
		// 3.1 当两个整数相除时结果只保留整数部分,丢弃小数部分
		System.out.println(5 / 2); // 2
		
		System.out.println("----------------------------------------");
		// 3.2 若希望保留小数部分该如何处理?
		// 处理方式一:使用强制类型转换将其中一个操作数转换为double类型再运算即可
		System.out.println((double)5 / 2);   // 2.5
		System.out.println(5 / (double)2);   // 2.5
		System.out.println((double)5 / (double)2); // 2.5
		System.out.println((double)(5 / 2)); // 2.0
		// 处理方式二:让其中一个操作数乘以1.0即可(推荐)
		System.out.println(5*1.0 / 2); // 2.5
		System.out.println(5.0 / 2);   // 2.5   ia.0 错误的表示
		
		System.out.println("----------------------------------------");
		// 3.3 0不能作除数
		//System.out.println(5 / 0); // 编译ok,运行发生java.lang.ArithmeticException(算术异常 记住): / by zero
		System.out.println(5 / 0.0); // Infinity 无穷
 		System.out.println(0 / 0.0); // NaN Not a Number 
	}
}
  1. 字符串连接运算符
  • + 可以实现字符串的连接,同时可以实现字符串与其他数据类型“相连”
  • 示例Code
public class ArithmeticTimeTest {
	public static void main(String[] args) {
		// 1.提示用户输入一个正整数的秒数并使用变量记录
		System.out.println("请输入一个正整数的秒数:");
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();
		
		// 2.将正整数的秒数拆分为时分秒后并使用变量记录
		// 3666秒 => 1小时1分钟6秒钟
		// 3666 / 3600 = 1 小时     3666 % 3600 = 66 / 60 = 1 分钟     3666 % 60 = 6 秒钟 
		int hour = num / 3600;      // 拆分小时数
		int min = num % 3600 / 60;  // 拆分分钟数
		int sec = num % 60;         // 拆分秒数
		
		// 3.打印最终的拆分结果
		System.out.println(num + "秒转换为" + hour + "小时" + min + "分钟" + sec + "秒钟");
		
		System.out.println("---------------------------------------------------------------------");
		// 4.+既可以作为字符串连接符,又可以作为加法运算符
		// 只要+两边的操作数中有一个操作数是字符串类型,则该+就被当做字符串连接符处理,否则当做加法运算符处理
		System.out.println(hour + min + sec);       // 8
		System.out.println(hour + min + sec + "");  // 8
		System.out.println(hour + min + "" + sec);  // 26
		System.out.println(hour + "" + min + sec);  // 116
		System.out.println("" + hour + min + sec);  // 116
		System.out.println("" + (hour + min + sec));// 8
	}
}
  1. 关系比较运算符
  • 所有以关系运算符作为最终运算的表达式结果一定是boolean类型
  • 示例Code
public class RelationJudgeTest {
	public static void main(String[] args) {
		// 1.提示用户输入一个整数并使用变量记录
		System.out.println("请输入一个整数:");
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();
		
		// 2.判断该整数是否为负数并打印
		boolean b1 = num < 0;
		System.out.println("b1 = " + b1);
		System.out.println(num < 0);
	}
}
public class RelationTest {	
	public static void main(String[] args) {		
		// 1.声明两个int类型的变量并初始化
		int ia = 5;
		int ib = 2;
		
		// 2.使用变量实现关系运算符的使用并打印结果
		boolean b1 = ia > ib;
		System.out.println("b1 = " + b1); // b1 = true
		System.out.println(ia > ib);   // 是否大于       true
		System.out.println(ia >= ib);  // 是否大于等于   大于或者等于  true
		System.out.println(ia < ib);   // 是否小于       false
		System.out.println(ia <= ib);  // 是否小于等于   false
		System.out.println(ia == ib);  // 是否等于       false
		System.out.println(ia != ib);  // 是否不等于     true
	}
}
  1. 自增减运算符
  • 只能用于变量,常数不可以
  • 示例Code
public class SelfTest {
	public static void main(String[] args) {
		
		// 1.声明一个int类型的变量并初始化
		int ia = 10;
		// 2.打印变量的数值
		System.out.println("ia = " + ia); // ia = 10
		
		System.out.println("---------------------------------------------");
		// 3.实现自增减运算符的使用
		// 表示让变量ia自身的数值加1,并覆盖该变量原来的数值   
		ia++;   // ia = ia + 1;
		System.out.println("ia = " + ia); // ia = 11
		
		// 表示让变量ia自身的数值加1,并覆盖该变量原来的数值  
		++ia;
		System.out.println("ia = " + ia); // ia = 12
		
		// 表示让变量ia自身的数值减1,并覆盖该变量原来的数值
		--ia;
		System.out.println("ia = " + ia); // ia = 11
		
		ia--;
		System.out.println("ia = " + ia); // ia = 10
		
		System.out.println("---------------------------------------------");
		// 4.简单的变换
		// 其中ia++这个整体叫做表达式   其中ia叫做操作数/变量       也就是ia++和ia表示不同的含义,因此所占的内存空间应该不同
		// 下面的代码是在打印表达式的结果
		// 后++表示先让变量ia的数值作为整个表达式的最终结果,然后再让ia变量自身的数值加1
		System.out.println(ia++);         // 10
		System.out.println("ia = " + ia); // 11
		// 前++表示先让变量自身的数值加1,然后再让变量的数值作为整个表达式的结果
		System.out.println(++ia);         // 12
		System.out.println("ia = " + ia); // 12
		
		System.out.println("---------------------------------------------");
		// 5.笔试考点
		int ib = ia++;
		System.out.println("ib = " + ib); // 12
		System.out.println("ia = " + ia); // 13
		int ic = ++ia;
		System.out.println("ic = " + ic); // 14
		System.out.println("ia = " + ia); // 14
		
		//                  14  + 16
		System.out.println(ia++ + ++ia);  // 30
		System.out.println("ia = " + ia); // 16
		
	}
}
  1. 逻辑运算符
  • &&||!
  • 逻辑运算符的操作数均为boolean表达式
  • 逻辑运算符短路特性
  • 对于逻辑与运算符来说,若第一个表达式(左边)为假则结果为假,此时跳过第二个表达式
  • 对于逻辑或运算符来说,若第一个表达式(左边)为真则结果为真,此时跳过第二个表达式
  • 示例Code
public class LogicTest {	
	public static void main(String[] args) {	
		// 1.声明两个boolean类型的变量并初始化
		boolean b1 = true;
		boolean b2 = false;
		// 2.打印变量的数值
		System.out.println("b1 = " + b1); // b1 = true
		System.out.println("b2 = " + b2); // b2 = false
		
		System.out.println("---------------------------------------------");
		// 3.使用上述变量实现逻辑运算符的使用
		boolean b3 = b1 && b2;
		System.out.println("b3 = " + b3); // false
		System.out.println(b1 && b2); // false   并且
		System.out.println(b1 || b2); // true    或者
		System.out.println(!b1);  // false       取反
		System.out.println(!b2);  // true
		
		System.out.println("---------------------------------------------");
		// 4.测试一下短路特性
		int ia = 3;
		int ib = 5;
		// 对于逻辑与运算符来说,若第一个条件为假则整个表达式为假,此时跳过第二个表达式不执行
		boolean b4 = (++ia == 3) && (++ib == 5);
		System.out.println("b4 = " + b4); // false
		System.out.println("ia = " + ia); // 4
		System.out.println("ib = " + ib); // 5
		
		// 对于逻辑或运算符来说,若第一个条件为真则整个表达式为真,此时跳过第二个表达式不执行
		boolean b5 = (++ia == 5) || (++ib == 5);
		System.out.println("b5 = " + b5); // true
		System.out.println("ia = " + ia); // 5
		System.out.println("ib = " + ib); // 5
	}
}
  1. 条件/三目运算符
  • 判断条件表达式是否成立,若成立则执行表达式1,否则执行表达式2
    条件表达式? 表达式1: 表达式2
  • 示例Code
public class LogicJudgeTest {
	public static void main(String[] args) {
		// 1.提示用户输入一个正整数并使用变量记录
		System.out.println("请输入一个正整数:");
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();
		
		// 2.使用逻辑运算符判断是否为三位数并打印    >= 100   <= 999   &&
		//System.out.println(100 <= num <= 999); // 错误: 二元运算符 '<=' 的操作数类型错误
		// 逻辑运算符主要用于连接多个关系运算符作为最终运算的表达式,用于实现多条件的连接
		System.out.println(100 <= num && num <= 999);
		// 使用三目运算符来判断是否为三位数
		System.out.println(num + ((100 <= num && num <= 999)? "是三位数": "不是三位数"));
	}
}
public class ThreeEyeTest {
	public static void main(String[] args) {	
		// 1.提示用户输入两个整数并使用变量记录
		System.out.println("请输入两个整数:");
		Scanner sc = new Scanner(System.in);
		int ia = sc.nextInt();
		int ib = sc.nextInt();
		
		// 2.使用三目运算符找到最大值并打印
		int max = ia > ib? ia: ib;
		System.out.println("最大值是:" + max);
		System.out.println("最大值是:" + (ia > ib? ia: ib));
	}
}
  1. 赋值运算符
  • = 表示赋值运算符,用于将=右边的数据赋值给=左边的变量,覆盖变量原来的数值
  • 赋值表达式本身也有值,其本身之值即为所赋之值
  • 赋值运算符与算术运算符结合的赋值运算符
    += -=*= /=
  • 示例Code
public class AssignTest {
	public static void main(String[] args) {
		// 1.声明一个int类型的变量并初始化
		int ia = 3;
		// 2.打印变量的数值
		System.out.println("ia = " + ia); // ia = 3
		
		System.out.println("-----------------------------------");
		// 3.简单赋值运算符的使用
		// 表示将数据5赋值给变量ia并且覆盖变量ia原来的数值
		ia = 5;
		System.out.println("ia = " + ia); // ia = 5
		// 下面的代码是在打印表达式的结果
		System.out.println( ia = 5 ); // 5
		System.out.println("ia = " + ia); // ia = 5
		int ib = ia = 6;
		System.out.println("ia = " + ia); // ia = 6
		System.out.println("ib = " + ib); // ib = 6
		int ic;
		ic = ib = ia = 8;
		System.out.println("ia = " + ia); // ia = 8
		System.out.println("ib = " + ib); // ib = 8
		System.out.println("ic = " + ic); // ic = 8
		
		System.out.println("-----------------------------------");
		// 4.复合赋值运算符的使用
		//ia = ia + 2;  目前推荐使用该方式
		ia += 2;        // 简化写法,从结果上来看是等价的
		System.out.println("ia = " + ia); // ia = 10
		
		System.out.println("-----------------------------------");
		// 5.笔试考点1
		byte b1 = 10;
		System.out.println("b1 = " + b1); // b1 = 10
		//b1 = b1 + 2; // 错误: 不兼容的类型: 从int转换到byte可能会有损失         byte + int 相加结果还是int类型
		//b1 = b1 + (byte)2; // 错误: 不兼容的类型: 从int转换到byte可能会有损失   byte + byte 相加结果还是int类型  编译器优化
		//b1 = (byte)(b1 + 2); // 强制类型转换,将int类型转换为byte
		b1 += 2; // 真正等价于b1 = (byte)(b1 + 2);
		System.out.println("b1 = " + b1); // b1 = 12
		
		System.out.println("-----------------------------------");
		// 6.笔试考点2
		//ia == 2; - 表示判断变量ia的数值是否等于2
		//2 == ia; - 表示判断2是否等于变量ia的数值,从结果上来说等价,推荐该方式
		//ia = 2;  - 表示将2赋值给变量ia,覆盖变量ia原来的数值
		//2 = ia;  //- 编译报错  错误: 意外的类型
	}
}
  1. 移位运算符
  • << 左移运算符,用于将数据的二进制位向左移动,右边使用0补充
  • >> 右移运算符,用于将数据的二进制位向右移动,左边使用符号位补充
  • >>> 表示逻辑右移运算符,用于将数据的二进制位向右移动,左边使用0补充
  • 示例Code
public class MoveBitTest {
	public static void main(String[] args) {
		// 1.声明一个byte类型的变量并初始化
		byte b1 = 13;
		// 2.打印变量的数值
		System.out.println("b1 = " + b1); // b1 = 13
		
		System.out.println("---------------------------------------------------");
		// 3.移位运算符的使用
		// 13的二进制是:... 0000 1101  => 左移1位的结果是:... 0001 1010 => 换算为十进制整数是:26
		//byte b2 = b1 << 1; // 错误: 不兼容的类型: 从int转换到byte可能会有损失   自动提升为int类型,也就是32位二进制
		byte b2 = (byte)(b1 << 1); 
		System.out.println("b2 = " + b2); // 26
		System.out.println(b1 << 1); // 26    左移1位相当于当前整数的数值*2
		System.out.println(b1 << 2); // 52    左移2位相当于当前整数的数值*4
		
		System.out.println("---------------------------------------------------");
		// 13的二进制是:... 0000 1101 => 右移1位的结果是:... 0000 0110 => 换算为十进制整数是:6
		System.out.println(b1 >> 1); // 6     右移1位相当于当前整数的数值/2
		System.out.println(b1 >> 2); // 3     右移2位相当于当前整数的数值/4
		
		System.out.println("---------------------------------------------------");
		// 逻辑右移   对于非负数来说,逻辑右移和右移的效果一致
		System.out.println(b1 >>> 2); // 3  
	}
}
  1. 位运算符
  • 位与&、位或|、位取反~、位异或^
  • 示例Code
public class BitTest {
	public static void main(String[] args) {
		// 1.声明两个byte类型的变量并初始化
		byte b1 = 11;
		byte b2 = 13;
		// 2.打印变量的数值
		System.out.println("b1 = " + b1); // b1 = 11
		System.out.println("b2 = " + b2); // b2 = 13
		
		System.out.println("---------------------------------------------------");
		// 3.实现位运算符的使用
		// b1的二进制为: 0000 1011          
		// b2的二进制为: 0000 1101
		System.out.println( b1 & b2);  // 按位与:同1为1,一0为0      按位与后的二进制为:0000 1001  => 转为十进制是:9
		System.out.println( b1 | b2);  // 按位或:一1为1,同0为0      按位或后的二进制为:0000 1111  => 转为十进制是:15
		System.out.println( b1 ^ b2);  // 按位异或:相同为0,不同为1  按位异或的二进制为:0000 0110  => 转为十进制是:6
		System.out.println( ~ b1);     // 按位取反:1为0,0为1         按位取反的二进制为:1111 0100 
		// 二进制1111 0100转为十进制 => 先减1: 1111 0011 => 按位取反:0000 1100 => 转为十进制:12  => 添加负号:-12
	}
}

2. 运算符优先级

  • 优先级概述
  • ()的优先级极高
  • =的优先级极低
  • 若无法确认优先级,则使用()来确保即可

四、流程控制

1. 分支结构

  1. if
  • 执行流程
    判断条件表达式是否成立
    => 若成立,则执行语句块;
    => 若不成立,则跳过语句块;
  • 示例Code
/*
    编程使用if分支结构查找两个整数中的最大值
 */

import java.util.Scanner; 
 
public class IfMaxTest {
	
	public static void main(String[] args) {
		
		// 1.提示用户输入两个整数并使用变量记录
		System.out.println("请输入两个整数:");
		Scanner sc = new Scanner(System.in);
		int ia = sc.nextInt();
		int ib = sc.nextInt();
		
		// 2.使用if分支结构找到最大值并打印
		// 方式一:使用两个if分支结构可以找到最大值
		/*
		if(ia >= ib) {
			System.out.println("最大值是:" + ia);
		}
		if(ia < ib) {
			System.out.println("最大值是:" + ib);
		}
		*/
		// 方式二:假设第一个数为最大值并记录  推荐方式  通用性
		int max = ia;
		if(ib > max) {
			max = ib;
		}
		System.out.println("最大值是:" + max);
	}
}
  1. ifelse
  • 执行流程
    判断条件表达式是否成立
    => 若成立,则执行语句块1;
    => 若不成立,则执行语句块2;
  1. ifelse ifelse
  • 执行流程
    判断条件表达式1是否成立
    => 若成立,则执行语句块1;
    => 若不成立,则判断条件表达式2是否成立
    => 若成立,则执行语句块2;
    => 若不成立,则执行语句块n;
  • 示例Code
/*
    编程使用if else if else分支结构判断考试成绩所在的等级
 */

import java.util.Scanner; 
 
public class IfScoreTest {
	
	public static void main(String[] args) {
		
		// 1.提示用户输入考试成绩并使用变量记录
		System.out.println("请输入您的考试成绩:");
		Scanner sc = new Scanner(System.in);
		int score = sc.nextInt();
		
		// 2.使用if else if else分支结构判断所在的等级并打印
		// 90 / 10 = 9;    91 / 10 = 9;  92 / 10 = 9;  99 / 10 = 9;   100 / 10 = 10;
		if(score >= 90 && score <= 100) {     // case 9:    case 10:  
			System.out.println("等级A");
		} else if(score >= 80) {              // case 8: 
			System.out.println("等级B");
		} else if(score >= 70) {              // case 7:
			System.out.println("等级C");
		} else if(score >= 60) {              // case 6:
			System.out.println("等级D");   
		} else {                              // default:
			System.out.println("等级E");
		}
	}
}
  1. switchcase
  • 执行流程
    计算变量/表达式的数值 => 判断是否匹配字面值1
    => 若匹配,则执行语句块1 => 执行break跳出当前结构
    => 若不匹配,则判断是否匹配字面值2
    => 若匹配,则执行语句块2 => 执行break跳出当前结构
    => 若不匹配,则执行语句块n
  • switch中支持的数据类型
    switch()中支持的数据类型有:byte、short、char以及int类型,从jdk1.5开始支持枚举类型,从jdk1.7开始支持String类型
  • 示例Code
/*
    编程使用switch case分支结构实现考试成绩的等级判断
 */

import java.util.Scanner; 
 
public class SwitchScoreTest {
	
	public static void main(String[] args) {
		
		// 1.提示用户输入考试成绩并使用变量记录  0 ~ 100
		System.out.println("请输入您的考试成绩:");
		Scanner sc = new Scanner(System.in);
		int score = sc.nextInt();
		
		// 2.使用switch case分支结构实现考试成绩的等级判断
		switch(score / 10) {
			case 10: //System.out.println("等级A"); //break;
			case 9:  System.out.println("等级A"); break; // case穿透  
			case 8:  System.out.println("等级B"); break;
			case 7:  System.out.println("等级C"); break;
			case 6:  System.out.println("等级D"); break;
			default: System.out.println("等级E"); //break;
		}
	}
}

2. 循环结构

  1. for
  • 执行流程
    执行初始化表达式 => 判断条件表达式是否成立
    => 成立则执行循环体 => 修改初始值表达式 => 判断条件是否成立
    => 若不成立,则循环结束
  • 示例Code
/*
    编程使用for循环打印三位数中的所有水仙花数
 */
public class ForWaterTest {
	
	public static void main(String[] args) {
	
		// 1.使用for循环打印所有的三位数
		for(int i = 100; i <= 999; i++) {
			
			// 3.拆分三位数中的各个数位上的数字
			// 123 / 100 = 1;        123 % 100 => 23 / 10 = 2;    123 % 10 = 3;
			int ia = i / 100;      // 拆分百位数
			int ib = i % 100 / 10; // 拆分十位数
			int ic = i % 10;       // 拆分个位数
			
			// 2.针对每个三位数都要判断该数是否为水仙花数,若是则打印,否则不打印
			// 判断该数是否等于各个数位的立方和
			if((ia*ia*ia + ib*ib*ib + ic*ic*ic) == i) {
				System.out.println("i = " + i);
			}
		}
	}
}
  • continue关键字
    continue语句用在循环体中,用于结束本次循环而开始下一次循环
  • break关键字
    break用于退出当前语句块,break用在循环体中用于退出循环
  • 死循环
    for(;;) 这种没有循环条件的循环叫做无限循环,俗称“死循环”
  • 双重for循环
  • 外层循环用于控制打印的行数,内层循环用于控制打印的列数,外层循环改一下,内层循环从头到尾跑一圈
  • 示例Code
/*
    编程使用双重for循环打印2 ~ 100之间的所有素数
 */
public class ForForPrimeTest {

   public static void main(String[] args) {

       // 1.使用for循环打印2 ~ 100之间的所有整数
       for(int i = 2; i <= 100; i++) {

           // 3.声明一个boolean类型的变量作为是否为素数的标记
           boolean flag = true;
           // 2.针对每一个当前的整数都要判断是否为素数,若是素数则打印,否则不打印
           // 判断一个数是否为素数的方法是:若该数不能被2到它本身-1之间的所有整数整除时,则证明该数是素数
           // 使用内层for循环用于控制2到该数自身-1之间的范围
           //for(int j = 2; j < i; j++) {
           // 只需要判断2到该数的平方根即可,因为随着除数的增大商必然减小,会造成重复的判断
           for(int j = 2; j <= Math.sqrt(i); j++) {
               // 使用当前数除以该循环中的每个数据并判断是否可以整除,只要找到一个可以整除的数据,则证明该数不是素数
               if(0 == i % j) {
                   flag = false;
                   break; // 跳出当前所在的内层循环,也就是不需要再继续除以下一个整数
               }
           }

           // 只可以打印素数
           if(flag) {
               System.out.println("i = " + i);
           }
       }
   }
}
/*
    编程使用双重for循环打印星星图案
 */
public class ForForStarTest {
	
	public static void main(String[] args) {
		
		// 1.打印第一个星星图案
		// 外层循环主要用于控制打印的行数
		for(int i = 1; i <= 5; i++) {
			// 内层循环主要用于控制打印的列数
			for(int j = 1; j <= 5; j++) {
				System.out.print("*");
			}
			System.out.println();
		}
		
		System.out.println("--------------------------------------------");
		// 2.打印第二个星星图案
		// 外层循环主要用于控制打印的行数
		for(int i = 1; i <= 5; i++) {
			// 内层循环主要用于控制打印的列数  也就是当前行的列数与当前行的行数是相等关系
			for(int j = 1; j <= i; j++) {
				System.out.print("*");
			}
			System.out.println();
		}
		
		System.out.println("--------------------------------------------");
		// 3.打印第三个星星图案
		// 外层循环主要用于控制打印的行数
		for(int i = 1; i <= 5; i++) {
			// 内层循环主要用于控制打印的列数  也就是当前行的列数与当前行的行数相加为6的关系
			for(int j = 1; j <= 6-i; j++) {
				System.out.print("*");
			}
			System.out.println();
		}
		
		System.out.println("--------------------------------------------");
		// 4.打印第四个星星图案
		// 外层循环主要用于控制打印的行数
		for(int i = 1; i <= 5; i++) {
			// 控制空格的个数
			for(int j = 1; j <= 5-i; j++) {
				System.out.print(" ");
			}
			// 内层循环主要用于控制打印的列数  也就是当前行的列数与当前行的行数为 2*i-1 的关系
			for(int j = 1; j <= 2*i-1; j++) {
				System.out.print("*");
			}
			System.out.println();
		}
	}
}

/*output:

*****
*****
*****
*****
*****
--------------------------------------------
*
**
***
****
*****
--------------------------------------------
*****
****
***
**
*
--------------------------------------------
    *
   ***
  *****
 *******
*********

*/
  • break关键字跳出多层循环
  • 示例Code
/*
    使用双重for循环打印九九乘法表
 */
public class ForForTableTest {

   public static void main(String[] args) {

       // 1.使用外层for循环控制打印的行数,一共9行
       outer:for(int i = 1; i <= 9; i++) {
           // 2.使用内层for循环控制打印的列数,最多9列,规律是:与当前行所在的行数相等
           for(int j = 1; j <= i; j++) {
               // 3.使用两个循环变量来拼接等式
               System.out.print(j + "*" + i + "=" + j*i + " ");
               // 4.当打印完毕6*6 = 36后结束整个打印
               if(6 == j) {
                   //break; // 主要用于跳出循环,但该关键字只能跳出当前所在的循环
                   break outer; // 表示可以跳出外层for循环
               }
           }
           System.out.println();
       }
   }
}
  1. while
  • 与for循环对比
    • while循环和for循环完全可以互换,当然推荐使用for循环
    • while循环更适合于明确循环条件但不明确循环次数的场合中
    • for循环更适合于明确循环次数或范围的场合中
    • while(true) 等价于 for(;😉 都表示无限循环
  • 示例Code
/*
    编程使用while循环实现任意正整数的反向输出
 */

import java.util.Scanner; 
 
public class WhileReverseTest {
	
	public static void main(String[] args) {
		
		// 1.提示用户输入一个正整数并使用变量记录  123
		System.out.println("请输入一个正整数:");
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();
		
		// 2.使用while循环进行拆分并打印
		//while(num > 0) {
			//System.out.print(num % 10);  // 拆分个位数
			//num /= 10;  // 丢弃个位数
		//}
		// 2.使用while循环拆分整数中的每个数字并记录到变量中
		int res = 0;
		int temp = num;  // 指定变量作为num的替身
		while(temp > 0) {
			res = res*10 + temp % 10; // 3     32   321
			temp /= 10;               // 12    1    0
		}
		
		// 3.打印逆序后的结果
		System.out.println(num + "逆序后的结果是:" + res);
	}
}
  1. do while
  • 使用场景
    do-while循环主要用于至少执行一次循环体的场合中

五、数组

1. 内存结构

  • 栈区:栈用于存放程序运行过程当中所有的局部变量。一个运行的Java程序从开始到结束会有多次变量的声明
  • 堆区:JVM会在其内存空间中开辟一个称为“堆”的存储空间,这部分空间用于存储使用new关键字创建的数组和对象
  • 创建数组时内存结构分析:
    数组名称作为一个某一类型局部变量在栈上,这个变量中存放了在堆内存中申请的一段连续空间(数组)的地址
  • 示例Code
/*
    编程实现数组之间元素的拷贝
 */
public class ArrayCopyTest {
	
	public static void main(String[] args) {
		
		// 1.声明一个初始值为11、22、33、44、55的一维数组
		int[] arr = {11, 22, 33, 44, 55};
		// 打印数组中的所有元素
		System.out.print("第一个数组中的元素有:");
		for(int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " "); // 11 22 33 44 55
		}
		System.out.println();
		
		System.out.println("----------------------------------------------------------");
		// 2.声明一个长度为3元素类型为int类型的一维数组
		int[] brr = new int[3];
		// 打印数组中的所有元素
		System.out.print("第二个数组中的元素有:");
		for(int i = 0; i < brr.length; i++) {
			System.out.print(brr[i] + " "); // 0 0 0
		}
		System.out.println();
		
		System.out.println("----------------------------------------------------------");
		// 3.将第一个数组中的中间3个元素赋值到第二个数组中
		/*
		brr[0] = arr[1];
		brr[1] = arr[2];
		brr[2] = arr[3];
		*/
		/*
		for(int i = 0; i < brr.length; i++) {
			brr[i] = arr[i+1];
		}
		*/
		// 可以直接使用Java官方提供的拷贝功能
		// 表示将数组arr中下标从1开始的3个元素拷贝到数组brr中下标从0开始的位置
		System.arraycopy(arr, 1, brr, 0, 3);
		// 打印第二个数组中的所有元素
		System.out.print("第二个数组中的元素有:");
		for(int i = 0; i < brr.length; i++) {
			System.out.print(brr[i] + " "); // 22 33 44
		}
		System.out.println();
		
		System.out.println("----------------------------------------------------------");
		// 4.笔试考点
		// 表示将变量arr的数值赋值给变量brr,覆盖变量brr中原来的数值
		// 数组名arr的内存空间中存放的是数据在堆区中的内存地址信息,赋值后让brr变量中存放了arr所指向堆区的内存地址
		// 也就是让brr和arr指向了同一块堆区空间,有本质上就是改变指向而已
		brr = arr;
		// 打印第二个数组中的所有元素
		System.out.print("第二个数组中的元素有:");
		for(int i = 0; i < brr.length; i++) {
			System.out.print(brr[i] + " "); //11 22 33 44 55 
		}
		System.out.println();	
		
	}
}

2. 一维数组

  • 一维数组的概述
  • 当需要在Java程序中记录多个类型相同的数据内容时,则声明一个一维数组即可,一维数组本质上就是在内存空间中申请一段连续的存储单元。
  • 数组是相同数据类型的多个元素的容器,元素按线性顺序排列,在Java语言中体现为一种引用数据类型
  • 调用数组的length属性可以获取数组的长度
  • 一维数组初始化方式
  • 基本类型的数组(数据元素为基本类型)创建后,其元素的初始值:
    byte、short、char、int、long为0;
    float和double为0.0;
    boolean为false。
  • 动态初始化:数据类型[] 数组名称 = new 数据类型[数组的长度];静态初始化:数据类型[] 数组名称 = new 数据类型 {初始值1, 初始值2, ...};

静态初始化中简化写法数据类型[] 数组名称 = {初始值1, 初始值2, ...};

  • 示例Code
/*
    编程实现一维数组的声明和使用
 */
public class ArrayTest {
	
	public static void main(String[] args) {
		
		// 1.声明一个长度为2元素类型为int类型的一维数组
		// 数据类型[] 数组名称 = new 数据类型[数组的长度];
		//int arr1[] = new int[2];    // 两种方式从结果上来说是一样的,不推荐使用
		//int num = 2;                // 声明一个初始值为2的变量 
		int[] arr1 = new int[2];      // 推荐该方式,更容易与变量的声明区分,提高了代码的可读性   动态方式
		
		// 2.打印一维数组的长度以及每个元素的数值
		System.out.println("数组的长度是:" + arr1.length); // 2   下标从0 ~ 1
		System.out.println("下标为0的元素是:" + arr1[0]);  // 0  默认值
		System.out.println("下标为1的元素是:" + arr1[1]); 	// 0  
        //System.out.println("下标为2的元素是:" + arr1[2]); 	// 编译ok,运行发生ArrayIndexOutOfBoundsException数组下标越界异常

		System.out.println("------------------------------------------------");
		// 3.使用for循环打印数组中的所有元素
		for(int i = 0; i < arr1.length; i++) {
			System.out.println("下标为" + i + "的元素是:" + arr1[i]); // 全是0
		}
		// 7.直接通过数组名来打印数组中的所有元素
		System.out.println("arr1 = " + arr1); // 地址信息
		
		System.out.println("------------------------------------------------");
		// 4.声明一个长度为5元素类型为double类型的一维数组
		double[] arr2 = new double[5];
		// 打印数组中每个元素值
		for(int i = 0; i < arr2.length; i++) {
			System.out.println("下标为" + i + "的元素是:" + arr2[i]); // 全是0.0 
		}
		
		System.out.println("------------------------------------------------");
		// 5.声明数组的同时就对数组中的元素进行初始化   静态方式的简化版
		char[] arr3 = {'a', 'b', 'c', 'd'};
		// 打印数组中的每个元素值
		for(int i = 0; i < arr3.length; i++) {
			System.out.println("下标为" + i + "的元素是:" + arr3[i]); // a b c d
		}
		
		System.out.println("------------------------------------------------");
		// 6.特殊的写法   静态方式
		boolean[] arr4 = new boolean[]{true, true, false, false};
		// 打印数组中的每个元素值
		for(int i = 0; i < arr4.length; i++) {
			System.out.println("下标为" + i + "的元素是:" + arr4[i]); // true true false false
		}
	}
}
  • 数组的优缺点
  • 可以直接通过下标(或索引)的方式访问指定位置的元素,速度很快。
  • 数组要求所有元素的类型相同。
  • 数组要求内存空间连续,并且长度一旦确定就不能修改。
  • 增加和删除元素时可能移动大量元素,效率低。
  • 数组工具类Arrays
  • 作用
    java.util.Arrays类可以实现对数组中元素的遍历、查找、排序等操作
  • 常用方法
  • 示例Code
/*
    编程实现数组工具类的使用
 */

import java.util.Arrays; 
 
public class ArraysTest {
	
	public static void main(String[] args) {
		
		// 1.声明一个初始值为10、20、30、40、50的一维数组
		int[] arr1 = {10, 20, 30, 40, 50};
		// 2.使用原始方式打印数组中的所有元素,要求打印格式为:[10, 20, 30, 40, 50]
		System.out.print("第一个数组中的元素有:[");
		for(int i = 0; i < arr1.length; i++) {
			// 当打印的元素是最后一个元素时,则直接打印元素本身即可
			if(arr1.length-1 == i) {
				System.out.print(arr1[i]);
			} else {
				// 否则打印元素后打印逗号加空格
				System.out.print(arr1[i] + ", ");
			}
		}
		System.out.println("]");
		
		System.out.println("---------------------------------------------------");
		// 3.使用数组工具类实现数组中所有元素的打印
		System.out.println("第一个数组中的元素有:" + Arrays.toString(arr1));  // [10, 20, 30, 40, 50]
		
		System.out.println("---------------------------------------------------");
		// 4.声明一个长度为5元素类型为int类型的一维数组
		int[] arr2 = new int[5];
		System.out.println("第二个数组中的元素有:" + Arrays.toString(arr2)); // [0, 0, 0, 0, 0]
		// 使用数组工具类中的fill方法实现数组中元素的填充并打印
		// 表示使用10来填充数组arr中的每个元素,也就是给数组中每个元素赋值为10
		Arrays.fill(arr2, 10);
		System.out.println("第二个数组中的元素有:" + Arrays.toString(arr2)); // [10, 10, 10, 10, 10]
		
		System.out.println("---------------------------------------------------");
		// 5.声明一个长度为5元素类型为int类型的一维数组并初始化
		int[] arr3 = new int[5];
		Arrays.fill(arr3, 10);
		System.out.println("第三个数组中的元素有:" + Arrays.toString(arr3)); // [10, 10, 10, 10, 10]
		// 判断该数组是否与上述数组相等并打印,若相同则打印true,否则打印false
		System.out.println(Arrays.equals(arr2, arr3)); // true
		// 修改数组3中的元素值
		arr3[4] = 20;
		System.out.println("第三个数组中的元素有:" + Arrays.toString(arr3)); // [10, 10, 10, 10, 20]
		System.out.println(Arrays.equals(arr2, arr3)); // false  要求内容要相同
		arr2[3] = 20;
		System.out.println("第二个数组中的元素有:" + Arrays.toString(arr2)); // [10, 10, 10, 20, 10]
		System.out.println(Arrays.equals(arr2, arr3)); // false  要求顺序要相同
	}
}
  • 一维数组应用案例
  • 示例Code
/*
    编程使用数组实现正整数中每个数字出现次数的统计
 */

import java.util.Scanner; 

public class ArrayCountTest {

  public static void main(String[] args) {

      // 1.提示用户输入一个正整数并使用变量记录
      System.out.println("请输入一个正整数:");
      Scanner sc = new Scanner(System.in);
      int num = sc.nextInt();

      // 2.准备一个长度为10元素类型int类型的一维数组,默认值为0
      int[] arr = new int[10];

      // 3.拆分正整数中的每个数字并统计到一维数组中
      int temp = num;
      while(temp > 0) {
          arr[temp%10]++;
          temp /= 10;
      }

      // 4.打印最终的统计结果
      for(int i = 0; i < arr.length; i++) {
          if(arr[i] > 0) {
              System.out.println("数字" + i + "出现了" + arr[i] + "次!");
          }
      }
  }
}

3. 二维数组

  • 二维数组概述
    二维数组本质上就是由多个一维数组摞在一起组成的数组,二维数组中的每个元素都是一维数组,而一维数组中的每个元素才是数据内容
  • 声明和初始化方式
  • 格式
    数据类型[][] 数组名称 = new 数据类型[行数][列数];数据类型[][] 数组名称 = {{元素1, 元素2,...}, ...};
  • 示例Code
/*
    编程实现二维数组的声明和使用
 */
public class ArrayArrayTest {
	
	public static void main(String[] args) {
		
		// 1.声明一个具有2行3列元素类型为int类型的二维数组
		int[][] arr1 = new int[2][3];
		// 打印数组中的每个元素
		// 使用外层for循环控制打印的行数
		for(int i = 0; i < arr1.length; i++) {
			// 使用内层for循环控制打印的列数
			for(int j = 0; j < arr1[i].length; j++) {
				System.out.print(arr1[i][j] + " "); // 全是0
			}
			System.out.println();
		}
		
		System.out.println("--------------------------------------------------");
		// 2.实现二维数组中元素的赋值
		int cnt = 1;
		// 使用外层for循环控制打印的行数
		for(int i = 0; i < arr1.length; i++) {
			// 使用内层for循环控制打印的列数
			for(int j = 0; j < arr1[i].length; j++) {
				arr1[i][j] = cnt++;
			}
		}
		// 使用外层for循环控制打印的行数
		for(int i = 0; i < arr1.length; i++) {
			// 使用内层for循环控制打印的列数
			for(int j = 0; j < arr1[i].length; j++) {
				System.out.print(arr1[i][j] + " "); // 1 2 3   4 5 6
			}
			System.out.println();
		}
		
		System.out.println("--------------------------------------------------");
		// 3.二维数组元素的初始化操作
		int[][] arr2 = {{11, 22, 33, 44}, {55, 66, 77, 88}};
		// 使用外层for循环控制打印的行数
		for(int i = 0; i < arr2.length; i++) {
			// 使用内层for循环控制打印的列数
			for(int j = 0; j < arr2[i].length; j++) {
				System.out.print(arr2[i][j] + " "); // 11 22 33 44   55 66 77 88
			}
			System.out.println();
		}
		
		System.out.println("--------------------------------------------------");
		// 4.考点
		int[][] arr3 = new int[3][];
		arr3[0] = new int[3];
		arr3[1] = new int[4];
		arr3[2] = new int[5];
	}
}
  • 二维数组应用案例
  • 示例Code
/*
    编程使用二维数组来实现杨辉三角的生成和遍历
 */

import java.util.Scanner; 
 
public class ArrayArrayTriangleTest {
	
	public static void main(String[] args) {
		
		// 1.提示用户输入一个行数并使用变量记录
		System.out.println("请输入一个行数:");
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();
		
		// 2.根据用户输入的行数来声明对应的二维数组
		int[][] arr = new int[num][];
		
		// 3.针对二维数组中的每个元素进行初始化,使用双重for循环
		// 使用外层for循环控制二维数组的行下标
		for(int i = 0; i < num; i++) {
			// 针对二维数组中的每一行进行内存空间的申请
			arr[i] = new int[i+1];
			// 使用内层for循环控制二维数组的列下标
			for(int j = 0; j <= i; j++) {
				// 当列下标为0或者列下标与当前行的行下标相等时,则对应位置的元素就是1
				if(0 == j || i == j) {
					arr[i][j] = 1;
				} else {
					// 否则对应位置的元素就是上一行当前列的元素加上上一行前一列的元素
					arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
				}
			}
		}
		
		// 4.打印最终生成的结果
		for(int i = 0; i < num; i++) {
			for(int j = 0; j <= i; j++) {
				System.out.print(arr[i][j] + " ");
			}
			System.out.println();
		}
	}
}
/*output:
请输入一个行数:
5

1 
1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
*/