1 顺序结构

顺序结构是所有编程语言做常用的程序结构。程序结构就是程序按照从上到下逐行地执行,中间没有任何判断和跳转。

2 分支结构

2.1 if条件语句

if语句使用布尔表达式或布尔值作为分支条件进行分支控制。if语句的三种形式如下:

第一种形式:

if (逻辑表达式)
        {
            语句;
        }

第二种形式:

 if (逻辑表达式)
        {
            语句;
        }
        else
        {
            语句;
        }

第三种形式:

if (逻辑表达式)
        {
            语句;
        }
        else if(逻辑表达式)
        {
            语句;
        }
        .... //可以有零个或多个else if语句
        else //最后的else语句也可以省略
        {
            语句;
        }

以上的三种形式中,放在if之后括号的只能是一个逻辑表达式,即这个表达式的返回值只能是true或者false。在上面的语句中,if 和else 后花括号括起来的多行代码被称为一个代码块,一个代码块通常被作为一个整体执行,除非遇到return、break、continue等关键字。

public class HelloWorld {
    public static  void main(String [] args){
        var a=5;
        if(a>4)
        {
            //如果a>4,则执行下面的执行体,只有一行代码作为代码块
            System.out.println("a大于4");
        }
        else
        {
            //否则,执行下面的执行体,只有一行代码作为代码块
            System.out.println("a不大于4");
        }
    }
}

上面的if else后面都只有一行语句,所以花括号可以省略,因为单行语句本身就是一个整体,但建议不要省略,因为花括号会有更好的可读性,而且保留花括号会减少发生错误的可能。

使用var 定义变量的语法: var 变量名 = 初始值;

var不是关键字,它相当于是一种动态类型;

var动态类型是编译器根据变量所赋的值来推断类型;

public class HelloWorld {
    public static  void main(String [] args){
        var a=5;
        if(a>4)
            //如果a>4,则执行下面的执行体,将只执行a--;只有一行代码作为执行体
            c--;
            System.out.println("a大于4");
        else
            //此处的else没有if语句,编译错误
            //否则,执行下面的执行体,只有一行代码作为代码块
            System.out.println("a不大于4");
    }
}

上面的就是因为省略花括号导致的错误;除了语法错误,还经常发生一个逻辑错误,这个逻辑错误不属于语法问题,但引起错误的可能性更大。看下面的一个程序:

public class HelloWorld {
    public static  void main(String [] args){
        var age=45;
        if(age >20)
        {
            System.out.println("青年人");
        }
        else if (age > 40)
        {
            System.out.println("中年人");
        }
        else if(age > 60)
        {
            System.out.println("老年人");
        }

    }
}

看是没问题,运行结果应该是中年人,但运行后的结果是 青年人 ,而实际希望45的判断结果是中年人 ,这显然有问题。

对于任何一个if else语句,表面看来else后没有任何条件,或else if后只有一个条件,但事实上还有一个容易被忽略的隐含条件:else本身就表示"否则",其本身就是一个条件。else的隐含条件是对前面的条件取反。因此可以将上面代码改写成下面的形式,

public class HelloWorld {
    public static  void main(String [] args){
        var age=45;
        if(age >20)
        {
            System.out.println("青年人");
        }
        //在原本的if条件中增加else的隐含条件
        if (age > 40 && !(age > 20))
        {
            System.out.println("中年人");
        }
        //在原本的if条件中增加else的隐含条件
        if(age > 60 && !(age > 20) && !(age >40 && !(age > 20)))
        {
            System.out.println("老年人");
        }
    }
}

条件 (age > 40 && !(age > 20)) 还可以写作 age>40 && age<=20 ,这样永远也不会发生,(age > 60 && !(age > 20) && !(age >40 && !(age > 20))) 就更不会发生了。

为达到目的可以将程序写成下面格式:

public class HelloWorld {
    public static  void main(String [] args){
        var age=45;
        if(age > 60 )
        {
            System.out.println("老年人");
        }
        if (age > 40 )
        {
            System.out.println("中年人");
        }
        if(age >20)
        {
            System.out.println("青年人");
        }

    }
}

改写成下面代码:

public class HelloWorld {
    public static  void main(String [] args){
        var age=45;
        if(age > 60 )
        {
            System.out.println("老年人");
        }
        //在原本的if条件中增加else的隐含条件
        if (age > 40 && !(age > 60))
        {
            System.out.println("中年人");
        }
        //在原本的if条件中增加else的隐含条件
        if(age >20&& !(age > 60 ) &&!(age > 40 && !(age > 60)))
        {
            System.out.println("青年人");
        }

    }
}

