静态static小问题20241224
package com.pangHuHuStudyJava.scanner;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
int i;
float f;
Scanner scanner = new Scanner(System.in);
// 输入整数
System.out.println("请输入一个整数:");
if (scanner.hasNextInt()) {
i = scanner.nextInt();
System.out.println("你输入的整数是:" + i);
} else {
System.out.println("你输入的不是整数!");
scanner.next(); // 清除错误输入
}
// 输入小数
System.out.println("请输入一个小数:");
if (scanner.hasNextFloat()) {
f = scanner.nextFloat();
System.out.println("你输入的小数是:" + f);
} else {
System.out.println("你输入的不是小数!");
scanner.next(); // 清除错误输入
}
scanner.close(); // 关闭资源
}
}
为什么我把i f 定义在main方法外就错了啊?
package com.pangHuHuStudyJava.scanner; import java.util.Scanner; public class Demo04 { int i; float f; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 输入整数 System.out.println("请输入一个整数:"); if (scanner.hasNextInt()) { i = scanner.nextInt(); System.out.println("你输入的整数是:" + i); } else { System.out.println("你输入的不是整数!"); scanner.next(); // 清除错误输入 } // 输入小数 System.out.println("请输入一个小数:"); if (scanner.hasNextFloat()) { f = scanner.nextFloat(); System.out.println("你输入的小数是:" + f); } else { System.out.println("你输入的不是小数!"); scanner.next(); // 清除错误输入 } scanner.close(); // 关闭资源 } }
变量定义位置的区别
- 定义在方法内部:
- 变量
i
和f
定义在main
方法内,属于局部变量。- 局部变量的作用范围仅限于所在方法,在方法执行结束后,变量也随之销毁。
- 这种情况下,变量在定义时会在堆栈中分配空间,Java 会确保你在使用局部变量前对其赋值。
- 定义在方法外部(类内):
- 如果将变量定义在
main
方法外,且不加Static
而直接放在类中,它们就成为类的成员变量,也叫实例变量。- 成员变量的作用范围是整个类,但它们依赖于类的实例,如果没有创建实例,成员变量是无法直接使用的(除非是
static
修饰的类变量)。- 你的
i
和f
是非static
成员变量,而main
方法是static
的,不能直接访问这些非static
成员变量。为什么会出错?
在 Java 中,
main
方法是一个静态方法 (static
),属于类本身,而不是类的对象。如果i
和f
是非静态变量,那么它们属于类的对象,必须通过对象来访问。由于main
是静态方法,它无法直接访问非静态变量。那如果我的方法不是静态的可以访问实例变量吗?
是的,非静态方法可以直接访问实例变量。因为非静态方法是依赖于对象实例的,而实例变量也属于对象,所以非静态方法能够直接访问实例变量。
示例代码
public class Example { int instanceVar = 42; // 实例变量 static int staticVar = 100; // 静态变量 // 非静态方法 public void nonStaticMethod() { System.out.println("实例变量: " + instanceVar); // 可以直接访问实例变量 System.out.println("静态变量: " + staticVar); // 也可以直接访问静态变量 } public static void main(String[] args) { Example obj = new Example(); // 创建实例 obj.nonStaticMethod(); // 调用非静态方法 } }
输出:
makefile复制代码实例变量: 42 静态变量: 100
为什么非静态方法可以访问实例变量?
- 非静态方法需要实例化对象:
- 非静态方法只能通过对象调用,而对象本身携带实例变量的值。因此,非静态方法可以直接访问实例变量。
- 对象的作用域:
- 每个对象实例有独立的实例变量(存储在堆内存中),非静态方法运行时可以引用这些变量。
- 非静态方法可以访问静态变量:
- 静态变量是全局共享的,所有实例都可以访问静态变量,非静态方法也可以直接访问。
总结
- 非静态方法可以直接访问实例变量和静态变量。
- 实例变量属于对象,非静态方法可以通过对象(实例)直接引用。
- 静态变量属于类(类变量),无论是静态方法还是非静态方法都可以访问。
如何修复?
有两种方法:
方法 1:将
i
和f
定义为静态变量package com.pangHuHuStudyJava.scanner; import java.util.Scanner; public class Demo04 { static int i; // 定义为静态变量 static float f; // 定义为静态变量 public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 输入整数 System.out.println("请输入一个整数:"); if (scanner.hasNextInt()) { i = scanner.nextInt(); System.out.println("你输入的整数是:" + i); } else { System.out.println("你输入的不是整数!"); scanner.next(); // 清除错误输入 } // 输入小数 System.out.println("请输入一个小数:"); if (scanner.hasNextFloat()) { f = scanner.nextFloat(); System.out.println("你输入的小数是:" + f); } else { System.out.println("你输入的不是小数!"); scanner.next(); // 清除错误输入 } scanner.close(); } }
方法 2:通过对象访问非静态变量
如果
i
和f
是非静态成员变量,需要创建类的实例才能访问:package com.pangHuHuStudyJava.scanner; import java.util.Scanner; public class Demo04 { int i; // 非静态变量 float f; // 非静态变量 public static void main(String[] args) { Demo04 demo = new Demo04(); // 创建类的实例 其实还是通过构造实例(对象)去修改实例变量 Scanner scanner = new Scanner(System.in); // 输入整数 System.out.println("请输入一个整数:"); if (scanner.hasNextInt()) { demo.i = scanner.nextInt(); System.out.println("你输入的整数是:" + demo.i); } else { System.out.println("你输入的不是整数!"); scanner.next(); // 清除错误输入 } // 输入小数 System.out.println("请输入一个小数:"); if (scanner.hasNextFloat()) { demo.f = scanner.nextFloat(); System.out.println("你输入的小数是:" + demo.f); } else { System.out.println("你输入的不是小数!"); scanner.next(); // 清除错误输入 } scanner.close(); } }
总结
- 如果你想在
main
方法直接访问变量,那么将它们定义为static
是最方便的方式。- 如果变量不需要是静态的,可以通过创建对象来访问非静态成员变量。
- 静态方法无法直接访问非静态变量,因为静态方法、变量属于类,非静态变量属于对象。
顺序结构 20241224
顺序结构
◆JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
◆ 顺序结构是最简单的算法结构。
◆语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。
package com.pangHuHuStudyJava.struct; public class SequentialStructure { public static void main(String[] args) { System.out.println("hello1"); System.out.println("hello2"); System.out.println("hello3"); System.out.println("hello4"); } }
if()选择结构20241224
if单选择结构
if双选择结构
if多选择结构
嵌套的if结构
switch多选择结构
if单选择结构
我们很多时候要判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
package com.pangHuHuStudyJava.struct; import java.util.Scanner; /* ****************if单选择结构************ if双选择结构 if多选择结构 嵌套的if结构 switch多选择结构 */ public class IfSelectStructureDemo01 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String str=scanner.nextLine(); if(str.equals("Hello")){//比较字符串内容! System.out.println("你输入的字符串是:Hello"); } System.out.println("End"); scanner.close(); } }
if()else双选择结构
语法:
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
package com.pangHuHuStudyJava.struct; import java.util.Scanner; /* if单选择结构 ****************if双选择结构**************** if多选择结构 嵌套的if结构 switch多选择结构 */ public class IfSelectStructureDemo02 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入你的分数:"); int score=scanner.nextInt(); if(score>=60){ System.out.println("恭喜你,你的成绩及格了!"); } else{ System.out.println("很遗憾,你的成绩不及格!"); } scanner.close(); } }
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 com.pangHuHuStudyJava.struct; import java.util.Scanner; /* if单选择结构 if双选择结构 ****************if多选择结构**************** 嵌套的if结构 switch多选择结构 */ public class IfSelectStructureDemo03 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入你的成绩"); int score = scanner.nextInt(); if(score==100){ System.out.println("恭喜!你的成绩是满分!"); } else if(score>=90 && score<100){ System.out.println("你的成绩为A等!"); } else if(score>=80 && score<90){ System.out.println("你的成绩为B等!"); } else if(score>=80 && score<70){ System.out.println("你的成绩为C等!"); } else if(score>=60 && score<70){ System.out.println("你的成绩为D等!"); } else if(score>=0 && score<60){ System.out.println("你的成绩不合格!"); } else { System.out.println("你输入的成绩不合法!"); } scanner.close(); } }
嵌套的if结构
使用嵌套的if...else语句是合法的。也就是说你可以在另一个if或者else if语句中使用if或者else if语句。你可以像if语句一样嵌套else if...else。
语法:
if(布尔表达式1){ ////如果布尔表达式1的值为true执行代码 }if(布尔表达式2){ ////如果布尔表达式2的值为true执行代码 }
switch选择结构
多选择结构还有一个实现方式是:switch case语句
switch case语句判断一个变量与一系列值中每个值是否相等,每个值称为一个分支
switch语句中的变量类型可以是:
byte、short、int、char
从Java SE 7 开始,switch 支持字符串String类型了
同时case标签必须为字符串常量或字面量
switch(expression){ case value : //语句块 break; case value : //语句块 break; default : //语句块 }
switch语句中,case具有穿透现象!
执行case分支语句时,即使case 满足条件如果没加 break;,继续也会继续向下执行,直到整个switch语句执行完毕才能结束。
当语句块后有== break==;时,程序会跳出switch语句。
default关键字在 switch 语句不匹配 case 中所有值时执行。
package com.pangHuHuStudyJava.struct; /* if单选择结构 if双选择结构 if多选择结构 嵌套的if结构 ****************switch多选择结构**************** */ import java.util.Scanner; public class SwitchSelectStructureDemo01 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String str = scanner.nextLine(); switch (str) { case "巢安龙": System.out.println("你输入的是:巢安龙"); break; case "CAL": System.out.println("你输入的是:CAL"); break; default: System.out.println("抱歉,没有识别到你输入的字符!"); break; } scanner.close(); } }
哈希值问题 反编译 javap -c ****.class
package com.pangHuHuStudyJava.struct; /* if单选择结构 if双选择结构 if多选择结构 嵌套的if结构 ****************switch多选择结构**************** */ import java.util.Scanner; public class SwitchSelectStructureDemo01 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String str = scanner.nextLine(); switch (str) { case "巢安龙": System.out.println("你输入的是:巢安龙"); break; case "CAL": System.out.println("你输入的是:CAL"); break; default: System.out.println("抱歉,没有识别到你输入的字符!"); break; } System.out.println("巢安龙".hashCode()); // 输出 23863954 System.out.println("CAL".hashCode()); // 输出 66478 System.out.println(str.hashCode()); // 输出 66478 scanner.close(); } }
第25行 第26行 打印两字符串的哈希值
第27行 打印输入字符串的哈希值!
输入:asdasdasda
抱歉,没有识别到你输入的字符!
23863954
66478
-1817180433D:\download\code\JavaSE\out\production\基础语法\com\pangHuHuStudyJava\struct>dir 驱动器 D 中的卷是 新加卷 卷的序列号是 5073-C048 D:\download\code\JavaSE\out\production\基础语法\com\pangHuHuStudyJava\struct 的目录 2024/12/24 15:40 <DIR> . 2024/12/24 15:05 <DIR> .. 2024/12/24 15:05 1,072 IfSelectStructureDemo01.class 2024/12/24 15:09 1,038 IfSelectStructureDemo02.class 2024/12/24 15:37 1,326 IfSelectStructureDemo03.class 2024/12/24 15:05 685 SequentialStructure.class 2024/12/24 15:37 1,302 SwitchSelectStructureDemo01.class 5 个文件 5,423 字节 2 个目录 183,152,959,488 可用字节 D:\download\code\JavaSE\out\production\基础语法\com\pangHuHuStudyJava\struct>javap -c SwitchSelectStructureDemo01.class Compiled from "SwitchSelectStructureDemo01.java" public class com.pangHuHuStudyJava.struct.SwitchSelectStructureDemo01 { public com.pangHuHuStudyJava.struct.SwitchSelectStructureDemo01(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: new #2 // class java/util/Scanner 3: dup 4: getstatic #3 // Field java/lang/System.in:Ljava/io/InputStream; 7: invokespecial #4 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V 10: astore_1 11: aload_1 12: invokevirtual #5 // Method java/util/Scanner.nextLine:()Ljava/lang/String; 15: astore_2 16: aload_2 17: astore_3 18: iconst_m1 19: istore 4 21: aload_3 22: invokevirtual #6 // Method java/lang/String.hashCode:()I 25: lookupswitch { // 2 66478: 67 23863954: 52 default: 79 } 52: aload_3 53: ldc #7 // String 巢安龙 55: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 58: ifeq 79 61: iconst_0 62: istore 4 64: goto 79 67: aload_3 68: ldc #9 // String CAL 70: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 73: ifeq 79 76: iconst_1 77: istore 4 79: iload 4 81: lookupswitch { // 2 0: 108 1: 116 default: 124 } 108: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream; 111: ldc #11 // String 你输入的是:巢安龙 113: invokevirtual #12 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 116: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream; 119: ldc #13 // String 你输入的是:CAL 121: invokevirtual #12 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 124: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream; 127: ldc #14 // String 抱歉,没有识别到你输入的字符! 129: invokevirtual #12 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 132: aload_1 133: invokevirtual #15 // Method java/util/Scanner.close:()V 136: return } D:\download\code\JavaSE\out\production\基础语法\com\pangHuHuStudyJava\struct>
第17行用了javap 反编译命令
javap -c SwitchSelectStructureDemo01.class
第43 44 行显示了哈希值
循环结构20241224
while循环结构
- while是最基本的循环,其结构式为:
while (布尔表达式){ }
- 只要布尔表达式为true,循环就会一直执行下去
- 我们大多数情况是会让循环停下来的,我们需要一个让表达式失效的方式来结束循环
- 少数情况需要循环一直执行,比如服务器的请求相应监听等
- 循环条件一直为true就会造成无限循环【死循环】,我们正常的业务应该尽量避免死循环。会影响程序性能或者程序卡死崩溃。
package com.pangHuHuStudyJava.struct; /** * while循环 */ public class CyclicStructureDemo01_While { public static void main(String[] args) { int i=0; int sum=0; /*while(i<100){ i++; System.out.println(i);*/ //循环输出1~100 while(i<100){ //i++; //sum+=i; sum+=++i; } System.out.println(sum); } }
输出结果:5050
do ...while循环
对于while语句而言,如果不满足条件,就不能进入循环。但有时候,我们需要即使不满足条件,也至少执行一次
do ... while循环和 while循环相似,不同的是,do ...while循环至少会执行一次
do{ //代码语句 }while(布尔表达式);
public class CyclicStructureDemo01_DoWhile { public static void main(String[] args) { int i = 0; int sum=0; do { i++; sum+=i; }while(i<100); System.out.println(sum); } }
输出:5050
while 和 do ...while 的区别:
- while先判断后执行,do ...while是先执行后判断!
- do ...while总是保证循环体会被至少执行一次。这是他们的主要差别。
package com.pangHuHuStudyJava.struct; import java.sql.SQLOutput; //简单说明一下 while 和do while 之间的区别 //do while 会至少执行一次先执行再判断 //while 是先判断再执行 public class CyclicStructureDemo03_DoWhile { public static void main(String[] args) { int a=0; while (a<0){ a++; } System.out.println(a); System.out.println("=================="); do{ a++; }while (a<0); System.out.println(a); } }
输出结果:
0
================
1
for循环
for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构
for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化值;布尔表达式;更新){ //代码语句 }
关于for循环有以下几点说明:
最先执行初始化步骤,可以说明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
然后,检测布尔表达式的值。如果为true,循环体被执行;如果为false,循环中止,开始执行循环体后面的语句
再次检测布尔表达式,循环执行上面的过程
for(;;)//死循环 { //语句块__________________注意这也是个死循环 }
package com.pangHuHuStudyJava.struct; public class CyclicStructureDemo04_For { public static void main(String[] args) { int a = 1; for (;;) { System.out.println(a); a++; } } }
等同于
package com.pangHuHuStudyJava.struct; public class CyclicStructureDemo04_For { public static void main(String[] args) { int a = 1; while(true){ System.out.println(a); a++; } } }
IDEA 快捷键 100.for
1.计算1~100内的所有奇数和 偶数和
package com.pangHuHuStudyJava.struct; //计算1~100内奇数和、偶数和 public class CyclicStructureDemo05_For { public static void main(String[] args) { int odd_sum = 0; int even_sum = 0; for (int i = 0; i <=100; i++) { if(i % 2 == 0) { odd_sum += i; } if(i % 2 ==1) { even_sum += i; } } System.out.println("odd_sum:"+odd_sum); System.out.println("even_sum:"+even_sum); } }
输出结果:
odd_sum:2550
even_sum:25002.用while 或者for循环输出1-1000之间能被5整除的数,且每行输出3个
package com.pangHuHuStudyJava.struct; //用while 或者for循环输出1-1000之间能被5整除的数,且每行输出3个 public class CyclicStructureDemo06_For { public static void main(String[] args) { int count=0; for (int i = 0; i < 1000; i++) { if(i % 5 ==0 ){ System.out.print(i+"\t"); count++; if (count % 3 ==0){ System.out.println("\n"); } } } } }
public static void main(String[] args) { int count = 0; int i=0; while(i<=1000){ if(i % 5 ==0){ System.out.print(i+"\t"); count++; if(count % 3==0){ System.out.println(); } } i++; } }
输出
System.out.print(i+"\t");//输出不换行
System.out.println();//输出换行
3.打印99乘法表
package com.pangHuHuStudyJava.struct; //打印99乘法表 public class CyclicStructureDemo07_For { public static void main(String[] args) { 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(); } } }
1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
4.增强型for循环
- 这里我们先只是见一面,做个了解,之后数组我们重点使用
- Java5引入了一种主要用于数组或集合的增强型for循环。
- Java增强for循环语法格式如下:
for (int x :numbers){ System.out.println(x); }
package com.pangHuHuStudyJava.struct; //增强型 for循环 public class CyclicStructureDemo08_For { public static void main(String[] args) { int[] numbers ={10,15,20,25,30,35}; for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); } System.out.println("================="); for (int x :numbers){ System.out.println(x); } } }
Break continue label 标签 20241224
break、continue、goto
break
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
public static void main(String[] args) { int i=0; while (i<100){ i++; System.out.println(i); if (i==30){ break; } } System.out.println("break停止循环");//break是跳出了循环并没有中止程序。
package com.pangHuHuStudyJava.struct; //测试break 跳循环的范围 跳出最近一层 public class BreakDemo02 { public static void main(String[] args) { for (int i = 1; i < 3; i++) { //外部循环 for (int j = 1; j < 10; j++) { //内部循环 if(j % 3 == 0){ System.out.println("马上执行到第9行break,内部循环中断"); break;//注意这里退出最近循环 内部的的for循环退出 第11行不执行的 } System.out.println("i=" + i + " j=" + j);//这行,到break执行后是不执行的,程序直接跳到13行 执行外部循环 } System.out.println("外部循环继续"); } } }
输出结果
i=1 j=1 i=1 j=2 马上执行到第9行break,内部循环中断 外部循环继续 i=2 j=1 i=2 j=2 马上执行到第9行break,内部循环中断 外部循环继续
break 如何跳出两层循环呢?
方法一:使用布尔值 在第一次跳出 设置布尔值变化,外一层循环判断布尔值变化,若变化,则再break一次退出外层循环
package com.pangHuHuStudyJava.struct; public class BreakDemo03 { public static void main(String[] args) { boolean flag = true; for (int i = 1; i < 3; i++) { for (int j = 1; j < 10; j++) { if(j % 3 == 0){ flag = false; //在第一次跳出前,改变标志位 System.out.println("跳出内层循环"); break;//执行到此处时,立即退出最近循环(内层for循环) 跳到15行去了 } System.out.println("i="+i+",j="+j); } if(flag==false){ //检测到标志位变化 执行16行 System.out.println("跳出外层循环"); break;//退出最外层循环 (外层for 循环) } } } }
输出结果:
i=1,j=1 i=1,j=2 跳出内层循环 跳出外层循环
方法二:设置标签,break 直接跳转到标签位置
package com.pangHuHuStudyJava.struct; public class BreakDemo04 { public static void main(String[] args) { outer:for (int i = 1; i < 4; i++) { for (int j = 1; j < 10; j++) { if(j % 3 == 0){ System.out.println("开始跳转,直接退出最外层循环"); break outer;//直接跳到outer位置,设置在最外层循环 跳出整个外层循环,程序从跳到14行了 } System.out.println("i="+i+",j="+j);//第六句判断成立后执行到第8句 这一句是不执行的 直接跳到14行 } System.out.println("test");//第六句判断成立后执行到第8句 这一句是不执行的 直接跳到14行 } System.out.println("test1"); } }
输出结果:
i=1,j=1 i=1,j=2 开始跳转,直接退出最外层循环 test1
continue
continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着执行下一次是否执行循环的判定。
package com.pangHuHuStudyJava.struct; //测试continue public class ContinueDemo01 { public static void main(String[] args) { int num=0; while(num<100){ num++; if(num % 30 ==0){ System.out.println();//每次跳出前 换下行 continue;//直接跳出 此次循环 (num=30) 但是循环还是会继续的程序又从第6行开始(31 61 91) 相当于只剔除了 30 60 90 } System.out.print(num+"\t"); } } }
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 97 98 99 100
如果是双层循环,可以用continue跳标签 比较下和break break 跳标签的区别
package com.pangHuHuStudyJava.struct; public class ContinueDemo02 { public static void main(String[] args) { for (int i = 1; i < 4; i++) { for (int j = 1; j < 10; j++) { if (j % 3 == 0) { System.out.println("开始跳转"); break;//直接跳出当前循环 程序从12行开始 执行到外层循环底部在看是否满足循环条件,继续两组循环 } System.out.println("i=" + i + ",j=" + j); } System.out.println("test"); } System.out.println("test1"); } }
输出结果:
i=1,j=1 i=1,j=2 开始跳转 test i=2,j=1 i=2,j=2 开始跳转 test i=3,j=1 i=3,j=2 开始跳转 test test1
continue 跳转标签
package com.pangHuHuStudyJava.struct; public class ContinueDemo03 { public static void main(String[] args) { outer:for (int i = 1; i < 4; i++) { for (int j = 1; j < 10; j++) { if(j % 3 == 0){ System.out.println("开始跳转"); continue outer;//跳出此次循环,到第四行判断程序程序是否继续循环 第12行跳开了 } System.out.println("i="+i+",j="+j); } System.out.println("test"); } System.out.println("test1"); } }
输出结果:
i=1,j=1 i=1,j=2 开始跳转 i=2,j=1 i=2,j=2 开始跳转 i=3,j=1 i=3,j=2 开始跳转 test1
goto
goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用,Java没有goto。然而在break和continue两个关键字身上,我们仍能看出一些goto的影子---带标签的break和continue
“标签”是指后面跟一个冒号的标识符,例如label:
对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
标签:scanner,分支,System,while,循环,println,out,public,结构 From: https://www.cnblogs.com/panghuhu-space/p/18628696总结:
我这是用了label 方法对吧?相当于goto方法,这种方法有什么好处,有什么坏处,一般在什么场合用它,有什么经典案例可以参考
ChatGPT 说:
ChatGPT
是的,你的代码使用了 Java 的 label(标签)方法,与传统的
goto
方式有一定相似性,但 Java 中没有直接的goto
关键字。标签结合break
或continue
可以实现类似goto
的跳转逻辑。以下是对这种方法的优缺点分析、适用场景以及经典案例。
标签方法的优缺点
优点
- 控制复杂循环流程
- 当嵌套循环层级较深时,标签方法可以快速跳出某些特定的外层循环,避免繁琐的逻辑判断,代码简洁明了。
- 减少标志变量
- 不需要通过额外的布尔变量来控制循环的退出条件,简化代码逻辑。
- 高效执行
- 在某些场景下,用标签跳转可以减少冗余判断,提高代码效率。
缺点
- 降低可读性
- 标签的逻辑不直观,尤其在复杂代码中,过多的标签会让人迷惑,破坏代码的结构化。
- 易引发逻辑混乱
- 由于标签会跳过部分代码执行路径,容易出现不易察觉的逻辑漏洞或隐藏的 Bug。
- 违反结构化编程原则
- 结构化编程强调通过条件判断和循环语句清晰地组织程序,而标签方法类似于
goto
,可能破坏这种结构性。
适用场景
- 复杂多层嵌套循环
- 在深层嵌套循环中,标签方法可以直接跳出多层循环而无需逐层判断。
示例:搜索二维数组中符合条件的某个值时,找到后直接终止外层循环。- 性能关键代码
- 当需要快速跳出多层循环以减少不必要的判断时,标签方法可以提高效率。
示例:图像处理或路径搜索等需要频繁遍历多维数据的场景。- 有限的控制流调整
- 当代码逻辑简单且标签使用得当时,可以通过标签减少额外的标志变量。
不适用场景
- 简单单层循环或逻辑清晰的代码
- 对于简单逻辑,使用标签显得多余且冗长。
- 替代一般逻辑控制
- 标签不能代替条件判断或函数调用,滥用标签可能导致难以维护的“意大利面条”代码(spaghetti code)。
经典案例
案例 1:查找二维数组中的第一个负数
public class LabelExample { public static void main(String[] args) { int[][] matrix = { {1, 2, 3}, {4, 5, -6}, {7, 8, 9} }; outer: // 定义外层标签 for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { if (matrix[i][j] < 0) { System.out.println("找到负数: " + matrix[i][j]); break outer; // 直接跳出外层循环 } } } System.out.println("搜索结束"); } }
输出:
makefile复制代码找到负数: -6 搜索结束
案例 2:跳过某些特定组合
java复制代码public class LabelContinueExample { public static void main(String[] args) { outer: for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { if (i == j) { System.out.println("跳过 i=" + i + ", j=" + j); continue outer; // 跳过当前外层循环迭代 } System.out.println("i=" + i + ", j=" + j); } } } }
输出:
css复制代码跳过 i=1, j=1 i=2, j=1 i=2, j=3 跳过 i=2, j=2 i=3, j=1 i=3, j=2 跳过 i=3, j=3
总结建议
- 标签方法的好处: 在嵌套循环层次较深时,能够有效控制程序流,避免复杂的标志变量判断。
- 标签方法的坏处: 使用不当会导致代码可读性差,特别是标签位置的跳转可能让人迷惑。
- 使用建议:
- 只在复杂嵌套循环或性能要求较高的场景中使用标签。
- 如果逻辑简单,优先通过
break
和continue
的普通用法实现。- 避免多处定义标签,保持代码简洁清晰。