java_day03_流程控制

ch03
目标:表达式和流程控制
----------------------------------------------
1.实例变量和局部变量
    程序的基本功能是处理数据,程序中需要使用变量来接收并表示数据。
    程序中的变量必须先定义之后才能使用。
    定义变量包括定义变量的"类型"以及变量的"名字"。
        例如: int a; Student s;
    程序中的变量分为实例变量和局部变量。

    1)实例变量(又称属性、全局变量、成员变量)
        位置: 
            直接定义在中类,属于类中的一种成员(成员变量/成员方法)。
            例如:
            public class Student{
                public String name;
            }

        作用范围:
            是指变量定义之后,都在哪些地方可以被访问到。
            由于实例变量是直接定义在类中的,所以在定义的时候可以使用修饰符进行修饰。
            例如:这四种修饰符的作用之后会介绍到
            public class Student{
                public String name1;
                protected String name2;
                String name3;
                private String name4;
            }
            以上是使用了四种访问权限控制修饰符来修饰了这四个变量。
            但是不管是哪种修饰符情况,实例变量再当前类中的每一个方法都是可以被访问到的(static修饰的静态方法除外)。

            public class Student{
                public String name1;
                protected String name2;
                String name3;
                private String name4;
                
                //类中的方法里面可以直接访问实例变量
                public void run(){
                    System.out.println(name1);
                    System.out.println(name2);
                    System.out.println(name3);
                    System.out.println(name4);
                }
            }
            
        默认值:
            类的中实例变量声明后,如果我们没有显式赋值的话,每种实例变量其实都是有自己的默认值的。
            实例变量的赋值分为隐式赋值和显式赋值
                隐式赋值就是JVM给它赋的值(就是说的默认值)
                显式赋值就是我们主动给它赋的值
            例如:
            public class Student{
                public int a;
                public float f;
                public char c;
                public boolean b;
                public String str;

                public void println(){
                    System.out.println(a);
                    System.out.println(f);
                    System.out.println(c);
                    System.out.println(b);
                    System.out.println(str);
                }
            }

            基本类型的实例变量:
                整型    :默认值为 0
                浮点型    :默认值为 0.0
                布尔型    :默认值为 false
                字符型    :默认值为 0 或者 '\u0000'
            引用类型的实例变量:
                默认值都是 null
        
        生命周期:
            实例变量是属于对象的,一个对象被创建出来的时候,这个对象中的实例变量就有了,直到这个对象被GC当做垃圾回收之后,这个实例变量也就没有了。


    1)局部变量
        位置:
            定义在方法的代码块中或者方法的参数列表中
            例如:a b c d四个都是局部变量
                public void test(int a){
                    int b;
                    {
                        int c;
                    }

                    if(true){
                        int d;
                    }
                }

        作用范围:
            1)如果是定义在方法的参数列表中,那么在当前方法的任何位置都可以访问该局部变量
                例如:
                public void test(int a){
                    System.out.println(a);
                    {
                        System.out.println(a);
                    }

                    if(true){
                        System.out.println(a);
                    }
                }

            2)如果是定义在方法中,那么就要看这个局部变量是"直接"位于哪一对大口号内
                例如:
                public void test(){
                    int a;
                    {
                        int b;
                    }

                    if(true){
                        int c;
                    }
                }
                观察局部变量a/b/c三个分别是"直接"位于哪一对大括号内,那么这个局部变量的作用范围就在那一对大括号内.
                如果访问的地方出了这个范围,那么是访问不到这个局部变量的。
            
        默认值:
            局部变量是"没有"默认值的,我们只能显式的赋值之后才能使用该变量,否则会编译报错.
            例如:
                //编译通过
                //只定义了变量但是没有使用
                public void test(){
                    int a;
                }

                //编译报错
                //因为在使用局部变量之前没有赋值
                public void test(){
                    int a;
                    System.out.println("a = "+a);
                }

                //编译通过
                //只有在使用之前赋值就可以了
                //int a = 1;
                //当然声明的同时就赋值也是可以的
                public void test(){
                    int a;
                    
                    a = 1;
                    System.out.println("a = "+a);
                }


        声明周期:
            当方法被调用,代码执行到局部变量的声明这一刻开始,这个局部变量就出现了,直到局部变量"直接"位于的大括号内中的代码执行结束的时候,该变量在内存中也就释放消失了。
            例如:
                //test方法执行完,变量a就没有了
                public void test(){
                    int a;
                }

                //if代码块执行完,变量b就没有了
                public void test(){
                    if(true){
                        int b;
                    }
                    
                    //这里是访问不到变量b的,编译报错
                    System.out.println("b = "+b);
                }

