Java
- 1、Scanner工具类
- 1.1 使用步骤
- 1.1.1 导包
- 1.1.2 创建Scanner对象
- 1.1.3 接收数据
- 1.2 Scanner练习
- 2 流程控制语句
- 2.1 分类
- 2.2顺序流程控制语句
- 2.3 选择流程控制语句
- 2.3.1 按照语法分类
- 2.3.2 按照分支个数分类
- 2.3.3 if分支语句的使用
- 2.3.4 switch分支语句的使用
- 2.4 循环流程控制语句
- 2.4.1 while循环
- 2.4.2 do...while循环
- 2.4.3 for循环
- 2.5 流程跳转语句
- 2.5.1 break
- 2.5.2 continue
- 2.5.3 return
- 2.6 循环嵌套经典案例
- 3 Random工具类
- 3.1 使用步骤
- 3.1.1 导包
- 3.1.2 使用new关键字创建随机数对象
- 3.1.3使用随机数对象方法获取随机数
- 3.2 猜数字案例
- 4 数组
- 4.1 分类
- 4.2 特点
- 4.3 一维数组的使用
- 4.3.1 声明
- 4.3.2 创建(初始化)
- 4.3.3 赋值
- 4.3.4 使用
- 4.4 索引
- 4.4.1 什么是索引
- 4.4.2 访问数组元素格式
- 4.5 案例
- 5 内存分配
- 5.1 Java中的内存分配
- 5.1.1 常量池
- 5.1.2 栈
- 5.1.3 堆
- 5.2 数组的内存分配
- 5.2.1 单个数组的内存分配
- 5.2.2 两个数组的内存分配
- 5.2.3 声明数组对象保存已有数组内存分配
- 6 数组排序练习
- 6.1 冒泡排序算法
- 6.2 选择排序算法
- 7 多维数组
- 7.1 多维数组的概念
- 7.2 二维数组的使用
- 7.2.1 声明
- 7.2.2 创建
- 7.2.3 赋值
- 7.2.4 使用
- 7.3 二维数组的遍历
- 7.4 二维数组的案例
- 7.4.1 使用二维数组根据输入数据创建保存杨辉三角
- 7.4.2 使用所学知识完成彩票0 ~ 13选五个数,1 ~ 7中选择一个数的生成并存储至数组。
- 7.4.3 猜拳游戏
- 8 方法(Method)
- 8.1 概念
- 8.2 方法基本使用
- 8.3 分类
- 8.3.1 无参数无返回值方法
- 8.3.2 有参数无返回值方法
- 8.3.3 无参数有返回值方法
- 8.3.4 有参数有返回值方法
- 8.4 调用
- 8.4.1 有无参数
- 8.4.2 有无返回值
- 8.4.3 方法执行流程
- 8.5 特点
- 8.6 方法扩展
- 8.7 方法重载
- 8.7.1 概念
- 8.7.2 为什么使用方法重载
- 8.7.3 方法重载的书写
- 8.7.4 方法重载的执行流程
1、Scanner工具类
Scanner键盘录入工具类,是Java开发与学习初期阶段,用于与程序进行简单交互的工具类,可以扫描与获取在控制台输入的数据。
1.1 使用步骤
1.1.1 导包
工具类由Java书写保存在指定位置,如果想使用必须从指定位置引入当前类中。
import java.util.Scanner;
//import 关键字 代表导入的意思
导包方式有:
- ①精确导入:知道使用的具体类,通过 包名.类名 的形式导入具体使用的类。 包名.类名
- ②全部导入:不知道具体使用的类或者需要使用指定包下所有的类。 包名.*
注意: 所有类默认导入java.lang包下的类 import java.lang.*;
1.1.2 创建Scanner对象
- 使用工具类创建具体使用的对象
- 语法:工具类 标识符 =new 工具类(系统输入);
Scanner sc = new Scanner (System.in);
//创建一个名为sc的扫描对象,用于扫描控制台系统输入的内容。
//sc表示变量名,其他均不可变
1.1.3 接收数据
- Java中对工具类方法使用提供的称之为方法。
- 使用方法为 工具类对象.方法名(参数)
int nextInt = sc.nextInt();
//获取控制台输入的下一个整数
String nextLine = sc.nextLine();
//获取控制台输入的下一行内容
注意: 两个方法不要连用,因为输入整数后的回车可能影响下一个获取一行的方法,如果必须这样使用可以额外创建工具类对象进行使用。
1.2 Scanner练习
案例:键盘输入月份 输出对应季节
import java.util.Scanner;
public class ScannerTest {
public static void main(String[] args) {
//键盘输入月份 输出对应季节
Scanner sc=new Scanner (System.in);
System.out.println("请输入月份:");
int month = sc.nextInt();
if(month>12||month<1){
System.out.println("你家有"+month+"月");
}else if(month>=3&&month<=5){
System.out.println(month+"月是春季");
}else if(month>=6&&month<=8){
System.out.println(month+"月是夏季");
}else if(month>=9&&month<=11){
System.out.println(month+"月是秋季");
}else{
System.out.println(month+"月是冬季");
}
}
}
思考:
代码书写时对于结果输出存在相同的多个,可不可以改为变量最后输出的形式?改写后的代码是否效率更高,思考原因。
2 流程控制语句
用于控制Java代码在程序执行过程中执行的顺序,可以通过各种的流程控制修改代码的执行流程完成一些特殊的需求。
2.1 分类
- 顺序流程控制语句
- 选择(分支)流程控制语句
- 循环流程控制语句
2.2顺序流程控制语句
顺序结构是Java程序默认的执行顺序,Java程序从上至下、从左至右逐条运行。
类默认执行main方法(主方法),如果没有书写其他流程控制语句,那么程序会安照书写顺序执行,在main方法执行结束后自动调用gc回收方法释放占用资源
- gc回收算法
①可达性分析法:当当前代码块执行结束后查看是否还有其他代码执行使用(先吃完不管,后吃完刷碗)。
②计数法:对于每个资源使用进行计算,默认为0.当当期使用收查看如果为0则回收。
2.3 选择流程控制语句
也称为分支流程控制语句,可以在代码书写时定义多个分支,在执行过程中根据条件表达式返回的结果,进行分支的执行。
2.3.1 按照语法分类
- if…else分支
- switch…case分支
2.3.2 按照分支个数分类
- 单分支
- 双分支
- 多分支
2.3.3 if分支语句的使用
- if单分支
当条件返回为true时,执行对应方法体,当条件返回false时不执行。
语法:
if(条件表达式){
方法体;
}
//单分支语句控制
//在原有的顺序流程执行的基础上如果遇到分支语句
//则执行条件表达式根据对应的值进行流程控制
//当满足条件时执行对应语句
//例如 声明变量保存成绩 使用单分支语句 判断如果没有及格则修改为60分
int score=99;
if(score<60){
score=60;
}
System.out.println("你的成绩为"+score+"分");
- 双分支语句
根据条件结果执行对应代码块
语法:
if(条件表达式){
方法体1;
}else{
方法体2;
}
//if双分支流程控制语句
//当条件满足时执行对应语句块,不满足时也定义语句块进行执行
//双分支语句 根据条件结果对两个代码块进行执行,有于boolean只存在true或者false
//所以两个代码块必被执行一个,另一个
//例 根据儿子成绩选择给儿子的奖励
int score=90;
if(score>=80){
System.out.println("旅游套餐");
}else{
System.out.println("扫帚套餐");
}
- 多分支语句
根据多个条件进行执行,最终执行某一个代码块
多分支语句可以书写多个条件判断,当对应条件判断返回true时 ,执行对应的方法体,当所有条件都不满足执行else中的方法体
语法:
if(条件表达式1){
方法体1;
}else if(条件表达式2){
方法体2;
}else if(条件表示3){
方法体3;
}.......
else if(条件表达式n){
方法体n;
}else{
方法体n+1;
}
System.out.println("开始");
// 需求:键盘录入一个星期数(1,2,...7),输出对应的星期一,星期二,...星期日
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个星期数(1-7):");
int week = sc.nextInt();
if(week == 1) {
System.out.println("星期一");
} else if(week == 2) {
System.out.println("星期二");
} else if(week == 3) {
System.out.println("星期三");
} else if(week == 4) {
System.out.println("星期四");
} else if(week == 5) {
System.out.println("星期五");
} else if(week == 6) {
System.out.println("星期六");
} else {
System.out.println("星期日");
}
System.out.println("结束");
面试题:
if分支语句与三目运算符的区别
- if分支语句是使用if关键字的特殊流程控制语句语法,三目运算符本质是运算符。
- 三目运算符会将结果返回,if语句不需要返回值。
- 在java源码中大量使用了三目运算符。
- 三目运算符书写的功能都可以使用if语句完成,但是反之可能要书写额外代码。
- 三目运算符运算结束后只能返回一个数据,if语句可以在代码块中对多个数据赋值。
- 三目运算符与if语句不成立的条件与代码块都不会执行。
- 三目运算符执行效率相比较if可能较低(如果三目运算符与if语句的结果都为常量时,三目运算符的效率高)。
2.3.4 switch分支语句的使用
底层使用的是值匹配的形式进行分支的执行,首先计算表达式的结果,根据每个case后的值与结果进行匹配,配上则执行对应语句体。
switch (表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
执行流程
1、执行表达式计算结果
2、将结果与每个case匹配
3、匹配后执行对应代码
4、代码执行后继续乡下执行遇到break跳出否则会继续执行
5、如果没有匹配性执行defalut中代码块(default可以书写在任意位置)注意:表达式的结果只能byte short char int String(1.74以后) 枚举(1.5以后)
理解:
可以将switch执行过程理解为如下:
每个switch都会声明一个boolean类型变量,默认为false,用于代码块是否执行,按照流程控制语句从上到下运行,case语句如果值匹配则会将这个变量变为true,继续向下执行,遇到代码块根据变量的值判断是否执行代码块,如果没有书写break结束当期代码块,则会将所有代码块执行,如果没有匹配项,则会执行default中的代码块
//例1 使用switch根据等级输出分数范围
//switch
Scanner sc=new Scanner(System.in);
System.out.println("请输入等级");
String scoreGrade=sc.nextLine();
//根据等级输出分数的范围
switch(scoreGrade){
case "A+":
System.out.println("分数范围是90~100");
break;
case "A":
System.out.println("分数范围是80~89");
break;
case "B":
System.out.println("分数范围是70~79");
break;
case "C":
System.out.println("分数范围是60~69");
break;
case "D":
System.out.println("分数范围是0~59");
break;
default:
System.out.println("你家有"+scoreGrade+"这个等级");
}
//例2 使用switch计算已过天数
package com.yunhe.day0607;
import java.util.Scanner;
public class Switch2 {
public static void main(String[] args) {
//switch
//输入年月日输出输入时期已过天数
int year=2021;
int month=11;
int day=30;
//5月已过天数
//1月 +2 月+....4月+day
//先计算2月有多少天
//声明变量保存二月天数
int twoMonth=28;
if(year%4==0){
twoMonth=29;
}
//声明变量保存总天数
int sumDay=0;
switch(month-1){
case 11:
sumDay+= 30;
case 10:
sumDay+= 31;
case 9:
sumDay+= 30;
case 8:
sumDay+= 31;
case 7:
sumDay+= 31;
case 6:
sumDay+= 30;
case 5:
sumDay+= 31;
case 4:
sumDay+= 30;
case 3:
sumDay+= 31;
case 2:
sumDay+= twoMonth;
case 1:
sumDay+=31;
default:
sumDay+=day;
}
System.out.println(sumDay);
}
}
2.4 循环流程控制语句
重复执行一段话相同的代码,进行有限或无限根据指定条件进行循环的执行
2.4.1 while循环
语法:
while(布尔表达式){
语句体;
}
-------------------------------
初始化语句;
while (条件判断语句) {
循环体语句;
条件控制语句;
}
当布尔表达式值为true时,执行相应语句体,否则不执行。
//例: 完成10次hello world的输出
//使用while语句完成输出10次操作
int i=1;
while(i<=10){
System.out.println("hello world"+i);
i++;
}
2.4.2 do…while循环
语法:
do{
语句体;
}while(布尔表达式);
------------------------
初始化语句;
do{
循环体语句;
条件控制语句;
}while (条件判断语句);
public class DoWhile {
public static void main(String[] args) {
//使用do...while输出10次hello world
int i=11;
do{
System.out.println("hello world"+i);
i++;
}while(i<=10);
}
}
面试题:
while循环与do…while循环的区别:
1、执行流程不同,while先执行条件表达式,do…while先执行循环体
2、循环体执行次数不同,while循环可能一次都不执行,do…while至少执行一次
3、使用场景不同
while是先判断后执行,do…while是先执行后判断。当第一次条件不成立时,while不会执行!而do-while无论是否成立都至少会执行一次!
2.4.3 for循环
for循环可以理解为while第二种语法的简化形式
语法:
for(初始化语句;条件判断语句;条件控制语句){
循环体语句;
}
执行的流程为:
①执行初始化语句
②执行条件判断语句,看其结果是true还是false
如果是false,循环结束
如果是true,继续执行
③执行循环体语句
④执行条件控制语句
⑤回到②继续
//for输出10次hello world
//循环统一思路
//先不考虑循环先执行一次
for(int i=1;i<=10;i++){
System.out.println("hello world"+i);
}
面试题:
while循环与for循环的区别:
1、语法不同,使用不同的关键字实现循环功能
2、初始化变量作用域不同(while循环创建的初始化变量在循环结束后也可以使用)
3、内存占用区别(for循环内创建的变量在for循环结束后就会回收 => 初始化与方法体中变量)
4、使用场景不同
(1)如果在循环结束后仍然需要使用初始化变量使用while
(2)如果进行有限次数的循环使用for(存在固定次数)
2.5 流程跳转语句
书写在流程语句中用于控制流程语句的特殊跳转与执行
2.5.1 break
break:跳出当前循环(结束当前循环),结束循环
会结束当前循环继续执行后续代码
for (int i = 1; i <=10; i++) {
if(i==5){
break;
}
System.out.println(i);
}
System.out.println("后续代码");
2.5.2 continue
continue:跳过本次循环,进入下次循环
跳过当前循环后续应该执行代码,进入下一次循环,循环结束后执行后续代码
for (int i = 1; i <=10; i++) {
if(i==5){
continue;
}
System.out.println(i);
}
System.out.println("后续代码");
注意: break和continue只能在循环中进行使用,单独使用无任何意义!!!
2.5.3 return
return:方法级别的结束
结束当前方法(main方法) 当前方法后续代码不会运行
return后不能书写代码
for (int i = 1; i <=10; i++) {
if(i==5){
return;
}
System.out.println(i);
}
System.out.println("后续代码");
2.6 循环嵌套经典案例
外循环执行一次,内循环执行一圈
- 例1 打印长方形
//在控制台打印长方形
//*****
//*****
//*****
// System.out.println("*****");
//思考一行怎么打印
//输次一个如下
for(int i=1;i<=3;i++){
for(int j=1;j<=5;j++){
System.out.print("*");
}
System.out.println();
}
- 例2 打印直角边在左下的直角三角形
for(int i=1;i<=4;i++){
for(int j=1;j<=i;j++){
if(j<=i){
System.out.print("*");
}
}
System.out.println();
}
输出如下:
*
**
***
****
*****
******
*******
********
- 例3 打印直角边在左上的直角三角形
for(int i = 5; i >= 1; i--){
for(int j = i; j >= 1; j--){
System.out.print("*");
}
System.out.println();
}
输出如下:
********
*******
******
*****
****
***
**
*
- 例4 打印直角边在右下的直角三角形
for(int i = 1; i <= 5; i++){
for(int j = 5; j >= 1; j--){
if(i < j){
System.out.print(" ");
}else{
System.out.print("*");
}
}
System.out.println();
}
输出如下:
*
**
***
****
*****
******
*******
********
- 例5 打印直角边在右上的直角三角形
for(int i = 1; i <= 5; i++){
for(int j = 1; j <= 5; j++){
if(i > j){
System.out.print(" ");
}else{
System.out.print("*");
}
}
System.out.println();
}
输出如下:
********
*******
******
*****
****
***
**
*
- 例6 打印正等腰三角形
//直接画
//控制行数
for(int i = 1; i <= 5;i++){
//控制前面空格
for(int j = 1; j <= 5 - i; j++){
System.out.print(" ");
}
//控制每行的*
for(int k = 1; k <= 2 * i - 1;k++){
System.out.print("*");
}
System.out.println();
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~");
//画一个正方形,然后进行扣
for(int i = 1; i <= 3; i++){
for(int j = 1; j <= 5; j++){
//扣去左上角和右上角,用空格代替
if(j <= 3 - i || j >= 3 + i){
System.out.print(" ");
}else{
System.out.print("*");
}
}
System.out.println();
}
输出如下:
*
***
*****
*******
*********
- 例7 打印倒等腰三角形
public class Triangle {
public static void main(String args[]) {
//确定三角形的行数并打印空行
for(int i = 5; i >= 1; i--) {
System.out.println();
//根据5-i的值确定前面空格的数量
for (int n = 1; n <= 5 - i; n++) {
System.out.print(" ");
}
//根据公式2*i-1确定打印*的个数
for (int j = 1; j <= 2*i-1; j++) {
System.out.print("*");
}
}
}
}
输出如下:
*********
*******
*****
***
*
3 Random工具类
随机数工具类,可以根据指定的范围生成随机数
注意: 生成的是伪随机数
3.1 使用步骤
3.1.1 导包
import java.util.Random;
3.1.2 使用new关键字创建随机数对象
Random r=new Random();
3.1.3使用随机数对象方法获取随机数
r.nextInt(2)
//会随机生成0~指定数据-1范围的数值
3.2 猜数字案例
1.开始游戏时电脑随机选择一个1~100以内的数据,我们通过输入的形式进行猜,每次会告诉数据偏大或偏小直至成功,输出次数。
import java.util.Random;
import java.util.Scanner;
public class NumberGame {
public static void main(String[] args) {
// 开始游戏时电脑随机选择一个1~100以内的数据,
// 我们通过输入的形式进行猜,
// 每次会告诉数据偏大或偏小直至成功,输出次数
// 电脑随机与玩家输入都需要工具类
Scanner sc = new Scanner(System.in);
Random r = new Random();
System.out.println("====猜数字游戏====");
System.out.println("请输入1~100之间的整数");
// 开始游戏时电脑随机选择一个1~100以内的数据=>
// 使用随机数类生成一个1~100之间的数据并创建变量保存
//int number = r.nextInt(100) + 1;
int number=50;
int count=0;
while (true) {
count++;
// 我们通过输入的形式进行猜=>
// 使用扫描器工具类获取我们输入的值
int player = sc.nextInt();
if (number == player) {
System.out.println("猜中了");
break;
} else if (player > number) {
System.out.println("猜大了");
} else {
System.out.println("猜小了");
}
}
System.out.println("您最終猜了"+count+"次");
}
}
2.当猜中之后,用户输入1可再次进入猜数字游戏,输入其他退出游戏。
System.out.println("========猜数字游戏========");
while(true){
//随机生成随机数,创建变量并保存
Random r = new Random();
System.out.println("请输入0~100的整数:");
int number = r.nextInt(100) + 1;
while(true){
//玩家输入0~100之间的数,创建变量并保存
Scanner sc = new Scanner(System.in);
int player = sc.nextInt();
//判断随机数与玩家输入数的大小
if(number == player){
System.out.println("猜中了");
break;
}else if(number > player){
System.out.println("猜小了");
}else{
System.out.println("猜大了");
}
}
//玩家输入0~100之间的数,创建变量并保存
Scanner sc0 = new Scanner(System.in);
System.out.println("是否再次进入游戏:1进入、0退出");
int flag = sc0.nextInt();
if(flag == 0){
System.out.println("=========你已退出游戏=========");
break;
}
}
4 数组
用于存储具有相同数据类型的容器称之为数组。
4.1 分类
- 一维数组
- 多维数组
4.2 特点
- 存储数据类型统一
- 可以存储任意数据类型
- 存储长度在创建时已经固定
- 存储类型固定
4.3 一维数组的使用
4.3.1 声明
声明数组变量保存数据
//①声明
//声明数组变量指定存储数据的类型
//语法:
//(1)数组存储数据的类型 [] 数组名;
int []arr1;
//创建一个存储整数类型的数组变量名为arr1;
//(2)数组存储数据的类型 数组名[];
int arr2[];
//创建一个存储整数类型变量名为arr2的数组
4.3.2 创建(初始化)
开辟内存空间,存储指定的数据,设置容量
动态创建: 数组动态初始化就是只给定数组的长度,由系统给出默认初始化值
格式: 数据类型[] 数组名 = new 数据类型[数组长度];int[] arr = new int[3];
静态创建: 在创建数组时,直接将元素确定,由系统计算出数组的长度
格式:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,…};
数据类型[] 数组名 = {元素1,元素2,…};int[] arr = {1, 2, 3};
//(1)动态创建
//创建指定类型的数组,赋值给声明好的数组变量中
//语法:声明好的数组变量=new 数据类型[长度];
arr1=new int[3];
//通常习惯将声明与创建一同进行
int [] arr3=new int[5];
//(2)静态创建
//将声明创建赋值一同进行
//语法:
//1)声明好的数组变量=数据类型[]{数据1,数据2,数据3};
//使用指定数据创建数组,并赋值给声明好的数组变量
arr2=new int[]{1,2,3,4,5};
//通常与声明一起进行
int []arr4=new int[]{1,2,3,4,5};
//2)简化语法: 存储数据的类型[] 数组名={数据1,数据2,数据3};
//必须与声明一起使用 所有数据使用{}包裹 数据之间使用,分隔
int []arr5={1,2,3,4};
4.3.3 赋值
动态创建会进行初始化赋值,会使用数据类型的默认值进行赋值,值为0
数组动态初始化就是只给定数组的长度,由系统给出默认初始化值静态创建在创建过程中会使用提供的数据进行创建
在创建数组时,直接将元素确定,由系统计算出数组的长度
//数组名[下标/索引]=值;
//索引:使用统一的变量保存多个数据,在进行数据区分时 使用索引进行区分
//索引的范围0~最大长度-1 数组提供属性length获取当前数组最大长度
System.out.println(arr1.length);
arr1[0]=1;
arr1[2]=8;
//arr1[3]=8; arr1索引范围0~2 会出现数组下标越界异常
4.3.4 使用
获取指定索引对应位置的数据
//直接使用数组名[索引]的方式进行获取
System.out.println(arr3[0]);
4.4 索引
4.4.1 什么是索引
每一个存储到数组的元素,都会自动的拥有一个编号,从0开始。
这个自动编号称为数组索引(index),可以通过数组的索引访问到数组中的元素。
4.4.2 访问数组元素格式
数组名[索引];
- 示例代码
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = new int[3];
//输出数组名
System.out.println(arr); //[I@880ec60
//输出数组中的元素
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
4.5 案例
使用数组存储班级所有人的成绩 ,分别计算最高分,最低分,平均分。
//例 使用数组存储班级所有人的成绩 ,分别计算最高分,最低分,平均分
//创建数组保存数据
int []score = {85,60,50,95,60,31,75,60,85,86};
//最高分
int max = score[0];
for(int i = 0; i < score.length; i++){
if(max < score[i]){
max = score[i];
}
}
System.out.println("最高分为:" + max);
//最低分
int min = score[0];
for(int i = 0; i < score.length; i++){
if(min > score[i]){
min = score[i];
}
}
System.out.println("最低分为:" + min);
//平均分
int average = 0;
int sum = 0;
for(int i = 0; i < score.length; i++){
sum += score[i];
}
average = sum / score.length;
System.out.println("平均分为:" + average);
5 内存分配
内存是计算机中的重要原件,临时存储区域,作用是运行程序。
我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的。
必须放进内存中才能运行,运行完毕后会清空内存。
Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。
5.1 Java中的内存分配
目前我们只需要记住三个内存,分别是:栈内存、堆内存和常量池
区域名称 | 作用 |
寄存器 | 给CPU使用,和我们开发无关。 |
本地方法栈 | JVM在使用操作系统功能的时候使用,和我们开发无关。 |
方法区 | 存储可以运行的class文件。 |
堆内存 | 存储对象或者数组,new来创建的,都存储在堆内存。 |
方法栈 | 方法运行时使用的内存,比如main方法运行,进入方法栈中执行。 |
5.1.1 常量池
常量池中保存运行过程中创建的常量(只要是在代码中出现的常量)
数据在第一次被使用时创建(当需要使用常量时会先去常量池中寻找,如果存在则直接使用对应地址)
常量池数据在整个程序运行结束后回收
5.1.2 栈
栈中保存的是运行过程中声明的变量,其中保存的是栈的名与数据地址
栈的回收时间根据回收算法决定(不用就回收)
5.1.3 堆
堆中保存的是运行过程中创建的对象(所有new出来的内容)
堆的回收时间根据回收算法决定(不用就回收)
5.2 数组的内存分配
5.2.1 单个数组的内存分配
单个数组的内存分配图如下:
5.2.2 两个数组的内存分配
两个数组的内存分配图如下:
多个数组创建多个存储空间进行数据存储,不同数组对象之间没有关联
5.2.3 声明数组对象保存已有数组内存分配
多个变量使用同一个地址进行操作,其他变量会获取修改后的数据
6 数组排序练习
6.1 冒泡排序算法
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,依次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
int []arr = {8,7,2,9,3,5,4,6,1};
//从小到大排序
for(int i = 0; i < arr.length - 1; i++){
for(int j = 0; j < arr.length - 1 - i; j++){
if(arr[j] > arr[j + 1]){
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
//从大到小排序
for(int i = 0; i < arr0.length - 1; i++){
for(int j = 0; j < arr0.length - 1 - i; j++){
if(arr0[j] < arr0[j + 1]){
int temp = arr0[j];
arr0[j] = arr0[j + 1];
arr0[j + 1] = temp;
}
}
}
6.2 选择排序算法
选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
int []arr = {8,7,2,9,3,5,4,6,1};
//从小到大排序
for(int i = 0; i < arr.length - 1; i++){
int minIndex = i;
for(int j = i + 1; j < arr.length; j++){
if(arr[minIndex] > arr[j]){
minIndex = j;
}
}
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
//从小到大排序
for(int i = 0; i < arr.length - 1; i++){
int maxIndex = i;
for(int j = i + 1; j < arr.length; j++){
if(arr[maxIndex] < arr[j]){
maxIndex = j;
}
}
int temp = arr[i];
arr[i] = arr[maxIndex];
arr[maxIndex] = temp;
}
7 多维数组
数组的概念:
用于存储具有相同数据类型的容器。
数组的特点:
- 可以存储基本数据类型与引用类型(所有类型数据)。
- 存储的数据类型与长度创建时确定不允许更改。
7.1 多维数组的概念
在Java中没有多维数组,所谓的多维数组其实是数组可以存储引用类型,而其本身为引用类型,在数组中存储数组引发的多维数组的概念,由于数组多层存储的数据复杂性,所以一般我们只使用二维数组。
7.2 二维数组的使用
7.2.1 声明
//声明
//数组的声明方式
//1 数据类型[] 数组名;
int[] [] arr1;
//2 数据类型 数组名[];
int []arr2[] ;
7.2.2 创建
//创建
//动态创建
//数组名=new [长度];
arr1=new int[4][2];//
//0 0
//0 0
//0 0
//0 0
//第一个[]代表当前数组存储数据的个数
//第二个[]代表当前数组存储的每个数组存储数据的个数
//可以理解为第一个[]代表行索引 第二个[]列索引
//静态创建
//数据类型 [] 数组名={数据1,数据2}
int[] [] arr3={
{1,2,3},
{4,5,6},
{7,8}};
7.2.3 赋值
//赋值
//数组名[索引]
arr1[0][0]=1;
//获取当前数组第一个数据数组中第一个数据
//分别为行索引 与列索引
7.2.4 使用
//使用
System.out.println(arr1[0][0]);
7.3 二维数组的遍历
for (int i = 0; i < arr3.length; i++) {
int [] arr=arr3[i];
for(int j=0;j<arr.length;j++){
System.out.print(arr[j]+" ");
}
System.out.println();
}
for (int i = 0; i < arr3.length; i++) {
for(int j=0;j<arr3[i].length;j++){
System.out.print(arr3[i][j]+" ");
}
System.out.println();
}
7.4 二维数组的案例
7.4.1 使用二维数组根据输入数据创建保存杨辉三角
//每一行除首末位为1 其余位为 上一行 与上一行前一项之和
//每行的个数为行数
//输入数据
Scanner sc = new Scanner(System.in);
//提示输入
System.out.println("请输入数字:");
//获取输入的数据
int number = sc.nextInt();
//输入数据,控制外部数组的长度
int[] [] arr = new int[number][];
//设置内部数组的长度,外数组的第i个元素,它的长度为i+1
for(int i = 0; i < arr.length; i++){
arr[i] = new int[i + 1];
}
//设置里边数据
for(int i = 0; i < arr.length; i++){
for(int j = 0; j < arr[i].length; j++){
//第一个数和最后一个数为1,其他的数是上一行 与上一行前一项之和
if(j == 0 || j == arr[i].length - 1){
arr[i][j] = 1;
}else{
arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
}
}
}
//遍历输出数组
for(int i = 0; i < arr.length; i++){
for(int j = 0; j < arr[i].length; j++){
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
sc.close();
输出结果为:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
7.4.2 使用所学知识完成彩票0 ~ 13选五个数,1 ~ 7中选择一个数的生成并存储至数组。
//生成随机数
Random r = new Random();
//创建数组,存放数据
int[] arr = new int[7];
//最后一位 1~7之间选一位
//存入数组最后一位
arr[arr.length - 1] = r.nextInt(7) + 1;
//生成
for(int i = 0; i < arr.length - 1; i++){
//生成一个1~13之间的数
int number = r.nextInt(13) + 1;
//默认flag为false,不是这个数之前不存在
boolean flag = false;
//判断生成的数与数组中的数
if(number == arr[i]){
//置flag为true
flag= true;
//退出循环
break;
}
//判断flag值
if(flag){
//如果存在,将i-1,重新生成随机数。
i--;
}else{
//如果不存在,将值存入数组
arr[i] = number;
//输出数据
System.out.print(arr[i] + " ");
}
}
7.4.3 猜拳游戏
// 猜拳游戏
// 用户输入:0-剪刀 1-舌头 2-布
// 电脑随机产生
// 五局三胜
// 输入数据
Scanner sc = new Scanner(System.in);
// 生成随机数
Random r = new Random();
System.out.println("======猜拳游戏======");
System.out.println("请输入:0-剪刀 1-石头 2-布");
String[] games = { "剪刀", "石头", "布" };
String ends;
// 定义游戏总数
int count = 0;
// 定义玩家赢的次数
int playerWin = 0;
// 定义电脑赢的次数
int pcWin = 0;
while (true) {
count++;
int player = sc.nextInt();
int pc = r.nextInt(3);
if (player == pc) {
ends = "平局";
} else {
if (player > pc) {
if (player - pc == 1) {
ends = "赢了";
playerWin++;
} else {
ends = "输了";
pcWin++;
}
} else {
if (pc - player == 1) {
ends = "输了";
pcWin++;
} else {
ends = "赢了";
playerWin++;
}
}
}
System.out.println("你出了" + games[player] + ",电脑出了" + games[pc] + ",你" + ends);
if (playerWin == 3) {
System.out.println("你已先赢3局");
break;
}else if(pcWin == 3){
System.out.println("电脑已先赢3局");
break;
}else if(count == 5){
if(playerWin >= pcWin){
System.out.println("五局已结束,你赢了,比分为:玩家-电脑" + playerWin + "-" + pcWin);
}else{
System.out.println("五局已结束,你输了,比分为:玩家-电脑" + playerWin + "-" + pcWin);
}
break;
}else{
System.out.println("你赢了" + playerWin + "局,电脑赢了" + "局,比分为:玩家-电脑" + playerWin + "-" + pcWin);
}
}
sc.close();
8 方法(Method)
8.1 概念
- 方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。
- 方法(method)又称之为函数,是将一行或多行代码进行封装,提供统一的方法名,通过方法名以及参数进行使用。
8.2 方法基本使用
方法书写格式
修饰符 返回值类型 方法名(参数列表){
//代码省略...
方法体;
}
// 修饰符 public static : 用于修饰当前方法定义当前方法使用权限 之后在封装会讲相应的关键字
// 返回值类型 void :用于定义方法执行结束后返回数据的类型,如果方法无需返回数据则使用void
// 如果方法没有返回值使用void 那么可以省略return,但是如果设置了任意返回类型,那么必须书写return并在return后返回与返回值类型匹配的数据
// 方法名 main:用于定义方法的名称 ,符合标识符命名规范
// 参数列表 String[] args:用于声明方法执行时需要使用的数据,可以有零到无穷个
// 参数列表,书写的语法为数据类型 变量名多个参数以,分割
// 方法体:用于定义方法执行时实际执行的代码
//main方法
//是一个类的入口方法=>当执行一个类的时候默认调用这个类的main方法
//main方法:修饰符 返回值 方法名参数固定
public static void main(String[] args) {
}
public static void fire() {
System.out.println("准备发射5发炮弹");
System.out.println("发射第1发炮弹* * * *");
System.out.println("发射第2发炮弹* * * *");
System.out.println("发射第3发炮弹* * * *");
System.out.println("发射第4发炮弹* * * *");
System.out.println("发射第5发炮弹* * * *");
System.out.println("发射5发炮弹结束");
}
方法调用格式:
方法名();
public static void main(String[] args) {
System.out.println("游戏开始...");
System.out.println("看到了一个怪物...血牙野猪...");
//调用方法,发射炮弹
fire();
System.out.println("...血牙野猪被打倒...");
}
8.3 分类
8.3.1 无参数无返回值方法
//无参无返回值
public static void add1(){
int a=1;
int b=2;
System.out.println(a+b);
}
8.3.2 有参数无返回值方法
//有参无返回值
public static void add2(int a,int b){
System.out.println(a+b);
}
8.3.3 无参数有返回值方法
//无参数有返回值
public static int add3(){
int a=5;
int b=6;
return a+b;
}
8.3.4 有参数有返回值方法
//有参有返回值
public static int add4(int a,int b){
return a+b;
}
总结: 有参可以使方法更加灵活,可以是方法执行时根据不同的参数进行不同的执行,返回值可以获取方法执行后返回的数据,如果之后的代码还想使用这个数据可以直接使用,无返回值方法通常就是输出,只能看到对应数据不能获取。
8.4 调用
8.4.1 有无参数
调用无参方法时只需要使用 方法名();即可调用
有参方法需要根据方法声明参数列表指定的类型与个数进行参数的传递
注意: 方法声明时,声明的变量名只是在当前方法中使用
8.4.2 有无返回值
无返回值方法:直接调用,一般在方法中书写输出语句进行输出结果
有返回值方法:调用前会根据返回值类型创建变量保存返回的类型
8.4.3 方法执行流程
- 在main方法执行过程中,调用其他方法,根据方法名获取对应方法,将调用方法时书写的参数传递给声明方法时声明的变量
- 形参:声明方法时参数列表声明的变量
- 实参:调用方法时实际传入的数据变量
- 输入方法名将实参传递给形参执行对应方法体的过程 称之为方法的执行
8.5 特点
- 1、方法书写在类中,方法中不能定义方法
- 2、方法不调用不执行
- 3、多个方法执行互不影响
- 4、一次编写多次运行(减少代码冗余,提高代码复用性,增强程序维护性与可扩展性)
8.6 方法扩展
引用类型作为方法的参数
与基本数据类型一样,引用类型作为参数类表书写方式不变。
//将指定数组排序
public static void sortArr1(int[] arr){
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
int tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
}
}
//根据名称查找是否存在
public static boolean find(String name){//name被查找人的名字
//创建包含所有名字的数组
String []names={"张三","李四","二狗子"};
//遍历数组判断是否存在
for(int i=0;i<names.length;i++){
if(names[i].equals(name)){
return true;
}
}
return false;
}
方法执行参数类型无论是基本数据类型还是引用数据类型,其实都是将对应数据的地址传递过来,在方法执行过程中进行操作,所以如果参数是数组,并且在方法执行过程中没有创建数组,那么作为参数传递的变量可以获取方法执行后最新数组的数据(参数与方法都对同一地址数据进行了操作)
8.7 方法重载
8.7.1 概念
在同一个类中,方法名相同参数列表不同我们称发生了方法的重载或两方法互为重载。
8.7.2 为什么使用方法重载
在方法声明过程中往往我们需要声明很多方法,并进行方法名标识符的定义,但是有时多个方法功能相似,参数不同这个时候就可以使用方法的重载,将多个方法名称标识符设置相同(不用起很多名字了)。
8.7.3 方法重载的书写
仅有返回类型不同是不足以区分两个重载的方法。
参数列表不同:
- 参数个数不同 ==> 两个方法 方法名相同 参数列表个数不同
- 参数数据类型不同 ==> 两个方法 方法名相同 参数列表个数相同 参数类型不同
- 参数顺序不同 ==> 两个方法 方法名相同 参数列表个数相同 参数类型相同(个数类型两个以上) 参数数据类型的顺序不同
//两个整数相加方法 返回结果
public static int sum(int a,int b){
return a+b;
}
//两个小数相加方法 返回结果
//方法的重载 参数数据类型不同
public static double sum(double a,double b){
return a+b;
}
//三个整数相加方法 返回结果
// 参数列表个数不同
public static int sum(int a,int b,int c){
return a+b+c;
}
//两个整数与一个小数相加 返回结果
public static double sum(int a,int b,double c){
return a+b+c;
}
//数据类型相同 个数相同 顺序不同
public static double sum(double a,int b,int c){
return a+b+c;
}
*面试题-
什么是方法的重载?
- 在同一个类中,方法名相同参数列表不同我们称发生了方法的重载或两方法互为重载
仅有返回类型不同是不足以区分两个重载的方法。- 参数列表不同有三种不同
①参数个数不同 ==> 两个方法 方法名相同 参数列表个数不同
②参数数据类型不同 ==> 两个方法 方法名相同 参数列表个数相同 参数类型不同
③参数顺序不同 ==> 两个方法 方法名相同 参数列表个数相同 参数类型相同(个数类型两个以上) 参数数据类型的顺序不同
8.7.4 方法重载的执行流程
- 方法存储在方法区中,在执行过程中由jvm动态决定执行的方法
- 首先会根据方法名在方法区中查找是否存在指定方法.
- 如果存在多个方法,依次获取传入参数的类型查找匹配项