Java快速入门---流程控制

Java学习笔记–流程控制

一、输入和输出

1.1、输出

在之前的代码中,我们总是使用System.out.println()来向屏幕输出一些内容。

println是print line的缩写,表示输出并换行,因此如果想不换行,可使用print()

public class Main{
    public static void main(String[] args) {
        System.out.print("A,");
        System.out.print("B,");
        System.out.print("C.");
        System.out.println();
        System.out.println("END");
        
        //A,B,C.
		//END
    }
}

1.2、格式化输出

为什么要格式化输出?因为计算机表示的数据不一定适合人来阅读,如下输出的结果:

public class Main {
    public static void main(String[] args) {
        double d = 12900000;
        System.out.println(d);	// 1.29E7
    } 
}

如果要把数据显示成我们期望的格式,就需要使用格式化输出的功能。格式化输出使用System.out.printf(),通过使用占位符%?printf()可以把后面的参数格式化成指定格式

public class Main{
    public static void main(String[] args) {
        double d = 3.1415926;
        System.out.printf("%.2f\n",d);	// 显示两位小数3.14
        System.out.printf("%.4f\n",d);	// 显示4位小数3.1416
    }
}
占位符说明
%d格式化输出整数
%x格式化输出十六进制整数
%f格式化输出浮点数
%e格式化输出科学计数法表示的浮点数
%s格式化字符串

注意:由于%表示占位符,因此,连续两个%%表示一个%字符本身。

占位符本身还可以有更详细的格式化参数。下面的例子把一个整数格式化成十六进制,并用0补足8位:

public class Main {
    public static void main(String[] args) {
        int n = 12345000;
        System.out.printf("n=%d, hex=%08x", n, n); // 注意,两个%占位符必须传入两个数
        //	n=12345000, hex=00bc5ea8
    }
}

1.3、输入

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
//      创建Scanner对象
        Scanner scanner = new Scanner(System.in);
//        打印提示
        System.out.println("输入你的id");
//        读取一行输入并获取字符串
        String name = scanner.nextLine();
//        打印提示
        System.out.println("输入你的年龄");
//        读取一行输入,并获取整数
        int age = scanner.nextInt();
        System.out.printf("Hi,%s,you are %d\n",name,age);
        
    }
}

首先,我们通过import语句导入java.util.Scanner,impor是导入某个类的语句,必须放到Java源代码的开头。

然后,创建Scanner对象并传入System.inSystem.out代表标准输出流,而System.in代表标准输入流。直接使用System.in读取用户输入虽然是可以的,但是需要更复杂的代码,二通过Scanner就可以简化后续的代码。

有了Scanner对象后,要读取用户输入的字符串,使用scanner.nextLine(),要读取用户输入的整数,使用scanner.nextInt()Scanner会自动转换数据类型,因此不必手动转换。

Java提供Scanner对象来方便输入,读取对应的类型可以使用:scanner.nextLine() / nextInt() / nextDouble() / nextFloat()/…

二、if判断

用法与JavaScript中基本一致,下列几点需注意

2.1、判断浮点数相等

由于浮点数有精度误差,因此浮点数使用==判断是否相等不靠谱。

正确的方法是利用差值小于某个临界值来判断:

public class Main {
    public static void main(String[] args) {
        double x = 1 - 9.0 / 10;
        if (Math.abs(x - 0.1) < 0.00001) {
            System.out.println("x is 0.1");
        } else {
            System.out.println("x is NOT 0.1");
        }
    }
}

2.2、判断引用类型相等

判断引用类型是否相等可以使用==运算符,但是,判断引用类型的变量是否相等,==表示"引用是否相等",或者说,”是否指向同一个对象“。例如,下面的两个String类型,他们的内容是相同的,但是,分别指向不同的对象,用==判断,结果为false.

public class Main {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "HELLO".toLowerCase();
        System.out.println(s1);
        System.out.println(s2);
        if (s1 == s2) {
            System.out.println("s1 == s2");
        } else {
            System.out.println("s1 != s2");
        }
    }
}

注意:要判断引用类型的变量内容是否相等,必须使用equals()方法

public class Main {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "HELLO".toLowerCase();
        System.out.println(s1);
        System.out.println(s2);
        if (s1.equals(s2)) {
            System.out.println("s1 equals s2");
        } else {
            System.out.println("s1 not equals s2");
        }
    }
}

注意:执行语句s1.equals(s2)时,如果变量s1null,会报NullPointerException

要避免NullPointerException,可使用&&进行短路判断

public class Main {
    public static void main(String[] args) {
        String s1 = null;
        //短路判断
        if (s1 != null && s1.equals("hello")) {
            System.out.println("hello");
        }
        //非短路判断
        if (s1.equals("hello")) {
            System.out.println("hello");
        }
    }
}

三、switch多重判断

switch语句根据siwtch(表达式)计算的结果,跳转到匹配的case结果,然后继续执行后续语句,直到遇到break结束执行。