2.java中的操作符(operator)
    1)赋值操作符:
        =   例如:   int x=0,i=1,j=1;
        *=  例如:   a*=b 等价于 a=a*b
        /=  例如:   a/=b 等价于 a=a/b;
        %=  例如:   a%=b 等价于 a=a%b;
        +=    例如:   a+=b 等价于 a=a+b;
        -=  例如:   a-=b 等价于 a=a-b;
        其他的都是类似情况
        
        a+=1; a++
        特殊情况:i++ 和 ++i
        i++表示先使用i的值,然后再让i自增1。
        ++i表示先让i的值自增1,然后再使用i的值。
        例如:
            int a = 1;
            System.out.println(a++);//1
            System.out.println(a);//2
        ---------------------------------
            int b = 1;
            System.out.println(++b);//2
            System.out.println(b);//2

        
        类似的i-- 和 --i也是一样的区别



    2)比较操作符
        >   :   大于
        >=  :   大于等于
        <   :   小于
        <=  :   小于等于

        注意:以上操作符只适用于整数类型和浮点数类型;

        int a=1,b=1;
        double d=1.0;
        System.out.println(a>b);//false
        System.out.println(a<b);//false
        System.out.println(a>=d);//true
        System.out.println(a<=b);//true

        instanceof: 判断一个引用类型变量所指向的对象是不是属于某个类型。
            Student s = new Student();
            System.out.println(s instanceof Object);//true
            System.out.println(s instanceof Student);//true
            //编译报错,因为Student类型和String没有任何子父类关系
            System.out.println(s instanceof String);

            注意:最终判断的是s所指向对象的类型是不是属于某类型,而不是判断变量s的类型是不是属于某个类型.
            例如:
                Object o = new Student();
                变量o的类型是Object,但是o指向的对象类是Studnet.可以这样写的原因是因为Object是Studnet的父类.这是java的高级特性"多态"的一种表现方式。


    3)相等操作符                     
        ==  :   判断俩个数据 是否 等于
        !=  :   判断俩个数据 是否 不等于

        既可以应用在基本类型的比较,也可以应用在引用类型的比较

        a.基本类型:
            int a=1,b=1; 
            float c=1.0f;
            double d=1.0;
            
            //比较的是俩个基本类型数据的值是否相等
            System.out.println(a==b);        //输出true;
            System.out.println(a==c);        //输出true;
            System.out.println(a==d);        //输出true;
            System.out.println(c==d);        //输出true;

        b.引用类型:
            这两个引用变量必须都引用同一个对象,结果才为true.
            Student s1 = new Student("zs",25,100);
            Student s2 = new Student("zs",25,100);
            //s1中存储的对象内存地址赋给变量s3
            Student s3 = s1;
            
            //比较俩个引用所指向对象的堆区内存地址是否一样
            //俩个对象的内存地址一样相比较才会是true
            System.out.println(s1 == s2);    //输出false;
            System.out.println(s1 == s3);    //输出true;

    4)相加操作符 
        +   :   数据类型值相加或字符串连接

            a.数据类型值相加
                int    a=1+2;   //a值为3;
                double b=1+2;   //b值为3.0;   
                double b=1+2.0; //c值为3.0;

            b.字符串连接
                System.out.println(1+2+"a");  //输出3a
                System.out.println(1+2.0+"a");//输出3.0a
                System.out.println(1+2.0+"a"+true);//输出3.0atrue
                System.out.println("a"+1+2); //输出a12
                System.out.println(1+"a"+2); //输出1a2

        /   :   整除, 如操作数均为整数,运算结果为商的整数部分
            int a1=12/5;        //2
            int a2=13/5;        //2
            int a3=-12/5;        //-2
            int a4=-13/5;        //-2
            int a5=1/5;            //0
            double a6=12/5;        //2.0
            double a7=12/5.0;    //2.4   

        %   :   取模操作符, 如操作数均为整数,运算结果为商的整数部分
            int a1=1%5;            //1
            int a2=13%5;        //3
            double a3=1%5;        //1.0
            double a4=12%5.1;    //1.8000000000000007


    5)移位操作符
        >>  :  算术右移位运算,也称做带符号右移位运算。
        
        注意:正数取反加1得到其对应的负数,负数取反加1得到其对应的正数

        int a1 = 12 >> 1;  //6;
        0000 1100    12
        -----------
         0000 110    >>1
        -----------
        0000 0110    补位 因为是正数所以补0  结果为6


        int a2 = 128 >> 2;//32;
        int a3 = 129 >> 2;//32;                 
        int a5 = -12 >> 1;//-6; 
        0000 1100    12
        ---------
        1111 0011    取反
        ---------
        1111 0100    +1  这个就是-12的二进制形式
        ----------
         1111 010    >>1

        1111 1010    补位 因为是负数所以补1  这个负数就是最终结果
        ---------

        0000 0101    取反
        ---------
        0000 0110    +1 结果为6 所以上面的最终结果是 -6


        int a6 = -12 >> 2;//-3; 

        0000 1100     12
        ---------
        1111 0011     取反
        ---------
        1111 0100     +1  这个就是-12的二进制形式
        ---------- 
          1111 01     >>2

        1111 1101     补位 因为是负数所以补1  这个负数就是最终结果
        ---------
        0000 0010     取反
        ---------
        0000 0011     +1 结果为3 所以上面的最终结果是 -3



        >>> :  逻辑右移位运算,也称为不带符号右移位运算。

        int a1 = 12 >>> 1;//6;
        int a2 = -12 >>> 2;//1073741821;                   

        注:
        a. 对12逻辑右移一位的过程为:舍弃二进制数的最后一位,在二进制数的开头增加一个0;
        b. 对-12逻辑右移二位的过程为:舍弃二进制数的最后二位,在二进制数的开头增加二个0;

        << :  左移位运算,也称为不带符号左移位运算。

        int a1 = 12  << 1;//24;
        int a2 = -12 << 2;//-48;                   
        int a3 = 128 << 2;//512;
        int a4 = 129 << 2;//516;    

        注:
        a. 对12左移一位的过程为:舍弃二进制数的开头一位,在二进制数的尾部增加一个0;
        b. 对-12左移二位的过程为:舍弃二进制数的开头二位,在二进制数的尾部增加二个0;


    6)位运算操作符  
        & 与运算
            1&1->1, 1&0->0, 0&1->0, 0&0->0;   
        | 或运算
            1|1->1, 1|0->1, 0|1->1, 0|0->0;
        ^ 异或运算
            1^1->0, 0^0->0,1^0->1, 0^1->1; 
            相同为0 不同为1  
            运算特点: a^0=a; a^a=0;
        ~ 取反运算
            ~1->0, ~0->1;

    7)逻辑操作符
        短路操作符,如果能根据操作左边的布尔表达式就能推算出整个表达式的布尔值,将不执行操作符右边的布尔表达式;
        
        短路与
        && 左边的布尔表达式的值为false, 整个表达式值肯定为false, 此时会忽略执行右边的布尔表达式。
            false&&true
            int a = 1;
            int b = 2;
            int c = 3;
            a>b&&c>b

            //没有短路功能
            a>b&c>b


        
        短路或
        || 左边的布尔表达式的值为true, 整个表达式值肯定为true, 此时会忽略执行右边的布尔表达式。  
        
        注意:&和&&的区别是什么? |和||的区别是什么?

    8)三目运算
        形式:
            布尔表达式 ? 表达式1 : 表达式2;

            如果上面布尔表达式的值为true, 就返回表达式1的值, 否则返回表达式2的值。

        例如:
            int score = 61;
            String result = (score>=60?"及格":"不及格"); 