就正常了!

2.2 switch分支语句

switch语句由一个控制表达式和多个case标签组成,和if语句不同的是,switch语句后面的控制表达式的数据类型只能是byte、short、int、char四种整形,枚举类型和java.lang.String (java字符串类,包含了字符串的值和实现字符串相关操作的一些方法。) 类型(从java7才允许),不能是boolean类型

switch (表达式)
        {
            case 条件1:
            {
                语句...
                break;
            }
            case 条件2:
            {
                语句...
                break;
            }
            .....
            default:
            {
                语句....
            }
        }

这种分支语句的执行是先对表达式求值,然后依次匹配条件1条件2...等值,如果表达式的值与条件都不相等就执行default标签后的代码块。

Java11的编译器做了一些改进如果开发者忘记case后加break语句,编译器会生成警告:“[fallthrough]可能无法实现case”。

实例:

public class HelloWorld {
    public static  void main(String [] args){
        var season="夏天";
        switch (season)
        {
            case "春天":
            {
                System.out.println("春暖花开");
                break;
            }
            case "夏天":
            {
                System.out.println("夏日炎炎");
                break;
            }
            case "秋天":
            {
                System.out.println("秋高气爽");
                break;
            }
            case "冬天":
            {
                System.out.println("冬雪皑皑");
                break;
            }
            default:
            {
                System.out.println("季节输入错误!");
            }
        }
    }
}

注意:

使用switch语句时,有两个需要注意的地方:一是switch语句后面的控制表达式的数据类型只能是byte、short、int、char四种整形,枚举类型和String类型,不能是boolean类型;二是如果忽略case后代码块的break;,将引入一个陷阱。

3 循环结构

循环语句可以在满足循环条件的情况下,反复执行某段代码,这段代码被称为循环体,当反复执行这个循环体时,需要在合适的时候把循环条件改为假,从而停止循环。循环语句一般包含四部分。

  1. 初始化语句:一条或多条,用于完成初始化工作,在循环开始前完成。
  2. 循环条件:属于boolean表达式,用于判断是否进行循环。
  3. 循环体:是循环的主体,如果循环条件允许,这个代码块将被重复运行,如果只有一句,花括号可以忽略。
  4. 迭代语句:这个部分在一次循环结束后执行,对循环条件求值之前执行,通常用于控制循环条件中的变量,使循环在合适时机退出。

3.1.1 while循环语句

格式:

        [初始化语句]
        while (循环条件)
        {
            语句;
            [迭代语句]
        }

实例:

        var count=0;
        //while后紧跟一个分号,说明循环体是一个空语句
        while(count<10);
        //下面的代码块与while已没有任何关系
        {
            System.out.println("------------"+count);
            count++;
        }

注意:

如果忽略了循环体的花括号,那么while循环条件仅控制到紧跟该循环条件的第一个分号处。

如果在while()直接写分号,说明当循环条件允许的情况下,一直执行空语句,不会执行下面的语句。

3.1.2 do while循环语句

do while 与while的区别在于:while是先判断循环条件,如果为真就执行循环体,如果为假就不执行。do while 是先执行循环体,然后判断条件,不管条件是否允许都最少执行一次。

do while语法格式如下:

        [初始化语句]
        do
        {
            语句;
            [迭代语句]
        }while (循环条件);

与while不同之处在于do while循环的循环条件后面必须有一个分号,这个分号是循环结束的标志。

public class HelloWorld {
    public static  void main(String [] args){
        var count=20;
        do {
            System.out.println(++count);
        }while(count<10);
        System.out.println("循环结束!");
    }
}

这个程序输出结果是:

21
循环结束!

说明即使条件是假也会执行一次。

3.2 for循环

for循环是更简洁的循环语句,大部分条件下,for循环可以替代while和do while循环。for循环语句基本格式如下:

        for([初始化]:[循环条件]:[迭代语句])
        {
            循环语句;
        }

每次循环都先执行初始化语句,而且初始化语句只在循环开始时执行一次,每次执行循环体之前先计算循环条件的值,如果循环条件返回true ,就执行循环体,循环体执行完毕后执行迭代语句。因此for循环中,循环条件总比循环体要多执行一次。

由于for循环的迭代语句与循环体分开,因此即使在执行循环体是遇到continue语句结束本次循环,迭代语句也会执行。

for循环实例:

public class HelloWorld {
    public static  void main(String [] args){
        for(var count=0;count<10;count++)
        {
            System.out.println(count);
        }
        System.out.println("循环结束!");
    }
}

上面的初始化语句和循环判断条件只是一个boolean表达式,实际上for循环支持同时指定多个初始化语句,循环条件也可以是一个包含逻辑运算符(&& || 等)的表达式。

for循环圆括号里只有两个分号是必需的,初始化、循环条件、迭代语句都是可以省略的。如果省略循环条件,这这个循环默认为true,将产生一个死循环。例如下面的程序:

public class HelloWorld {
    public static  void main(String [] args){
        for(;;)
        {
            //省略循环三个部分将产生一个死循环
            System.out.println("===========");
        }
        System.out.println("循环结束!");
    }
}

最后一个循环结束将无法访问。

public class HelloWorld {
    public static  void main(String [] args){
        var count = 0;
        for(;count<10;)
        {
            System.out.println("===========");
            count++; //把迭代放在循环体之后定义
        }
        System.out.println("循环结束!");
    }
}

如果把迭代语句写在循环体后会受到continue语句影响。迭代语句将得不到执行。

将初始化语句放在for循环之前可以扩大初始化语句的作用域,在for循环里定义的变量的作用域只有这个循环。

提示:

选择循环变量时,习惯使用i ,j ,k来作为循环变量。

4 控制循环结构

4.1 使用break结束循环

break用于结束一个循环,跳出循环体。不管哪种循环,在循环体中遇到break,系统将完全结束该循环,开始执行循环之后的代码。

break不仅可以结束内层的循环,如果break后跟一个标签,可以退出标签所代表的循环。

java中的标签就是一个紧跟着英文冒号(:)的标识符。java中的标签只有放在循环语句之前才有作用。

public class BreakDemo {
    public static void main(String[] args) {
        outer:  //外层循环,outer作为标识符
        for (var i = 0; i < 5; i++) {
            //内层循环
            for (var j = 0; j < 3; j++) {
                System.out.println("i的值是:" + i + " j的值是:" + j);
                if (j == 1) {
                    //跳出outer标签所代表的循环
                    break outer;
                }

            }
        }
    }
}

运行结果是:

i的值是:0 j的值是:0
i的值是:0 j的值是:1

从外层循环进入内层循环后,当j=1时遇到break outer;语句,将会结束outer指定的循环,不是只结束内层循环,而是结束外层循环。

4.2 使用continue忽略本次循环剩下的语句

continue的功能和break类似,区别是break是退出当前循环或者外层循环,continue并不会退出循环,仅仅是当循环体执行到continue时跳过下面语句,直接进入下一次循环,如果continue带标签的话就跳过标签所代表的循环。

实例:

public class BreakDemo {
    public static void main(String[] args) {
        outer:  //外层循环,outer作为标识符
        for (var i = 0; i < 5; i++) {
            //内层循环
            for (var j = 0; i < 3; j++) {
                System.out.println("i的值是:" + i + " j的值是:" + j);
                if (j == 1) {
                    //忽略outer标签所指定的循环中本次所剩下的语句
                    continue outer;
                }

            }
        }
    }
}

运行结果:

i的值是:0 j的值是:0
i的值是:0 j的值是:1
i的值是:1 j的值是:0
i的值是:1 j的值是:1
i的值是:2 j的值是:0
i的值是:2 j的值是:1
i的值是:3 j的值是:0
i的值是:3 j的值是:1
i的值是:4 j的值是:0
i的值是:4 j的值是:1

由于当满足j==1时就会执行continue outer; 语句,所以j的值无法大于1,就又重新进入最外层循环。

4.3 使用return结束方法

return不是专门用来结束循环的,return结束的是一个方法,当一个方法执行到return时,这个方法将被结束。

public class BreakDemo {
    public static void main(String[] args) {
        for (var i = 0; i < 5; i++) {
            //内层循环
            for (var j = 0; j < 3; j++) {
                System.out.println("i的值是:" + i + " j的值是:" + j);
                if (j == 1) {
                    return;
                }
                System.out.println("return后的语句!");
            }
        }
    }
}

上面的程序只能运行到j等于1,虽然return并不专门用来控制循环结构但return确实可以结束一个循环。但是return结束的是一个方法,不管有几层循环。

5 数组类型

5.1 数组的理解

java的数组元素的类型必须具有相同的数据类型。即一个数组只能存一种数据类型的数据。