public class Main {
    public static void main(String[] args) {
        int option = 1;
        switch (option) {
            case 1:
                System.out.println("Selected 1");
                break;
            case 2:
                System.out.println("Selected 2");
                break;
            case 3:
                System.out.println("Selected 3");
                break;
            default:
                System.out.println("Not selected");
                break;
                
        }
    }
}

option的值在1,2,3中没有匹配到时,将会执行default的代码,若没有default,将什么都不执行。

在有多个==判断时,switch语句比if语句更加清晰

注意:case语句没有{},且case语句具有穿透性,漏写break将会持续向下执行,直到遇见break

3.1、合并书写

当有几个case语句执行的是同一组语句块时,可合并写

public class Main {
    public static void main(String[] args) {
        int option = 2;
        switch (option) {
        case 1:
        case 2:
        case 3:
            System.out.println("Selected 1, 2, 3");
            break;
        default:
            System.out.println("Not selected");
            break;
        }
    }
}

switch语句还可以使用枚举类型,枚举类型后面会进行学习

3.2、switch表达式

使用switch时,如果遗漏了break,就会造成严重的逻辑错误,而且不易在源代码中发现错误。从Java 12开始,switch语句升级为更简洁的表达式语法,使用类似模式匹配(Pattern Matching)的方法,保证只有一种路径会被执行,并且不需要break语句:

public class Main {
    public static void main(String[] args) {
        String fruit = "apple";
        switch (fruit) {
        case "apple" -> System.out.println("Selected apple");
        case "pear" -> System.out.println("Selected pear");
        case "mango" -> {
            System.out.println("Selected mango");
            System.out.println("Good choice!");
        }
        default -> System.out.println("No fruit selected");
        }
    }
}

注意新语法使用->,如果有多条语句,需要用{}括起来。不要写break语句,因为新语法只会执行匹配的语句,没有穿透效应。

很多时候,我们还可能用switch语句给某个变量赋值。例如:

int opt;
switch (fruit) {
case "apple":
    opt = 1;
    break;
case "pear":
case "mango":
    opt = 2;
    break;
default:
    opt = 0;
    break;
}

使用新的switch语法,不但不需要break,还可以直接返回值。把上面的代码改写如下:

public class Main {
    public static void main(String[] args) {
        String fruit = "apple";
        int opt = switch (fruit) {
            case "apple" -> 1;
            case "pear", "mango" -> 2;
            default -> 0;
        }; // 注意赋值语句要以;结束
        System.out.println("opt = " + opt);
    }
}

3.3、yield

yield返回一个值作为switch语句的返回值:

public class Main {
    public static void main(String[] args) {
        String fruit = "orange";
        int opt = switch (fruit) {
            case "apple" -> 1;
            case "pear", "mango" -> 2;
            default -> {
                int code = fruit.hashCode();
                yield code; // switch语句返回值
            }
        };
        System.out.println("opt = " + opt);
    }
}

四、while循环

while (条件表达式) {
    循环语句
}

while循环在每次循环开始之前,首先判断条件是否成立。如果为true,就把循环体内的语句执行一遍,如果为false,那就直接跳到while循环的末尾,继续往下执行。

public class Main {
    public static void main(String[] args) {
        int sum = 0;
        int n = 1;
        while (n <= 100) {		//循环条件是n <= 100
            sum += n;
            n++;
        }
        System.out.println(sum);// 5050
    }
} 

注意:while循环是先判断循环条件,再循环,因此,有可能一次循环都不做

五、do while循环

while循环时先判断,再执行循环,而do while是先执行循环,再进行判断

do {
    执行循环语句
} while(条件表达式)

因此,do while循环至少循环一次

把对1到100的求和用do while循环改写一下:

public class Main {
    public static void main(String[] args) {
        int n = 1;
        int sum = 0;
        
        do {
        	sum += n;
            n++;
        } while(n <= 100)
            System.out.println(sum);
    }
}

六、for循环

for (初始条件; 循环检测条件; 循环后更新计数器) {
    // 执行语句
}

示例

public class Main {
    public static void main(String[] args) {
        int sum = 0;
        for (int i=1; i<=100; i++) {
            sum = sum + i;
        }
        System.out.println(sum);
    }
}

6.1、for each循环

public class Main{
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        for(int item: arr ){
            System.out.println(item);
        }
    }
}

for循环相比,for each循环的变量(item)不再是计数器,而是直接对应到数组的每个元素。for each循环的写法也更简洁。但是,for each循环无法指定遍历顺序,也无法获取数组的索引。

除了数组外,for each循环能够遍历所有“可迭代”的数据类型,包括后面会介绍的ListMap等。

七、break和continue

无论是while循环还是for循环,有两个特别的语句可以使用,就是break语句和continue

7.1、break

在循环过程中,可以使用break语句跳出当前循环