3.类型转换
    1)基本类型之间的转换
        隐式转换(自动转换)
            byte a = 1;
            //a是byte类型(8位),b是int类型的(32)
            //编译通过,类型自动转换(隐式转换)
            int b = a;
            
            特点:小的可以自动转换(隐式转换)为大的,因为无非就是在前面多补几个0而已,不会影响数据值
            
        显式转换
            //编译报错,32位的值给8位的变量
            int a = 100;
            byte b = a;

            //编译通过
            //这时候需要类型强制转换(俗称强转,也就是显式转换)
            int a = 100;
            byte b = (byte)a;

            特点:大的值给小的变量,需要强制转换,但是转换后的结果JVM不会保证还是正确的,因为这是程序员自己的个人行为.
            

    2)引用类型之间的转换
        隐式转换
            //编译通过,类型自动转换(隐式转换)
            Student s = new Student();
            Object o = s;

            特点:子类类型的变量可以自动转换(隐式转换)为父类类型

        显式转换
            //编译通过,运行后也不报错
            //因为引用o本来指向的就是Student对象
            Object o = new Student();
            Student s = (Student)o;

            //编译通过,运行后报错
            //因为o本来指向的时候Teacher对象
            //而Teacher类型对象和Student类型没有任何关系
            Object o = new Teacher();
            Student s = (Student)o;