一旦数组初始化完成,数组在内存中的空间就被固定下来,因此数组的长度无法被修改。即使清空数组数据,但它占用的空间依旧存在,还属于该数组,数组的长度也不变。

java的数组既可以存储基本类型的数组,也可以存储引用类型的数据,只要所有数据元素具有相同数据类型即可。

基本数据类型

特点:

一、从概念方面来说

基本数据类型:变量名指向具体的数值

引用数据类型:变量名指向存数据对象的内存地址

二、从内存构建方面来说

基本数据类型:变量在声明之后java就会立刻分配给他内存空间

引用数据类型:它以特殊的方式(类似C指针)指向对象实体(具体的值),这类变量声明时不会分配内存,只是存储了一个内存地址。

5.2 定义数组

java支持两种定义数组方式:

type[] arrayName;
type arrayName[];

推荐使用第一种,因为可以更清楚看出新定义了一个新的变量,变量名是arrayName,变量类型是type[] 。type[]与type是两种不同的数据类型。

这种方式既容易理解,有符合定义变量的规范。越来越多的语言都使用type[] arrayName这种数组定义方式。

注意:

定义数组时不能指定数组的长度。

5.3 数组的初始化

java中的数组必须先初始化,然后才可以使用。

初始化就是为数组的数组元素分配内存空间,并为数组元素赋初值。

数组的初始化方式:

  1. 静态初始化:初始化时由程序员指定每个数组元素的初始值,由系统决定数组长度。
  2. 动态初始化:初始化时由程序员指定长度,系统分配初始值(引用类型初始值为null)。

静态初始化语法格式:

type[] arrayName; //定义arrayName变量。
arrayName =new type[] {元素1,元素2,.....};

显式指定的数组元素类型应该与new关键字后面的type类型相同。

显式初始化即为手工给予初值,否则为隐式初始化,将内容设置为默认值。

还可以用以下简化格式:

type[] arrayName = {元素1,元素2,....};

直接用一个花括号来定义一个数组,使用花括号把数组元素括起来形成一个数组,在定义数组的同时执行初始化才支持使用简化的静态初始化。

动态初始化格式:
.ms/image/RDbZioB7nzgASs3" target="_blank">

trpe[] arrayName ;// 定义数组变量
arrayName =new type[length];

e.g.

int[] eg=new int[5];
  1. 整数类型:byte,short,int,long默认初始化值都是0
  2. ​ 浮点类型:float,double默认初始化值都是0.0
  3. ​ 布尔类型:boolean默认初始化值false
  4. ​ 字符类型:char默认初始化值'u0000'
  5. 数组类型是引用类型:默认初始化是null。

注意:

不要同时使用静态初始化和动态初始化,也就是说不要在进行数组初始化时,既指定数组长度,又给每个元素分配初始值。

在定义数组类型变量时同样可以使用var定义变量,只要在定义该变量时为其指定初始值即可。

e.g.

var names = new String[] {"liming"};
var book=new String[5];

使用静态初始化的简化语法执行初始化时不能使用var定义数组变量。

why?

5.4 foreach 循环(增强的for循环)

foreach循环的语法格式如下:

for(type variableName : array | collection)
{
//variableName自动迭代循环访问某个元素
}

上面的type是数组元素或直接定义var格式,variableName是一个形参名,foreach循环将自动将数组元素依次赋给该变量。

e.g.

public class ArrayDemo {
    public static void main(String [] args){
        int[] a={5,6,7,8};//简化的静态初始化
        for(var i: a)
        System.out.println(i);
        var book=new String[5];//动态初始化
        book[1]="operatingSystem";
        for(var i: book)
            System.out.println(i);
        var n=new String[] {"haha","heiehi"};
        for(var i=0;i<n.length;i++)
            System.out.println(n[i]);

    }
}

运行结果:

5
6
7
8
null
operatingSystem
null
haha
heiehi

使用foreach循环遍历数组元素时无需获得数组长度,也无需根据索引来访问数组元素。

foreach与普通for循环的不同在于,它不需要循环条件和循环迭代语句,这些都由系统来完成,当每个元素都被迭代依次后,foreach循环自动结束。

注意:

使用foreach循环迭代时不能改变数组元素的值,所以不要对foreach的循环变量进行赋值。

本文导出文档下载地址:Download

资料:

jdk-11中文api修订版.CHM

jdk11官方api文档(html版).7z

Last modification:November 21st, 2020 at 10:18 pm
如果觉得我的文章对你有用,请随意赞赏