2023/3/25 13:57:34
用户交互(获取用户输入)Scanner
-
之前我们学的基本语法中并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以用来获取用户输入
-
java.util.Scanner是Java5的新特性,我们可以通过Scanner类来获取用户的输入
-
基本语法
Scanner s = new Scanner(System.in);
-
通过Scanner类的next()与nextLine()方法获取输入的字符串(String),在读取前我们一般需要用hasNext()与hasNextLine()判断是否还有输入的数据
hasXxx()方法
-
用于检验用户输入的数据
next()
-
一定要读取到有效字符后才可以结束输入
-
对输入有效字符之前遇到的空白,next()方法会自动将其去掉
-
只有输入有效字符后才将其后面输入的空白作为分隔符或结束符
-
next()不能得到带有空格的字符串
package scanner; import java.util.Scanner; /** * 获取用户输入Scanner 使用next()方法接收 // * @date 2023/3/25 14:02:18 * @author ZQ * @since 1.8 */ public class Demo01 { public static void main(String[] args) { // 创建一个扫描器对象,用于接收键盘数据 Scanner sc = new Scanner(System.in); System.out.println("使用next()方法接收"); System.out.println("请输入内容:"); // 判断用户有没有输入字符串 if (sc.hasNext()) { // 使用next()方法接收 String str1 = sc.next(); System.out.println("输入的内容为:" + str1); } // 关闭,凡是属于IO流的类,使用后不关闭就会占用系统资源,要养成好习惯,用完就关掉 sc.close(); } }
nextLine()
-
以Enter(回车)为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。
-
可以获得空白
package scanner; import java.util.Scanner; /** * 获取用户输入Scanner 使用nextLine()方法接收 // * @date 2023/3/25 14:02:18 * @author ZQ * @since 1.8 */ public class Demo02 { public static void main(String[] args) { // 创建一个扫描器对象,用于接收键盘数据 Scanner sc = new Scanner(System.in); System.out.println("使用nextLine()方法接收"); System.out.println("请输入内容:"); // 判断用户有没有输入字符串 if (sc.hasNext()) { // 使用nextLine()方法接收 String str1 = sc.nextLine(); System.out.println("输入的内容为:" + str1); } // 关闭,凡是属于IO流的类,使用后不关闭就会占用系统资源,要养成好习惯,用完就关掉 sc.close(); } }
获取小数和整数
-
使用hasXxx()方法
-
Xxx表示某一种基本数据类型
-
均为小驼峰法命名
package scanner; import java.util.Scanner; /** * 获取用户输入Scanner 获取用户输入的整数和小数,用hasXxx()方法接收 // * @date 2023/3/25 14:28:18 * @author ZQ * @since 1.8 */ public class Demo04 { public static void main(String[] args) { // 创建一个扫描器对象,用于接收键盘数据 Scanner sc = new Scanner(System.in); // 定义两个变量来存储要输入的数据 int i = 0; float f = 0.0F; System.out.println("请输入数据:"); if (sc.hasNextInt()) { // 使用nextLine()方法接收 i = sc.nextInt(); System.out.println("输入的int数据为:" + i); } else if (sc.hasNextFloat()) { // 使用nextLine()方法接收 f = sc.nextFloat(); System.out.println("输入的float数据为:" + f); } else { System.out.println("对不起,您输入的数据无效"); } // 关闭,凡是属于IO流的类,使用后不关闭就会占用系统资源,要养成好习惯,用完就关掉 sc.close(); } }
练习
package scanner; import java.util.Scanner; /** * 获取用户输入Scanner 练习 // * @date 2023/3/27 10:04:47 * @author ZQ * @since 1.8 */ public class Demo05 { public static void main(String[] args) { // 输入多个数字,并求其总和、平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果 // 创建一个扫描器对象,用于接收键盘数据 Scanner sc = new Scanner(System.in); // 定义变量来存储数据 // 总和 double sum = 0.0; // 平均数 double avg = 0.0; // 输入的数字 double number = 0; // 输入的个数 int n = 0; System.out.println("请输入数字,按回车键确认,输入非数字按回车即可结束输入:请输入第1个数字:"); while(sc.hasNextDouble()) { n++; System.out.println("请输入第" + (n+1) + "个数字,输入非数字按回车即可结束输入:"); number = sc.nextDouble(); sum += number; } avg = sum / n; System.out.println("您输入的数据的总和为:" + sum); System.out.println("您输入的数据的平均数为:" + avg); // 关闭,凡是属于IO流的类,使用后不关闭就会占用系统资源,要养成好习惯,用完就关掉 sc.close(); } }
2023/3/27 10:06:41
Java流程控制
顺序结构
-
Java的基本结构就是顺序结构,除非特别指明,否则就按顺序一句一句执行
-
顺序结构是最简单的算法结构
-
语句与语句之间,框与框之间,是按照从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构
选择结构
if
if单选择结构
-
我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
-
语法:
if(布尔表达式){ // 如果布尔表达式为true时将执行的语句 }else{ // 如果布尔表达式的值为false时将执行的语句 }
if双选择结构
-
如果现在有个需求,公司需要收购一个软件,成功了,给人支付100万元,失败了,自己找人开发。这样一个需求用一个if就不行了,我们需要有两个判断,需要一个双选择结构,所以就有了if-else结构
-
语法
if(布尔表达式){ // 如果布尔表达式为true时将执行的语句 }
if多选择结构
-
我们发现刚才的代码不太符合实际情况,真实的情况中还可能存在ABCD,存在区间多级判断。比如90-100就是A,80-90就是B等等,在生活中我们很多时候的选择也不仅仅只有两个,所以我们需要一个多选择结构来处理这类问题
-
语法:
if(布尔表达式1){ // 如果布尔表达式1的值为true时要执行的语句 }else if(布尔表达式2){ // 如果布尔表达式2的值为true时要执行的语句 }else if(布尔表达式3){ // 如果布尔表达式3的值为true时要执行的语句 }else{ // 如果以上布尔表达式的值都不为true时要执行的语句 }
-
例子:
package struct; import java.util.Scanner; /** * 选择结构 // * @date 2023/3/27 11:14:26 * @author ZQ * @since 1.8 */ public class SelectiveStructure { public static void main(String[] args) { // 考试成绩大于等于60分就是及格,小于60分就是不及格 Scanner sc = new Scanner(System.in); double score = 0.0; System.out.println("请输入成绩:"); if (!sc.hasNextDouble()) { System.out.println("对不起,您的输入有误,请重新输入"); return; } score = sc.nextDouble(); if (score > 100 || score < 0) { System.out.println("对不起,您的输入有误,请重新输入"); } else if (score == 100) { System.out.println("你太牛了,满分!!!"); } else if (score >= 90) { System.out.println("A级"); } else if (score >= 80) { System.out.println("B级"); } else if (score >= 70) { System.out.println("C级"); } else if (score >= 60) { System.out.println("A级"); } else { System.out.println("不及格,该奋斗啦!!!"); } sc.close(); } }
嵌套的if结构
-
使用嵌套的if...else语句是合法的。也就是说你可以再另一个if或者else if语句中使用if或者else if语句。你可以像if语句一样嵌套else if...else
-
语法:
if(布尔表达式1){ // 如果布尔表达式1的值为true时要执行的语句 if(布尔表达式2){ // 如果布尔表达式2的值为true时要执行的语句 } }
-
思考:二分查找思想
switch(switch多选择结构)
-
多选择结构还有一个实现方式就是switch case语句。
-
switch case语句判断一个变量与一系列值中某个值是否相等,每一个值称为一个分支
-
switch语句中的变量类型可以是:
-
byte、short、int或者char
-
从JavaSE7开始,switch支持字符串String类型了
-
同时case标签必须为字符串常量或字面量
-
-
语法:
switch (expression) { case value: // 语句 break; // 可选 case value: // 语句 break; // 可选 // 可以有任意数量的case语句 default: // 可选 // 语句 }
-
例子:
package struct; import java.util.Scanner; public class SwitchDemo01 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); char grade; System.out.println("请输入成绩等级:"); // 只会识别输入的第一个字符 grade = sc.nextLine().toUpperCase().charAt(0); switch (grade) { case 'A': System.out.println("优秀"); break; case 'B': System.out.println("良好"); break; case 'C': System.out.println("及格"); break; case 'D': System.out.println("不及格"); break; default: System.out.println("成绩等级格式有误"); } sc.close(); } }
-
注意:case语句内的语句如果没有加上break;终止的话,会出现case穿透现象,匹配到的语句以及它后面的所有语句都会执行,直到switch全部结束或者遇到break;时才算执行完毕
循环结构
while
-
语法:
while(布尔表达式){ // 循环内容 }
-
只要布尔表达式为true,循环就会一直执行下去
-
我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环
-
少部分情况需要循环一直进行,比如服务器的请求响应监听等
-
循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死崩溃!
-
思考:计算1+2+3+...+100=?
do while
-
对于while而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
-
do...while与while相似,不同的是,do...while循环至少会执行一次
do{ // 循环语句 }while(布尔表达式);
-
while和do...while的区别:
-
while先判断后执行,do...while是先执行后判断!
-
do...while总是保证循环体会被至少执行一次!这是他们的主要差别。
-
for
-
虽然所有循环结构都可以用while或者do...while表示,但Java提供了另一种语句——for循环,使一些循环结构变得更加简单。
-
for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
-
for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化; 布尔表达式; 更新){ // 代码语句 }
-
练习1:计算0到100之间的奇数和偶数的和
-
练习2:用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
-
练习3:打印九九乘法表
package struct; /** * 循环结构 // * @date 2023/3/27 23:08:32 * @author ZQ * @since 1.8 */ public class LoopStructure02 { public static void main(String[] args) { // for // 计算0到100之间的奇数和偶数的和 int sum1 = 0; int sum2 = 0; for (int i = 0; i <= 100; i++) { if (i % 2 == 0) { // 偶数的和 sum1 += i; } else { // 奇数的和 sum2 += i; } } System.out.println("偶数的和为:" + sum1); System.out.println("奇数的和为:" + sum2); System.out.println("====================================="); // 用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个 int flag = 0; for (int i = 1; i <= 1000; i++) { if (i % 5 == 0) { if (flag % 3 == 0){ System.out.print(i + "\t"); } else if (flag % 3 == 1){ System.out.print(i + "\t"); } else { System.out.print(i + "\n"); } flag++; } } System.out.println(); System.out.println("====================================="); // 打印九九乘法表 for (int i = 1; i < 10; i++) { for (int j = 1; j <= i; j++) { System.out.print(j + "*" + i + "=" + i*j + "\t"); } System.out.println(); } } }
Java5增强for循环(foreach)
-
Java5引入了一种主要用于数组或集合的增强型for循环
-
语法:
for(声明语句 : 表达式){ // 要执行的语句 }
-
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
-
表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
break与continue
-
break在任何循环语句的主体部分均可以使用,用于强制退出循环,不执行循环中剩余的语句。(break语句也可以在switch中使用)
-
continue语句用在循环的语句体中,用于跳过当此循环,当次循环不执行continue后面的语句,然后继续进行下一次及后面的循环。
-
break语句只能用于循环语句和switch语句之中,而不能单独使用;而对于continue语句,它也必须放在循环语句内部,不能单独使用。
-
关于goto关键字
-
goto关键字很早就在程序设计语言中出现。尽管goto仍然是Java的一个保留关键字,但并未在Java语言中得到正式使用;Java目前还没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子---带标签的break和continue。
-
“标签”是指后面跟一个冒号的标识符,例如:label:
-
对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们虚妄在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
-
-
特殊语法(Java标签语法,一般用来从当前循环直接跳到其他循环):在Java中,我们可以使用标签来标识循环语句,从而控制break和continue语句的执行。具体做法是在循环语句前加上一个标签,然后在break和continue语句后加上这个标签即可。示例如下:
outer: for (int i = 0; i < 10; i++) { inner: for (int j = 0; j < 10; j++) { if (i == 5 && j == 5) { break outer; // 跳出外层循环 } if (i == 3 && j == 3) { continue inner; // 跳过内层循环剩余语句,进入到下一次内层循环 } System.out.println("i=" + i + ", j=" + j); } }
-
在上面的例子中,我们使用outer和inner两个标签来表示外层循环和内层循环。当i和j的值分别为5和5时,使用
break outer
语句跳出了外层循环。当i和j的值分别为3和3时,使用continue inner
语句跳过了内层循环剩余语句,直接进入到下一次内层循环。注意,在使用标签控制break和continue语句时,要确保标签的使用是合理的,否则可能导致代码逻辑混乱或出现死循环等问题。
-
程序控制练习题
-
打印三角形 5行
package struct; /** * 流程控制练习题 // * @date 2023/3/31 11:30:35 * @author ZQ * @since 1.8 */ public class TestDemo01 { public static void main(String[] args) { // 打印三角形 5行 for (int i = 0; i < 5; i++) { for (int j = 0; j < 5-i; j++) { System.out.print(" "); } for (int j = 0; j <= 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 = 5; j >= i; j--) { System.out.print(" "); } for (int j = 1; j <= i; j++) { System.out.print("*"); } for (int j = 1; j < i; j++) { System.out.print("*"); } System.out.println(); } } }
DEBUG
-
Debug是一种程序的调试工具,它是供程序员检查和解决问题的工具。使用Debug工具可以帮助程序员快速定位程序中的错误,并且更加深入地理解程序运行的过程,以便于进行修复。
-
其中,Debug主要有以下两个作用:
-
追踪代码的运行流程:通过调试工具,我们可以单步执行程序,观察每一个语句的执行情况,了解程序的执行顺序、变量的值等等。这对于理解整个程序的运行流程非常有帮助,同时也有助于在程序出现问题时更快地定位和解决错误。
-
程序运行异常定位:程序出现问题是常有的事情,但是想要精准地找到问题所在却不是一件容易的事情。使用Debug工具,我们可以设置断点、观察变量值、调用栈等等,并且可以在程序运行到设定的断点处暂停,从而更加方便地进行问题定位和调试。
-
-
总之,Debug工具是程序员在开发中必不可少的调试工具,它可以提高程序开发的效率和质量,帮助程序员更好地理解程序的运行过程,并且快速定位和解决问题。
-
如何在IDEA中进行debug调试:
-
当我们需要进行程序调试时,使用debug调试非常方便。下面是一些关于 IDEA 进行 debug 的基本步骤:
-
在代码中设置断点,可以通过点击代码行号左边的空白处来设置断点,也可以在代码行上右键选择 Toggle Breakpoints 来设置。
-
点击 IDEA 左侧的 Debug 标签,或者按下 Shift + F9 快捷键,打开 Debug 窗口。
-
在 Debug 窗口中,点击 Debug 按钮或者按下 F9 快捷键,开始程序的 debug 运行。
-
当程序遇到断点时,程序会暂停,此时可以通过 Debug 窗口中的控制按钮来单步执行、进入方法、跳过方法等等。
-
调试结束后,可以点击 Debug 窗口右上角的 Stop 按钮或者按下 Shift + F2 快捷键来停止调试。
-
-
2023/04/01 16:59:36
Java方法
什么是方法
-
Java方法是语句的集合,他们在一起执行一个功能
-
方法是解决一类问题的步骤的有序组合
-
方法包含于类或对象中
-
方法在程序中被创建,在其他地方被引用
-
-
Java的方法类似于其他语言中的函数,是一段用来完成特定功能的代码片段
设计方法的原则
-
方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只能完成1个功能,这样利于我们后期的拓展。(单一职责原则)
-
上述原则是:单一职责原则(Single Responsibility Principle,SRP)。这个原则是面向对象编程中的常见原则之一,它要求一个类或一个方法只负责一项职责或功能,避免一个类或方法承担过多的职责或功能导致代码难以维护、理解和拓展。在实践中,通过将功能分解成多个相互独立的类或方法,可以使系统更加灵活、可复用和可维护。比如,将一个大型方法分解成几个小方法,每个小方法只完成一个明确的功能,从而提高代码复用性和可维护性。
方法的命名规则
-
小驼峰法
方法的定义及调用
方法的定义
-
方法包含一个方法头和一个方法体。下面是一个方法的所有组成部分:
-
修饰符:访问控制修饰符,这是可选的,告诉编译器如何调用该方法。不写的话默认为default
-
返回值类型:方法可能会返回一个值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void,表示该方法无返回值
-
方法名:是方法的实际名称。方法名和参数表共同构成方法签名
-
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值成为实参或变量。参数列表指的是参数类型、顺序和参数的个数。参数是可选的,方法可以不包括任何参数
-
形式参数:在方法被调用时用于接收外界输入的数据
-
实参:调用方法时实际传给方法的数据
-
-
参数名:指的是参数的命名(小驼峰法)
-
方法体:方法体包含具体的语句,定义该方法的功能
-
返回值:该方法返回的一个值,可有可无
-
-
语法如下:
[访问修饰符] [static] 返回值类型 方法名(参数列表){ // 方法体 return 返回值; }
方法的调用
-
语法:
对象名.方法名(实参列表)
-
Java支持两种调用方法的方式,根据方法是否返回值来选择
-
当方法返回一个值的时候,方法调用通常被当作一个值,例如:
int larger = max(30, 40);
-
如果方法的返回值为void,方法调用一定是一条语句,例如:
System.out.println("Hello!"); tets();
值传递
-
值传递(Pass-by-Value)是指将实际参数的值复制一份传递给形式参数,即在调用方法时,传递的是变量值的副本,而不是变量本身。在方法体内,对形式参数的任何修改都不会影响实际参数的值。
引用传递
-
引用传递(Pass-by-Reference)是指将实际参数的引用地址(内存地址)传递给形式参数,即在调用方法时,传递的是变量地址的副本,而不是变量值本身。在方法体内,对形式参数的任何修改都会反映到实际参数上,也就是说,实际参数的值也会发生相应的改变。
注意:
-
需要注意的是,Java中不支持引用传递,而是采用了类似于指针传递的方式来实现对对象的引用传递。即在方法调用时,传递的是对象引用的副本,而不是对象本身。这使得在方法体内可以对对象的状态进行修改,并将这些修改保存在原对象中,从而达到了"看似"引用传递的效果。
Java访问控制修饰符
-
不写访问控制修饰符,则默认为default
-
在Java中,访问控制修饰符 (Access Control Modifier) 用于限制类、变量、方法等的访问权限,可以保证程序的安全性和可维护性。Java中有四种访问控制修饰符。
-
public public表示公共的,是最为宽松的访问控制修饰符。使用public修饰的成员可以被任何代码访问,在整个程序中都可见。
-
private private表示私有的,是最为严格的访问控制修饰符。使用private修饰的成员只能在所属类内部被访问,其他类无法访问。
-
protected protected表示受保护的,使用protected修饰的成员可以在本类、同包下的其他类中、以及该类的子类中被访问,但是在其他包下的类中不可访问。
-
default 默认访问控制修饰符 如果没有使用任何访问控制修饰符,那么默认访问控制修饰符 (Package Access Modifier) 会被应用。使用默认访问控制修饰符修饰的成员可以在本类和同包下的其他类中被访问,但是在其他包下的类中不可访问。
-
-
需要注意的是,访问控制修饰符只能用于类的成员(如变量、方法等),不能应用于类本身。在应用访问控制修饰符时,需要根据实际情况选择适当的修饰符,以保证程序的正确性和安全性。
-
Java中访问控制修饰符按照由宽松到严格的顺序为:public、protected、default、private
方法重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数
-
方法重载的规则:
-
方法名称必须相同
-
参数列表必须不同(参数个数不同、参数类型不同、参数排列顺序不同等)
-
方法的返回类型可以相同也可以不相同
-
仅仅返回类型不同不足以成为方法的重载
-
-
实现理论:
-
方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
-
命令行传参
-
有时候你希望运行一个程序的时候再给它传递消息。这要靠传递命令行参数给main()函数实现
-
当在java代码中写了package,编译时要注意:
# 不能写成:javac com.zqzq.method.Demo01.java # 会报错:javac: 找不到文件: com.zqzq.method.Demo01.java # 要到对应包下的文件夹下执行 # 正确写法(javac 文件名) javac Demo01.java # 不能写成:java Demo01 # 正确写法(java 包名.类名) java com.zqzq.method.Demo01
-
命令行传参语法
java com.zqzq.method.Demo01 arg1 arg2 arg3 ......
可变参数(不定项参数)(可变长参数)
-
JDK1.5开始,Java支持传递同类型的可变参数给一个方法
-
在方法声明中,在指定参数类型后加一个省略号(...)
-
一个方法中只能指定一个可变参数,他必须是方法的最后一个参数。任何普通的参数必须在它之前声明
递归
-
A方法调用B方法,我们很容易理解!
-
递归就是:A方法调用A方法!就是自己调用自己
-
利用递归可以用简单的程序来解决一些复杂的问题。它通过把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合
-
递归结构包括两个部分:
-
递归头:什么时候不调用自身方法。如果没有头,将陷入死循环
-
递归体:什么时候调用自身方法
-