4.流程控制-if
    程序中if语句的代码块只有满足特定条件的情况下才会被执行.
    1)if语句
        if(true|false) {
            //执行代码    
        }
    
    2)if-else语句
        if(true|false){
            //执行代码1
        }else{
            //执行代码2
        }
        注意:if和else是一组的,二者有且只有一个会执行
    
    3)if-elseif-else
        if(true|false){
            //执行代码1
        }
        else if(true|false){
            //执行代码2
        }
        ....
        else{
            //执行代码3
        }
        注意:以上三个代码块也是一组的,有且只有一个会执行
    
    4)简写形式
        不管是if还是elseif还是else,只要其后面执行的代码"只有一句",那么就可以把大括号去掉,执行效果也是一样的。
        例如:
            public void test(int x) {
                if(x>10)
                    System.out.println("参数大于10");
                else if(x>5) 
                    System.out.println("参数大于5");
                else if(x>0)
                    System.out.println("参数大于0");
                else
                    System.out.println("参数小于等于0");
            }
    

    5)相关例子
        写一个方法实现分时问侯, 如是8点至12点,返回"上午好", 12点至14点,返回"中午好",14点至18点,返回"下午好", 其它时间返回"晚上好"。
        注:方法中使用return可以把数据返回给方法的调用者
        public String sayHello(int hour) {
            String msg; 
            if(hour >=8 && hour < 12) 
                msg = "上午好";
            else if(hour>=12 && hour <14) 
                msg = "中午好";
            else if(hour>=14 && hour <18) 
                 msg = "下午好";
            else 
                 msg = "晚上好";

            return msg;
        }


        写一个方法判断某一年是否为闰年
        标准:能被4整除,但不能被100整除;或者能被400整除

        //返回true表示是闰年,false表示不是闰年
        public boolean isLeapYear(int year) {
            if((year%4==0 && year%100!=0) || (year%400==0))
                return true;
            else 
                return false;
        }


5.流程控制-switch
    使用switch语句完成的功能,使用if语句同样也能完成。但是使用if语句完成的功能,使用switch语句却不一定能完成。不过在某些特定的情况下,switch还是有着自己的独特之处。

    1)语法
        注意:break关键字表示直接退出整个switch代码块

        switch(变量) {
            case value1:
                 //执行代码1;
                 break;
            ...
            case valueN
                 //执行代码n;
                 break;

            default:
                 //执行代码;
                 break;
        }
        
        注:switch只能接收byte, short, char或者int类型的变量,如果是JKD1.7那么也可以接收String类型的变量
        
        例如:
        int day = 4;
        String result;
        switch(day) {
            case 0:
               result = "星期天";
               break;
            case 1:
               result = "星期一";
               break;
            case 2:
               result = "星期二";
               break;
            case 3:
               result = "星期三";
               break;
            case 4:
               result = "星期四";
               break;
            case 5:
               result = "星期五";
               break;
            case 6:
               result = "星期六";
               break;
            default:
               result = "参数有误";
               break;
        }
        System.out.println(day+" : "+result);

    2)特殊情况
        如果switch的变量与某个case的值匹配,那么就从这个case中的代码开始执行。假如遇到break,就退出整个switch语句,否则依次执行switch语句中后续的case子句,而且不再检查case的值。
        
        例如:写一个方法,返回指定月份有多少天
        public int getLastDay(int year, int month) {
            int day = 30;
            switch(month) {
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                case 12:
                    day=31;
                    break;
                case 2:
                    day = getLeapYear(year)? 29:28;
            }

            return day;
        }
        注意:此处调用的getLeapYear方法就是上面if语句的例子所写的判断一个年份是否是闰年的方法.(在同一个类中,方法之间可以直接调用)


