Java 基础入门(五):控制台输入输出与方法详解
文章目录
- 一、控制台输出
- 1.1 常见的输出方法
- 1.1.1 println():输出并换行
- 1.1.2 print():输出但不换行
- 1.1.3 printf():格式化输出
- 二、控制台输入
- 2.1 Scanner 的基本使用
- 2.2 输入字符串
- 2.2.1 next():读取一个单词
- 2.2.2 nextLine():读取一整行
- 2.2.3 next() 与 nextLine() 的区别
- 2.3 输入整数
- 2.4 输入浮点数
- 2.5 Scanner 常用输入方法总结
- 2.6 如何处理多组输入?
- 三、方法的概念与使用
- 3.1 方法的概念
- 3.2 方法的定义
- 3.3 方法的定义与调用
- 3.4 方法的返回值
- 3.4.1 有返回值的方法
- 3.4.2 没有返回值的方法
- 3.5 方法的参数
- 3.6 形参和实参
- 3.7 Java 的参数传递:值传递
- 3.7.1 为什么 swap() 不能交换两个 int 变量?
- 3.7.2 结合方法调用栈理解
- 四、方法重载
- 4.1 方法重载的概念
- 4.2 方法重载示例
- 4.3 重载方法如何匹配?
一、控制台输出
在 Java 中,控制台输出是指将程序运行过程中产生的信息显示在控制台上。
前面的学习中,我们已经多次使用:
System.out.println();实际上,Java 还提供了其他常见的输出方式。
1.1 常见的输出方法
Java 中常见的控制台输出方法包括:
| 方法 | 作用 |
|---|---|
System.out.print() | 输出内容,不自动换行 |
System.out.println() | 输出内容,结束后换行 |
System.out.printf() | 按照指定格式输出内容 |
1.1.1 println():输出并换行
publicclassOutputDemo{publicstaticvoidmain(String[]args){System.out.println("Hello");System.out.println("Java");}}运行结果:
Hello Javaprintln()在输出指定内容后,会自动换行。
因此,下一次输出会从新的一行开始。
1.1.2 print():输出但不换行
publicclassOutputDemo{publicstaticvoidmain(String[]args){System.out.print("Hello ");System.out.print("Java");}}运行结果:
Hello Javaprint()不会自动换行,因此后续内容会继续输出在同一行。
如果希望主动换行,可以使用转义字符\n。
例如:
System.out.print("Hello\nJava");运行结果:
Hello Java1.1.3 printf():格式化输出
printf()允许在字符串中使用格式说明符,按照指定格式输出数据。
例如:
publicclassOutputDemo{publicstaticvoidmain(String[]args){Stringname="Tom";intage=20;doublescore=95.678;System.out.printf("姓名:%s,年龄:%d,成绩:%.2f%n",name,age,score);}}运行结果:
姓名:Tom,年龄:20,成绩:95.68常见的格式说明符:
| 格式说明符 | 作用 | 示例 |
|---|---|---|
%d | 输出十进制整数 | 20 |
%f | 输出浮点数 | 3.140000 |
%.2f | 保留两位小数 | 3.14 |
%s | 输出字符串形式的内容 | Hello |
%c | 输出字符 | A |
%b | 输出布尔形式的内容 | true |
二、控制台输入
前面编写的程序中,大部分数据都是直接写在代码中的。
例如:
intage=20;但实际开发中,数据往往需要由用户输入。
为了在 Java 程序中读取控制台输入,可以使用Scanner类。
2.1 Scanner 的基本使用
Scanner位于java.util包中,因此使用之前需要导入:
importjava.util.Scanner;随后创建Scanner对象:
Scannerscanner=newScanner(System.in);其中:
Scanner:Java 提供的输入扫描类。scanner:创建的对象名称。new Scanner(System.in):创建一个从标准输入读取数据的 Scanner 对象。System.in:Java 的标准输入流,通常对应控制台输入。
现在还没有正式学习类和对象,因此暂时只需要掌握这段代码的基本用法即可。
2.2 输入字符串
使用Scanner输入字符串时,常见的两个方法是:
next()nextLine()虽然它们都能读取字符串,但读取规则不同。
2.2.1 next():读取一个单词
next()会读取下一个以空白字符分隔的输入内容。
这里的空白字符通常包括:
- 空格
- 制表符
- 换行符
示例:
importjava.util.Scanner;publicclassInputDemo{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);System.out.print("请输入姓名:");Stringname=scanner.next();System.out.println("姓名:"+name);}}假设输入:
Zhang San程序输出:
姓名:Zhang这是因为next()遇到空格后,当前内容读取结束。
2.2.2 nextLine():读取一整行
如果希望读取包含空格的完整内容,可以使用nextLine()。
importjava.util.Scanner;publicclassInputDemo{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);System.out.print("请输入姓名:");Stringname=scanner.nextLine();System.out.println("姓名:"+name);}}假设输入:
Zhang San程序输出:
姓名:Zhang SannextLine()会读取当前行剩余的内容,直到遇到行结束位置,并且不会将换行符包含在返回的字符串中。
2.2.3 next() 与 nextLine() 的区别
| 比较项 | next() | nextLine() |
|---|---|---|
| 读取单位 | 一个以空白分隔的内容 | 当前行剩余内容 |
| 能否读取带空格的完整句子 | 不适合 | 可以 |
| 遇到空格 | 当前内容结束 | 继续读取 |
| 遇到换行 | 作为分隔符 | 结束当前行 |
注意:混合使用 nextInt() 与 nextLine() 时,需要特别小心。
例如:
Scannerscanner=newScanner(System.in);System.out.print("请输入年龄:");intage=scanner.nextInt();System.out.print("请输入姓名:");Stringname=scanner.nextLine();假设用户输入年龄20后按下回车。
此时nextInt()只读取整数,当前行末尾的换行仍然留在输入中。
紧接着执行nextLine(),它会读取当前行剩余的内容,因此可能直接得到一个空字符串。
如果希望接下来输入新的一行,可以先读取掉当前行的剩余内容:
intage=scanner.nextInt();scanner.nextLine();// 消耗当前行剩余内容Stringname=scanner.nextLine();这是Scanner使用过程中非常常见的易错点。
2.3 输入整数
如果希望用户输入整数,可以使用:
nextInt()例如:
importjava.util.Scanner;publicclassInputDemo{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);System.out.print("请输入年龄:");intage=scanner.nextInt();System.out.println("年龄:"+age);}}示例运行:
请输入年龄:20 年龄:20需要注意,nextInt()要求下一个输入内容能够按照相应的整数格式解析。
如果输入的是无法解析为整数的内容,例如abc,就可能抛出InputMismatchException。
2.4 输入浮点数
如果希望读取小数,可以根据需要使用:
nextFloat()nextDouble()例如:
importjava.util.Scanner;publicclassInputDemo{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);System.out.print("请输入体重:");doubleweight=scanner.nextDouble();System.out.println("体重:"+weight);}}示例运行:
请输入体重:65.5 体重:65.5其中:
nextFloat():读取float类型的数据。nextDouble():读取double类型的数据。
2.5 Scanner 常用输入方法总结
| 方法 | 作用 |
|---|---|
next() | 读取下一个字符串内容 |
nextLine() | 读取当前行剩余内容 |
nextInt() | 读取 int 整数 |
nextFloat() | 读取 float 浮点数 |
nextDouble() | 读取 double 浮点数 |
这些方法的输入格式应当与预期的数据类型一致,否则可能出现输入异常。
2.6 如何处理多组输入?
在算法练习中,经常需要连续读取多个整数,但题目不一定提前告知输入数据的数量。
这时,可以结合while循环和Scanner的hasNextInt()方法实现。
例如:
importjava.util.Scanner;publicclassInputDemo{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);while(scanner.hasNextInt()){intnum=scanner.nextInt();System.out.println(num);}}}运行过程:
程序启动后,等待用户输入整数。
10 // 用户输入 10,按下回车 10 // 程序输出 10 20 // 用户输入 20,按下回车 20 // 程序输出 20 30 // 用户输入 30,按下回车 30 // 程序输出 30注意:
hasNextInt()用于判断下一个输入内容能否解析为int,本身不会消耗该整数。nextInt()用于实际读取整数。- 输入三个整数后,程序不会自动结束,而是继续等待后续输入。
- 如果需要主动结束输入,可以向控制台发送文件结束标记(EOF)。Windows 命令行通常使用
Ctrl + Z后按回车;Linux、macOS 终端通常使用Ctrl + D。IDEA 中的操作可能因控制台配置而不同。
此外,也可以一次性输入10 20 30,因为nextInt()会按照空白字符分隔读取每个整数。但在学习阶段,逐个输入更有助于理解循环读取的执行过程。
三、方法的概念与使用
在前面的学习中,我们已经能够使用流程控制解决一些问题。
例如,判断某一年是否为闰年:
intyear=2024;if((year%4==0&&year%100!=0)||year%400==0){System.out.println("是闰年");}else{System.out.println("不是闰年");}如果程序中有多个位置都需要判断闰年,难道每次都需要重新编写这段代码吗?
显然没有必要。
这时,就可以使用方法(Method),将具有特定功能的代码组织起来,方便重复调用。
3.1 方法的概念
方法是 Java 中用于完成特定功能的一段代码。
通过方法,我们可以将复杂的程序拆分为多个功能相对独立的部分。
使用方法具有以下好处:
- 提高代码复用性:相同功能不需要重复编写。
- 提高代码可读性:通过方法名称表达功能。
- 降低维护成本:修改某个功能时,可以集中修改对应方法。
- 便于分解问题:将复杂问题拆分为多个简单任务。
3.2 方法的定义
在当前基础阶段,可以先掌握以下常见写法:
publicstatic返回值类型 方法名(参数列表){// 方法体return返回值;}其中:
| 组成部分 | 含义 |
|---|---|
public | 访问修饰符 |
static | 静态修饰符 |
| 返回值类型 | 表示方法返回结果的类型 |
| 方法名 | 用于标识并调用方法 |
| 参数列表 | 用于接收调用方法时传入的数据 |
| 方法体 | 方法实际执行的代码 |
return | 结束当前方法,可同时返回结果 |
这里的public和static涉及后续的面向对象知识。
现阶段可以先理解为:使用static定义的静态方法,可以在同一个类的静态main方法中直接通过方法名调用。
3.3 方法的定义与调用
以判断闰年为例。
我们可以将判断逻辑封装成一个方法:
publicclassMethodDemo{// 判断一个年份是否为闰年publicstaticbooleanisLeapYear(intyear){return(year%4==0&&year%100!=0)||year%400==0;}publicstaticvoidmain(String[]args){intyear=2024;booleanresult=isLeapYear(year);if(result){System.out.println("是闰年");}else{System.out.println("不是闰年");}}}运行结果:
是闰年3.4 方法的返回值
方法可以有返回值,也可以没有返回值。
3.4.1 有返回值的方法
例如,计算两个整数之和:
publicstaticintadd(inta,intb){returna+b;}调用:
intresult=add(10,20);System.out.println(result);// 30这里的int表示方法返回一个整数结果。
return a + b;会将计算结果返回给调用方,并结束当前方法。
3.4.2 没有返回值的方法
如果方法只负责输出信息,不需要向调用者返回结果,可以使用void。
例如:
publicstaticvoidhello(){System.out.println("Hello Java");}调用:
hello();运行结果:
Hello Java注意:
- 有返回值的方法,需要保证正常完成的执行路径符合返回值要求。
void方法不返回结果,但可以使用单独的return;提前结束方法。- 方法的返回类型需要与实际返回的表达式在 Java 类型规则下兼容。
3.5 方法的参数
方法可以通过参数接收外部传入的数据。
例如:
publicstaticintadd(inta,intb){returna+b;}这里的a、b就是方法定义中的参数。
调用时:
add(10,20);向方法传入了两个实际数值。
这就涉及两个重要概念:形参和实参。
3.6 形参和实参
形参(Formal Parameter)
形参是方法定义时声明的参数,用于接收调用方传入的数据。
例如:
publicstaticintadd(inta,intb)这里的:
a、b就是形参。
实参(Actual Argument)
实参是调用方法时提供的实际参数值或表达式。
例如:
add(10,20);这里的:
10、20就是实参。
方法调用时,需要满足相应的参数匹配规则,包括参数数量、类型兼容性以及参数顺序等。
对于普通的位置参数调用,实参与形参按位置对应。
例如:
publicstaticvoidprintInfo(Stringname,intage){System.out.println(name+":"+age);}正确调用:
printInfo("Tom",20);不能直接将两种不同类型的参数顺序颠倒:
// printInfo(20, "Tom"); // 编译错误3.7 Java 的参数传递:值传递
Java 的方法参数传递采用值传递(Pass by Value)。
所谓值传递,就是调用方法时,将实参表达式计算得到的值复制一份,用于初始化形参。
对于基本数据类型,形参与调用方的变量相互独立,修改形参不会影响调用方变量的值。
3.7.1 为什么 swap() 不能交换两个 int 变量?
先观察下面的代码:
publicclassTest{publicstaticvoidswap(intx,inty){inttemp=x;x=y;y=temp;}publicstaticvoidmain(String[]args){inta=10;intb=20;swap(a,b);System.out.println("a = "+a);System.out.println("b = "+b);}}运行结果:
a = 10 b = 20明明在swap()中执行了交换操作,为什么a和b的值没有改变?
3.7.2 结合方法调用栈理解
Java 中,每次方法调用都会创建对应的栈帧(Stack Frame),用于保存本次调用的局部变量及其他执行状态。
① 调用 swap() 前
此时只有main()方法的栈帧:
栈顶 ┌─────────────────┐ │ main() │ │ a = 10 │ │ b = 20 │ └─────────────────┘ 栈底② 调用 swap(a, b)
执行swap(a, b)时,会创建新的栈帧,并将a、b的值分别复制给形参x、y。
栈顶 ┌─────────────────┐ │ swap() │ │ x = 10 │ │ y = 20 │ ├─────────────────┤ │ main() │ │ a = 10 │ │ b = 20 │ └─────────────────┘ 栈底注意:x、y与a、b是不同的局部变量。
③ swap() 内部完成交换
inttemp=x;x=y;y=temp;此时:
栈顶 ┌─────────────────┐ │ swap() │ │ x = 20 │ │ y = 10 │ │ temp = 10 │ ├─────────────────┤ │ main() │ │ a = 10 │ │ b = 20 │ └─────────────────┘ 栈底可以发现,交换的只是swap()中的形参,main()中的变量并未改变。
④ swap() 执行结束
swap()对应的栈帧退出,程序返回main()继续执行。
因此,最终输出仍然是:
a = 10 b = 20以上栈帧图仅用于说明方法调用和局部变量之间的关系,并非 JVM 的完整内存结构。
四、方法重载
在实际开发中,有时多个方法完成的功能相似,但需要处理的参数不同。
例如:
- 计算两个整数之和。
- 计算三个整数之和。
- 计算两个浮点数之和。
如果每个方法都使用不同名称,可能降低代码的统一性。
Java 提供了方法重载(Method Overloading)来解决这类问题。
4.1 方法重载的概念
方法重载是指在同一个类中,允许定义多个名称相同、但参数列表不同的方法。
构成方法重载需要满足:
- 方法名称相同。
- 参数列表不同。
其中,参数列表不同可以体现为:
- 参数数量不同。
- 参数类型不同。
- 参数类型的排列顺序不同。
注意:方法的返回值类型不能单独作为判断重载的依据。
4.2 方法重载示例
publicclassOverloadDemo{// 两个整数相加publicstaticintadd(inta,intb){returna+b;}// 三个整数相加publicstaticintadd(inta,intb,intc){returna+b+c;}// 两个 double 类型数据相加publicstaticdoubleadd(doublea,doubleb){returna+b;}publicstaticvoidmain(String[]args){System.out.println(add(10,20));System.out.println(add(10,20,30));System.out.println(add(1.5,2.5));}}运行结果:
30 60 4.0虽然三个方法都叫add,但参数列表不同,因此可以构成方法重载。
4.3 重载方法如何匹配?
在调用重载方法时,Java 编译器会根据方法名称和实际参数,按照方法调用的匹配规则选择合适的方法。
例如:
add(10,20);两个参数都是int,因此可以匹配:
add(inta,intb)如果调用:
add(1.5,2.5);则可以匹配:
add(doublea,doubleb)下一篇文章将介绍Java 程序调试(Debug),重点讲解 IntelliJ IDEA 中断点的设置、Debug 模式的使用、单步执行、变量值的观察以及方法调用过程的跟踪,帮助读者掌握程序调试的基本方法,学会分析代码执行流程、定位错误,并进一步加深对方法调用和递归执行过程的理解。