public class Main{
    public static void main(String[] args) {
        int sum = 0;
        for (int i=1; ; i++) {
            sum = sum + i;
            if (i == 100) {
                break;
            }
        }
        System.out.println(sum);
    }
}

使用for循环计算从1到100时,我们并没有在for()周设置循环退出的检测条件。但是在内部,通过if判断,如果i==100,就通过break跳出当前循环

break语句通常都是配合if使用。要注意:break语句总是跳出自己所在的那一层循环

public class Main {
    public static void main(String[] args) {
        for (int i=1; i<=10; i++) {
            System.out.println("i = " + i);
            for (int j=1; j<=10; j++) {
                System.out.println("j = " + j);
                if (j >= i) {
                    break;
                }
            }
            // break跳到这里
            System.out.println("breaked");
        }
        //不会跳到这里
    }
}

7.2、continue

break会跳出当前循环,也就是整个循环都不会执行了.而continue是提前结束本次循环,直接继续执行下一次循环.

public class Main {
    public static void main(String[] args) {
        int sum = 0;
        for (int i=1; i<=10; i++) {
            System.out.println("begin i = " + i);
            if (i % 2 == 0) {
              continue; // continue语句会结束本次循环
            }
            sum = sum + i;
            System.out.println("end i = " + i);
        }
        System.out.println(sum); // 25
    }
}

在多层嵌套的循环中,continue语句同样是结束本次自己所在的循环。

八、数组操作

8.1、遍历数组

可使用for循环,或者for each循环进行遍历

public class Main {
    public static void main(String[] args) {
        int[] ns = { 1, 4, 9, 16, 25 };
        // for 循环
        for (int i=0; i<ns.length; i++) {
            int n = ns[i];
            System.out.println(n);
        }
        
        // for each 循环 
        for (int n : ns) {
            System.out.println(n);
        }
    }
}

直接打印数组,得到的是数组在 JVM 中的引用地址

int[] ns = { 1, 1, 2, 3, 5, 8 };
System.out.println(ns); // 类似 [I@7852e922

想获得数组的值,应使用for each循环,或者Java提供的Arrays.toString()

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] ns = { 1, 1, 2, 3, 5, 8 };
        
        // for each循环
        for (int n : ns) {
            System.out.print(n + ", ");
        }
        
        // Arrays.toString()
        System.out.println(Arrays.toString(ns));
    }
}

8.2、数组排序

常用的排序算法有,冒泡排序插入排序快速排序等。

//冒泡排序
int[] arr = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };

System.out.println("排序前: " + Arrays.toString(arr));
for (int i = 0; i < arr.length ; i++) {
    for (int j = 0; j < arr.length - 1; j++) {
        if (arr[j] > arr[j+1]){
            int midNum = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = midNum;
        }
    }

    System.out.println("排序中 === " + Arrays.toString(arr));
}
System.out.println("排序后: " + Arrays.toString(arr));

冒泡排序的特点: 每一轮循环后, 将最大的一位交换到末尾

Java内置数组排序 JDK Arrays.sort()

int[] arr = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));

必须注意,对数组排序实际上修改了数组本身。例如,排序前的数组是:

int[] ns = { 9, 3, 6, 5 };

在内存中,这个整型数组表示如下:

      ┌───┬───┬───┬───┐
ns───>│ 9 │ 3 │ 6 │ 5 │
      └───┴───┴───┴───┘

当我们调用Arrays.sort(ns);后,这个整型数组在内存中变为:

      ┌───┬───┬───┬───┐
ns───>│ 3 │ 5 │ 6 │ 9 │
      └───┴───┴───┴───┘

即变量ns指向的数组内容已经被改变了。

8.3、多维数组

二维数组:

public class Main{
    public static void main(String[] args) {
        int[][] arr = {
            {1,2,3},
            {4,5,6},
            {7,8,9}
        };
        System.out.println(arr.length);
        System.out.println(Arrays.deepToString(arr));
    }
}

使用Java标准库的Arrays.deepToString()可以打印多维数组

三维数组:

int[][][] ns = {
    {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    },
    {
        {10, 11},
        {12, 13}
    },
    {
        {14, 15, 16},
        {17, 18}
    }
};

九、命令行参数

Java程序的入口是main方法,而main方法可以接受一个命令参数,它是一个String[]数组。

这个命令行参数由 JVM接受用户输入并传给main方法

public class My{
    public static void main(String[] args) {
        for(String arg: args) {
            System.out.println(arg);
        }
    }
}

我们可以利用接收到的命令行参数,根据不同的参数执行不同的代码。例如,实现一个-version参数,打印程序版本号:

public class Main {
    public static void main(String[] args) {
        for (String arg : args) {
            if ("-version".equals(arg)) {
                System.out.println("v 1.0");
                break;
            }
        }
    }
}

上面这个程序必须在命令行执行,我们先编译它:

$ javac Main.java

然后,执行的时候,给它传递一个-version参数:

$ java Main -version
v 1.0

这样,程序就可以根据传入的命令行参数,作出不同的响应。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值