6.循环-for
    语法:
        for(<初始化>; <条件表达式>; <增量>)  {
            //要循环执行的代码
        }
        直到某一次增量执行后,条件表达式的值为false则循环结束
        
        执行步骤:
        1.初始化
        2.条件表达式
            2.1 false则退出循环
            2.2 true则执行循环代码
            2.3 执行增量变化
            2.4 判断条件表达式
                false则退出循环
                true则执行循环代码
                ....

    例如:
        使用循环打印10次hello world
        for(int i=0;i<10;i++){
            System.out.println("hello world");
        }

    
    例如:
        写一个方法,完成计算从1加到100的和
        public int sum() {
            int result = 0;
            for(int i=1;i<=100;i++) {
                //result = result + i;
                result+=i;
            }
            return result;
        }

    例如:
        写一个方法,完成计算从1加到n的和
        public int sum(int n) {
            int result = 0;
            for(int i=1;i<=n;i++) {
                result = result + i;
            }
            return result;
        }

    
    注意:for语句一般用在循环次数事先可确定的情况下
    
7.循环-while
    while
        语法:
        while(循环条件) {
            循环体
        }

        当循环条件为true时,就执行循环代码,否则终止循环;
    
    例如:
        用while循环完成计算从1加到n的和
        public int sum(int n) {
            int result = 0;
            int i=1;
            while(i<=n) {
                result = result + i;
                i++;
            }
            return result;
        }
    

    do-while
        和while非常类似,只不过先执行循环体,然后再判断循环条件.

        语法:
            do{
                循环体
            } while(循环条件);
        
        例如:
            用do-while循环完成计算从1加到n的和
            public int sum(int n) {
                int result = 0;
                int i = 1;
                do {
                    result = result + i;
                    i++;
                } while(i<=n)
                return result;
            }


    注意:while和do-while循环用在循环次数事先不可确定的情况下


8.循环的嵌套
    例如:打印出五行每行十个☆
    //这个循环可以打出五个换行
    for(int i=0;i<5;i++){
        System.out.println();
    }
    
    //这个循环可以连着打印出10个☆
    //但是不会换行
    //注意print方法和println方法的区别
    for(int j=0;j<10;j++){
        System.out.print("☆");
    }

    那么把俩个循环嵌套在一起即可完成功能
    for(int i=0;i<5;i++){

        for(int j=0;j<10;j++){
            System.out.print("☆");
        }

        System.out.println();
    }

    例如:
        往控制台上输出以下内容:
            *
            **
            ***
            ****
            *****
            ******
            *******

        public void print(int n){
            for(int i=0;i<n;i++){
                for(int j=0;j<i+1;j++){
                    System.out.print("*");
                }
                System.out.println();
            }
        }

9.break和continue
    注:break和continue一般都是要结合循环使用的(for/while/do-while)
    break
        终止当前或指定循环
        for(int i=0;i<10;i++){
            if(i==3){
                break;
            }
            System.out.println("i = "+i);
        }
        输出结果:
        i = 0
        i = 1
        i = 2
    
    continue
        跳过本次循环,执行下一次循环
        for(int i=0;i<10;i++){
            if(i==3){
                continue;
            }
            System.out.println("i = "+i);
        }
        输出结果:
        i = 0
        i = 1
        i = 2
        i = 4
        i = 5
        i = 6
        i = 7
        i = 8
        i = 9


10.label标签
    在循环嵌套的时候,使用label可以让break或者continue作用到指定的循环上,否则break或者continue只会默认作用到当前所处的循环上。

    例如: 这个break跳出的是当前循环(也就是这里的内循环)
    for(int i=0;i<3;i++){

        for(int j=0;j<5;j++){
            if(j==3){
                break;
            }
            System.out.println("j = "+j);
        }

    }
    输出结果:
    j = 0
    j = 1
    j = 2
    j = 0
    j = 1
    j = 2
    j = 0
    j = 1
    j = 2


    例如:这个break跳出的是外循环(因为使用了label)
    f1:for(int i=0;i<3;i++){

        for(int j=0;j<5;j++){
            if(j==3){
                break f1;
            }
            System.out.println("j = "+j);
        }

    }
    输出结果:
    j = 0
    j = 1
    j = 2

猜你喜欢

转载自www.cnblogs.com/yue-170305/p/11478907.html