Java学习

前言:之前学了几遍Java,笔记做的不怎么样,现在想重新整理一下,但是仍然有纰漏,欢迎指正!

基本语法

关键字和保留字

关键字(keyword)
定义

被Java语言赋予了特殊含义,用作专门哦那个图的字符串

特点

所有关键字中所有字母都是小写的

在这里插入图片描述

在这里插入图片描述

保留字(reserved word)
定义

现有的Java版本尚未使用,但是以后版本呢可能会作为关键字使用。

gotoconst

标识符(identifier)

定义

Java 对各种变量、 方法和类等要素命名时使用的字符序列称为标识符。

标识符定义规则:
  • 由26个英文字母大小写, 0-9 , _或 $ 组成
  • 数字不可以开头。
  • 不可以使用关键字和保留字,但能包含关键字和保留字。
  • Java中严格区分大小写,长度无限制。
  • 标识符不能包含空格。
标识符提示
  • 凡是自己可以起名字的地方都叫标识符。

  • Static也可以作为标识符,因为Java严格区分大小写

名称命名规范
命名规范:
  • 包名:多单词组成时所有字母都小写: xxxyyyzzz
  • 类名、接口名:多单词组成时,所有单词的首字母大写: XxxYyyZzz
  • 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个
    单词首字母大写: xxxYyyZzz
  • 常量名:所有字母都大写。多单词时每个单词用下划线连接: XXX_YYY_ZZZ
注意事项:
  • 不强制遵循这个规则(即使不按照这个规则也不会报错),但是尽量采用这种命名规则增加可读性,易用性(调用类的时候可以不看就知道怎么写)

  • 起名的时候要做到“见名知意”,即见到名字就知道是什么意思

  • 由于Java采用Unicode编码,故标识符可以使用用汉字,但是实际使用应该避免使用汉字

变量

概念
  • 内存中的一个存储区域
  • 该区域的数据可以在同一类型范围内不断变化
  • 变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值
作用:

​ 用于在内存中保存数据

声明变量
  • 语法: <数据类型> <变量名称>
    例如: int var;
变量的赋值
  • 语法: <变量名称> = <值>
    例如: var = 10;
声明和赋值变量
  • 语法: <数据类型> <变量名> = <初始化值>
    例如:int var = 10;
变量声明使用实例:
/**
 * @author wangxin
 * @create 2020-07-23 10:04
 */
public class Main {
  public static void main(String[] args) {
    //声明并赋值
    int age = 10;
    System.out.println(age);

    //先声明再赋值
    int num;
    num = 5;
    System.out.println(num);

    //若只声明不赋值会报错
    //    int charge;
    //    System.out.println(charge);
  }
}
变量的类型:
分类:

在这里插入图片描述

注意其中字符串为引用数据类型

汇总表:

在这里插入图片描述

字节换算:

例如byte,有一个字节,1字节=8bit ,1bit能存储一个二进制数,所以能存储最大的数位(二进制全为1),即为255,最小能存储(二进制全为0),即为0,因为实际使用含负数,所以取中间的范围,即为-128到+127

​ 1MB = 1024KB 1KB= 1024B 1B=8bit

bit: 计算机中的最小存储单位。 byte:计算机中基本存储单元。

整形:
  • byte超过定义大小会报错,注意编译时,运行时byte值的大小

  • long以的l结尾,通常采用大写的L,因为l和1很像,可以避免出错

  • 平常编程中通常使用较多的是int

浮点型
  • 浮点比整形存的数据范围更大,因为采用次幂存储,没有具体到每一位,故节省空间,存的范围更大

  • 由表中得出double和float的精度不能非常高(float:小数点后7位,double:小数点后14位),需要高精度的浮点需要引用其他类的支持(见后)。

  • 定义float要以f结尾,大小写都可以

  • 编程中通常使用double

字符类型
  • 采用单引号包住字符

  • 只能包一个字符(两个字符会报错)

  • 字符里面也可以放转义字符,转义字符如下表

在这里插入图片描述

  • 字符里面可以放Unicode码(16进制)表示单个字符

Unicode字符集是把字符与二进制互转的对应关系表,因为计算机底层采用二进制存储数据,所以字符集类似函数中的函数,二进制和字符类似于自变量和因变量(可互换,因为谁当自变量因变量取决于怎么转换)

布尔类型
  • 只能取true,false(不带任何符号)

  • 常用于条件判断循环等中使用

变量类型实例:
/**
 * @author wangxin
 * @create 2020-07-23 10:04
 */
public class Main {
  public static void main(String[] args) {
     //1.byte正常使用:10
      byte b1 = 10;
      System.out.println(b1);

    //2.byte超过范围,报错
    //  byte b2 = 128;

    //3.long正常使用:1234567891044455455
      long l1 = 1234567891044455455L;
      System.out.println(l1);

    //4.float正常使用:2.5
      float f1 = 2.5f;
    System.out.println(f1);

    //5.不会报错,但是超过精度的数据会被截取,此输出为:2.1234567
    float f2 = 2.123456789f;
    System.out.println(f2);

    //6.double正常使用:3.1415926
    double d1 = 3.1415926;
    System.out.println(d1);

    //8.char正常使用:w  王  わ
    char c1 = 'w';
    System.out.println(c1);
    char c2 = '王';
    System.out.println(c2);
    char c3 = 'わ';
    System.out.println(c3);

    //9.正常使用,转义符:'
    char c4 = '\'';
    System.out.println(c4);

    //10.正常使用,Unicode码:王
    char c5 = '\u738b';
    System.out.println(c5);

    //11.如果括号里面不包含任何值会报错
    //char c6 = '';


    //12.布尔类型正常使用:true
    boolean ble1 = true;
    System.out.println(ble1);
    
    //13.布尔类型错误使用,不能待任何符号
   // boolean ble2 = 'true';

  }
}
变量使用作用域:
定义:

变量在程序中有它存在的有效位置,超出这个位置则变量无法使用。

变量作用域实例:
/**
 * @author wangxin
 * @create 2020-07-23 10:04
 */
public class Main {
  public static void main(String[] args) {
    //1.声明变量age且可以访问age
    int age = 10;
    System.out.println(age);

    //3.再次声明age无法声明,因为age在此作用域内有效,再次声明变量重复,报错
    //int age = 20;

  }
  public static void method(){
    //2.无法访问age,因为age是另外一个函数的变量,超出了age的作用域
    //System.out.println(age);
  }
}
变量使用注意事项总结:
  • Java中每个变量必须先声明,后使用

  • Java为强类型语言必须声明变量类型,JavaScript、python为弱类型可不用声明变量类型

  • 使用变量名来访问这块区域的数据

  • 变量的作用域:其定义所在的一对{ }内

  • 变量只有在其作用域内才有效

  • 同一个作用域内,不能定义重名的变量

Tips:逆向思维,有些时候遇到不确定的问题,可以先假设成立,然后代码验证正确与否

自动类型提升
定义:

有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。

其中无boolean类型,因为布尔类型无法做运算

自动转换关系:

在这里插入图片描述

  • 由图中得出byte,char,short处于同级关系,故不能相互转化(自身转化也不行),都只能自动转化为int

  • 级别低和级别高的运算的结果自动往级别高的靠,且只能拿级别高的变量类型来装

  • java在做运算的时候,如果操作数均在int范围内,那么一律在int的空间内运算

自动提升实例:
/**
 * @author wangxin
 * @create 2020-07-23 10:04
 */
public class Main {
  public static void main(String[] args) {
    //1.正常类型转换:30
    byte b1 = 10;
    int i1 = 20;
    int i2 = i1 + b1;
    System.out.println(i2);

    //2.采用同级的变量类型,或者更低的变量类型,报错
    //byte b2 = b1+i1;

    //3.同级别的变量不能装(byte,short,char),报错
//    byte b3 = 10;
//    byte b4 = 10;
//    byte b5 = b3+b4;
  }
}
强制类型转换
定义:

自动类型转换的逆过程, 将容量大的数据类型转换为容量小的数据类型。

  • 使用时要加上强制转换符:()
  • 但可能造成精度降低或溢出,格外要注意。

当定义int为128时,强制转换为byte,其大小超过了byte,最后输出-128

  • long类型的变量没有加L,转为int,数据的大小超过int会报错(整型默认为int类型)

  • float后面不加f会报错(浮点型数据默认为double类型)

强制类型转换实例:
/**
 * @author wangxin
 * @create 2020-07-23 10:04
 */
public class Main {
  public static void main(String[] args) {
      //1.正常转换:100
      int i1 = 100;
      byte b1 = (byte) i1;
    System.out.println(b1);

    //2.正常转换,精度溢出:3
    double d1 = 3.14;
    int i2 = (int) d1;
    System.out.println(i2);

    //3.long类型的变量没有加L,数据的大小超过int会报错(整型默认为int类型)
    //long l1 = 12345678910;   报错
    //正确
    long l2 = 12345678910L;

    //4.float后面要加f,不然会报错(浮点数默认为double类型的)
    //float f1 = 3.14;
    
  }
}

字符串类型
定义:

用于存储字符串的数据类型,本质是引用数据类型

  • 使用双引号,内容不写也可以,也可以只写一个字符。

  • 当把任何基本数据类型的值和字符串(String)进行连接运算时(+), 基本数据类型的值将自动转化为字符串(String)类型

练习题:
  • String str1 = 4; //判断对错: no,String不能存储 整型数据
  • String str2 = 3.5f + “”; //判断str2对错: yes 类型自动转换为String
  • System.out.println(‘a’+1+“Hello!”); //输出: 98Hello! 前面char和int相加结果为int,再和String相加
字符串使用实例
/**
 * @author wangxin
 * @create 2020-07-23 10:04
 */
public class Main {
  public static void main(String[] args) {
    //1.String正确的使用方式,都可以正常输出
    String s1 = "";
    String s2 = "王";
    String s3 = "\n";
    String s4 = "陪伴是最长情的告白!";
    System.out.println(s1);
    System.out.println(s2);
    System.out.println(s3);
    System.out.println(s4);
    //2.String与其他数据类型相加,自动转换为String类型
    String s5 = "学号:";
    int i1 = 10;
    String s6 = i1+s5;
    System.out.println(s6);
  }
}

其中String转其他基本类型详见之后的String的包装类使用

进制之间的转换
  • 所有数字在计算机底层都以二进制形式存在。

  • 对于整数而言,有四种表示方式:

    • 二进制(binary): 0,1 ,满2进1.以0b或0B开头
    • 十进制(decimal): 0-9 ,满10进1。
    • 八进制(octal): 0-7 ,满8进1. 以数字0开头表示
    • 十六进制(hex): 0-9及A-F,满16进1. 以0x或0X开头表示。此处的A-F不区分大小写。
      如: 0x21AF +1= 0X21B0
  • 常用进制如下表

在这里插入图片描述

在这里插入图片描述

二进制简介:
  • Java整数常量默认是int类型,当用二进制定义整数时,其第32位是符号位;当是long类型时,二进制默认占64位,第64位是符号位
  • 二进制的整数有如下三种形式:
    • 原码:直接将一个数值换成二进制数。最高位是符号位
    • 负数的反码:是对原码按位取反,最高位(符号位)确定为1。
    • 负数的补码:其反码加1(末尾加1,如果本来为1需要进位)。
  • 计算机以二进制补码的形式保存所有的整数。
    • 正数的原码、反码、补码都相同
    • 负数的补码是其反码+1

为什么要使用原码、反码、补码表示形式呢?

计算机辨别“符号位”显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法(只需要原酸加法), 这样计算机运算的设计就更简单了。

在这里插入图片描述

二进制的保存

在这里插入图片描述

在这里插入图片描述

问题:当int类型的数据128转换为byte类型时为什么结果为-128?

因为int是4字节的存储方式,byte的1字节的存储方式,当int的128转换为byte时超过了1位的大小,故byte只截取一位的数据,导致符号位和大小改变。

在这里插入图片描述

双字节转换为byte 截取最后,符号位改变

二进制转十进制

在这里插入图片描述

十进制转二进制

在这里插入图片描述

其它进制的转换

在这里插入图片描述

以二进制作为中间变量进行转换

在这里插入图片描述

在这里插入图片描述

运算符

  • 算术运算符
  • 赋值运算符
  • 比较运算符(关系运算符)
  • 逻辑运算符
  • 位运算符
  • 三元运算符
算数运算符

在这里插入图片描述

加法运算符
  • 对于整型和浮点型而言,等同于数学计算中的加法
  • 对于字符串而言,用于连接字符串
减法运算符
  • 普通计算中的减法
乘法运算符
  • 普通计算中的乘法
除法运算符
  • 普通计算的除法
  • 注意当除数和被除数数据类型为整数类型时,结果也为整型
  • 当除数和被除数任一有一个为浮点型数据时,会自动转化为浮点结果(数据类型的自动向上转换)
  • 当除数与被除数都是整形时,注意除数为零会引发异常(程序出错),要避免
求余运算符
  • 求余的结果不一定是整数,也可能是小数(5(int)%3.3(double))
  • 当第一个操作数与第二个操作数都是整形时,注意第二个操作数为零会引发异常(程序出错),要避免
  • 如果某一个操作数为浮点数,当第二个操作数为0时,结果为NaN
  • 第一个操作数为0(0.0)和任何数求余都是0(0.0)
  • 求余结果的符号取决于第一个操作数
自加运算符(++)
  • 自加是单目运算符,只能运算一个变量
  • 自加只能操作单个数值(整型、浮点型)的变量,不可以操作常量或表达式
  • 自加运算符可以出现在变量的左边和右边,其效果不一样
    • 左边(++var):先把变量+1,再把变量放进表达式中运算
    • 右边(var++):先把变量放进表达式中运算,再把变量+1
自减运算符(–)

同自加运算符

思考:byte a=127; 那System.out.println(++a);输出的值为多少?

答:当执行输出语句的时候,++a先执行自加,然后再输出,我们知道byte最大为127,自加操作已经超出了byte的大小,这个时候程序在int运算区域(4字节)内运算,当输出的时候,自动截取int内的(1字节),导致数值和符号位改变,最后输出为-128,更具体的原因请看上

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
     byte a = 127;
        System.out.println(++a);
    }
}
算数运算符实例
/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
      int a = 30;
      int b = 20;
      double c = 30.3;
      double d = 25.5;
      String e = "陪伴是";
      String f = "最长情的告白!";

      //整型变量相加:50
      System.out.println(a+b);
      //浮点型变量相加:55.8
        System.out.println(c+d);
      //字符串相加:陪伴是最长情的告白!
        System.out.println(e+f);

        //整型变量相减:10
        System.out.println(a-b);
        //浮点型变量相减:4.800000000000001
        System.out.println(c-d);

        //整型变量相乘:600
        System.out.println(a*b);
        //浮点型变量相乘:772.65
        System.out.println(c*d);


        //整型变量相除,后面部分会被截取,不是四舍五入:1
        System.out.println(a/b);
        //浮点型变量相除,具有小数部分:1.188235294117647
        System.out.println(c/d);
        //当除数和被除数中有只要有一个为浮点型数据时,结果为浮点型:0.9900990099009901   1.01
      System.out.println(a/c);
      System.out.println(c/a);
        int g = 0;
        //除数不可以为零,报错: by zero
        //System.out.println(a/g);
      double h = 0.0;
      //当除数是浮点型为零时,不会报错,结果为:Infinity
      System.out.println(a/h);

      //整型求余 :10
      System.out.println(a%b);
      //浮点型求余:4.800000000000001
      System.out.println(c%d);
      //当dierge数是浮点型为零时,不会报错,结果为:NaN
      System.out.println(a%h);

      int x1 = 10;
      int y1 = 20;
      //自增在前,先运算,再带入表达式   x1 = 11  x2 = 11
      int x2 = ++x1;
      System.out.println("x1 = " + x1);
      System.out.println("x2 = " + x2);
      //自增在后,先带入表达式,再运算  y1 = 21  y2 = 20
      int y2 = y1++;
      System.out.println("y1 = " + y1);
      System.out.println("y2 = " + y2);
    }
}
赋值运算符

作用:用于为变量指定变量值

  • 可以连续赋值

    /**
     * @author wangxin
     * @create 2020-07-24 9:08
     */
    public class Main {
        public static void main(String[] args) {
            //单个整型赋值
            int a = 100;
            //单个浮点赋值
           double b = 2.5;
           //单个字符串赋值
          String c = "陪伴是最长情的告白!";
          //单个布尔赋值
          boolean d = true;
          //多个整型赋值,e,f,g都为10
          int e;
          int f;
          int g;
          e = f = g = 10;
        }
    }
    
  • 取反运算只适用于单个操作数,它直接将计算机底层二进制码按位取反(包括符号位)。

位运算举例1(5^9)
  1. 5的二进制码是0101(0是为了对齐)
  2. 9的二进制码是1001
  3. 由运算法则中的异或运算法则得结果为 1100,为10进制的12,得到最后结果

在这里插入图片描述

问:为什么是直接用二进制码计算的?

答:因为正数的原码和补码是相同的,故直接拿原码计算即可(底层并不是,自己手算可以这样)

问:为什么前面有这摩多0?

答:8bit=1字节 int占4字节 故有32bit,32个存储0、1的单元,前面没有值,故为0,方便计算,只取有效部分

位运算举例2(~-5)
  1. 首先得出-5的反码
  2. 再得出-5的补码
  3. 最后把补码取反,得到结果

在这里插入图片描述

注意:其中取反以后符号位为0的话直接就是答案,如果符号位为1则需要逆运算得到原码才是最终结果!!!

位运算符举例3(左移运算符)
  • 5 << 2 (5向左移动2位)
  1. 把5的二进制(000…0101)码向左移动两位(包括符号位,0…010100)
  2. 得到新的二进制码(10100),即为答案20

由于正数二进制原码补码都一样,且计算的时候符号位都没有改变,故直接用原码计算即可

  • -5 << 2(-5向左移动2位)
  1. 把-5转换为补码(11111…111011)
  2. 向左移动两位(111…101100)
  3. 补码减1(二进制的1),恢复成反码(111…101011)
  4. 恢复成原码(100…010100),答案即为-20

提示:减1的时候遇到末尾为0的时候可能不好想,可以联想100-1=099 即是 100-001=011(二进制)

在这里插入图片描述

位运算符举例4(右移运算符)
  • -5 >> 2 (有符号右移运算符)
  1. 把-5转换为补码(11111…111011)
  2. 把补码右移两位,前面空出的用符号位的数字填充(1111111…1110)
  3. 减一得到反码(1111111…1101)
  4. 取反得到原码(1000000…0010),得到答案-2

在这里插入图片描述

  • -5 >>> 2 (无符号右移运算符)
  1. 把-5转换为补码(11111…111011)
  2. 把补码右移两位,前面空出的用符号位的0填充(0011111…1110)
  3. 减一得到反码(0011111…1101)
  4. 取反得到原码(0100000…0010),得到答案1073741822

在这里插入图片描述

注意:

  • 对于低于int类型(入byte、short和char)的操作总是先转换为int再进行移位
  • 对于int类型的整数移位a>>b,如果b>32的时候,系统会先对32求余(int类型的数据只有32位),然后得到的结果才是真正的位移数,例如,a>>33和a>>1,a>>32和a是结果是一样的
  • 由上可得long类型由于是64位的,同理可得和上面的类似结论
  • 移位运算不会改变变量,只是得到了一个结果
  • a左移n位=a*(2^n) a右移n位=2/(2^n)
总结

在这里插入图片描述

拓展赋值运算符
作用
  • 用于自身赋值运算

在这里插入图片描述

  • 底层的原理和普通赋值不一样
/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
      short a = 10;
      //这样写会报错
      //a=a+1;
      //拓展运算写法不会错
       a+=1;
      System.out.println("a = " + a);
    }
}
  • 拓展写法可以提升性能,且增加可读性,推荐!!!
比较运算符
作用

用于判断两个变量或者常量的大小,比较结果返回的是布尔值

分类

在这里插入图片描述

  • 其中<,<=,>,>=与数学中的很类似,就不做介绍
==运算符
  • 如果两个操作数都是数值类型,即使是类型不同,值相同,也返回true
/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
  public static void main(String[] args) {
    int a = 10;
    double b = 10.0;
    //输出true
    System.out.println(a==b);
    
    int c = 97;
    char d = 'a';
    //字符a对应97,故输出true
    System.out.println(c==d);
  }
}
  • 引用类型不可以和基本数据类型作比较
  • 如果两个操作数为引用类型(例如String),必须两个类型具有父子关系(继承的知识)才能比较,并且需要指向同一个对象才能返回true
import java.util.Scanner;

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
  public static void main(String[] args) {
      String a ="陪伴是最长情的告白";

      Object o = new Object();
      //所有引用类型会继承Object类,所以可以比较,但是他们指向的对象不一样,所以输出false
    System.out.println(o == a);

    //引用的对象都是"陪伴是最长情的告白"这个字符串,返回true
    System.out.println("陪伴是最长情的告白" == a);

    String b = "陪伴是最长情的告白";
    //即使是新建一个字符串,只要内容一样,那么引用的对象都一样,还是返回true
    System.out.println(a == b);

    String c = "陪伴是最长情的告白!";
    //字符串内容不一样了,返回false
    System.out.println(c == b);

    Scanner sc1 = new  Scanner(System.in);
    Scanner sc2 = new  Scanner(System.in);
    //两个新建对象,引用的对象是不一样的,所以返回false
    System.out.println(sc1 == sc2);
    //把sc2的对象赋值给sc1,这个时候两个的引用对象都一样,所以返回true
    sc1 = sc2;
    System.out.println(sc1 == sc2);
  }
}

提示:Sting字符串比较内容是否一样一般是不用==的,一般采用equals方法比较

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
  public static void main(String[] args) {
     String a = "陪伴是最长情的告白";
     String b = new String("陪伴是最长情的告白");
     //显示的字符串和a是一样的
    System.out.println(b);
    //比较结果是false,因为==比较的是引用的对象,这两个的引用对象是不一样的
    System.out.println("a==b = " + (a == b));
    //用equals方法比较字符串内容,得到true
    System.out.println(a.equals(b));
  }
}
!=运算符
  • 如果两个操作数都是数值类型,即使是类型不同,只要值不同,就返回true
  • 如果两个操作数为引用类型(例如String),必须两个类型具有父子关系(继承的知识)才能比较,并且只要指向对象不同就返回true
逻辑运算符
作用

用于操作两个布尔类型的常量或者变量

在这里插入图片描述

  • 逻辑运算符用于连接布尔型表达式,在Java中不可以写成3<x<6,应该写成x>3 & x<6 。

  • “&”和“&&”的区别:

    • 单&时,左边无论真假,右边都进行运算;

    • 双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。

  • “|”和“||”的区别同理, ||表示:当左边为真,右边不参与运算。

不短路&

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
  public static void main(String[] args) {
    int a = 5;
    int b = 10;
    //运行结果为a = 5 , b = 11 ,b++可以得到运算
    if(a>4 | b++ >10){
      System.out.println("a = " + a);
      System.out.println("b = " + b);
    }
  }
}

短路&&

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
  public static void main(String[] args) {
    int a = 5;
    int b = 10;
    //运行结果为a = 5 , b = 10 ,b++得不到运算
    if(a>4 || b++ >10){
      System.out.println("a = " + a);
      System.out.println("b = " + b);
    }
  }
}
三目运算符
作用

用于判断,并且返回给某个值

格式

在这里插入图片描述

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
  public static void main(String[] args) {
    //判断5是否大于3,并且把字符串返回给变量,输出 5大于3
   String str = 5>3 ? "5大于3" : "5不大于3";
    System.out.println(str);
  }
}

等价于

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
  public static void main(String[] args) {
    //判断5是否大于3
     String  str = null;
    if(5>3){
      str = "5大于3";
    }else{
      str = "5不大于3";
    }
    System.out.println(str);   
  }
}
  • 三目运算符还支持嵌套
/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
  public static void main(String[] args) {
        int a = 11;
        int b = 11;
        //三目运算符嵌套,判断是不是相等 ,输出 : a等于b
    System.out.println(a > b ?
            "a大于b" : (a < b ? "a小于b" : "a等于b")
    );
  }
}
运算符的优先级

运算符具有运算的优先级,优先级高的优先运算

优先级表

在这里插入图片描述

  • 单目运算符、赋值运算符、三目运算符是从右至左运算的

  • 不要把一个表达式写的太复杂,尽量使用"()"控制顺序

流程控制

作用

流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。

  • 顺序结构
  • 分支结构
  • 循环结构
顺序结构
定义

程序从上到下逐行地执行,中间没有任何判断和跳转。

在这里插入图片描述

注意:Java变量必须在前文有定义才能使用,不然会报错

分支结构
定义

根据条件,选择性地执行某段代码。

三种形式的if语句

在这里插入图片描述

在这里插入图片描述

  • 放在if后面的必须是逻辑表达式(返回值为布尔类型)
  • 如果代码块里面遇到了return、break、continue等关键字或者遇到了异常,代码后面的语句都会得不到执行
  • 语句块只有一条执行语句时,一对{}可以省略,为了提高可读性和不容易出错,建议即使是一条执行语句也要写大括号
  • if-else语句结构,根据需要可以嵌套使用
  • 当if-else结构是“多选一”时,最后的else是可选的,根据需要可以省略
  • 当多个条件是“互斥”关系时,条件判断语句及执行语句间顺序无所谓
  • 当多个条件是“包含”关系时,“小上大下”

互斥:A和B的交集为空,即两个条件表达的范围没有重复,各自独立

包含:A和B具有交集,即两个条件表达的范围有重复(并不是完全重复,也可能只是一部分重复)。

小上大下:上面的是范围小的条件,往下逐渐增大范围

switch-case语句

语法

在这里插入图片描述

规则

  • switch(表达式)中表达式的值必须是下述几种类型之一: byte, short,char, int, 枚举 (jdk 5.0及以后支持), String (jdk 7.0及以后支持);
  • case子句中的值必须是常量,不能是变量名或不确定的表达式值;
  • 同一个switch语句,所有case子句中的常量值互不相同,且常量值类型要相同和表达式的值类型相同;
  • break语句用来在执行完一个case分支后务必使用break使程序跳出switch语句块;如果没有break,程序会顺序一直执行到switch结尾(执行过程中无论是不是等于那个常量,都会执行里面的语句)
  • default子句是可有可无的。位置也可以灵活放置(一般建议放在最后)。当没有匹配的case时,执行default
循环结构
定义

根据循环条件,重复性的执行某段代码。

分类
  • for 循环
  • while 循环
  • do-while 循环
循环语句的四个部分
  • 初始化部分(init_statement)
  • 循环条件部分(test_exp)
  • 循环体部分(body_statement)
  • 迭代部分(alter_statement)

在这里插入图片描述

for循环

语法

for (①初始化部分 ; ②循环条件部分 ; ④迭代部分){
③循环体部分;

执行流程

​ ①-②-③-④-②-③-④-②-③-④-…-②

  • ②循环条件部分为boolean类型表达式,当值为false时,退出循环
  • ①初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔
  • ④可以有多个变量更新,用逗号分隔

图解例子

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 100; i++) {
        	System.out.println(i);         
        }
    }
}

在这里插入图片描述

tips

  • 变量污染问题:

    ​ 变量定义的时候尽量不要把作用范围扩展的太大,这样容易误操作导致数据改变,得不到想要的结果

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
    	//作用域在整个函数内都有效
        int i = 0;
        for (; i < 10; i++) {
            System.out.println(i);
        }
    }
}
/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //作用域仅仅在for循环内有效,用完自动销毁
        for (  int i = 0; i < 10; i++) {
            System.out.println(i);
        }
    }
}
  • 使用循环变量技巧

    ​ 尽量不要直接使用循环变量,而是应该用一个临时变量去装循环变量,避免由于改变等操作导致循环变量的改变。

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        int tmp = 0;
        for (int i = 0; i < 10; i++) {
            tmp = i;
            //这里可以访问i的值
            System.out.println("tmp = " + tmp);
        }
        //还可以访问最后i的值
        System.out.println("tmp = " + tmp);
    }
}
  • for循环的括号内可以不写循环初始化、条件部分(不写会导致死循环,但是不写不会语法报错)和迭代部分
  • 对于标准for循环而言,循环条件总是要比迭代语句多执行一次
while循环

语法格式

①初始化部分
while(②循环条件部分){
③循环体部分;
④迭代部分;
}

执行过程

​ ①-②-③-④-②-③-④-②-③-④-…-②

  • 注意不要忘记写④(迭代部分)。 否则, 循环将不能结束, 变成死循环。

while使用例子

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //初始化循环变量
        int count = 0;
        //当count<10的时候,执行循环体
        while (count < 10){
            //执行的语句
            System.out.println("count = " + count);
            //迭代语句
            count++;
        }
    }
}

tips:

当while()的后面有分号的时候是一个死循环,请注意,这样分号相当于是一个空语句!

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //初始化循环变量
        int count = 0;
        //分号是空语句,这是一个死循环
        while (count < 10);
        //不会得到执行,上面是一个死循环
        {
            System.out.println("count = " + count);
            count++;
        }
    }
}
do-while循环

语法格式

①初始化部分;
do{
③循环体部分
④迭代部分
}while(②循环条件部分);

执行过程

​ ①---②-③-④-②-③-④-…②

  • 无论最开始循环条件是否成立,都会至少执行一次循环体

示例

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //初始化循环变量
        int count = 20;
        //count的值已经大于10,返回的结果已经是假了,但是仍然会执行一次下面的输出语句
        do {
            System.out.println(count++);
        }while (count < 10);
    }
}
循环嵌套

定义:循环内又嵌套循环的结构

在这里插入图片描述

  • 执行次数等于内层的循环次数(m)乘以外层的循环次数(n),即为m*n

  • 只有当内层循环的循环条件为false的时候,才会完全跳出内层循环,才可以结束外层循环的当次循环

  • 其中的循环结构,使用for、while和do-while都可以当作循环的语块

实例

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.println("i = "+i+"   j = "+j);
            }
        }
    }
}

运行结果

i = 0   j = 0
i = 0   j = 1
i = 0   j = 2
i = 1   j = 0
i = 1   j = 1
i = 1   j = 2
i = 2   j = 0
i = 2   j = 1
i = 2   j = 2
i = 3   j = 0
i = 3   j = 1
i = 3   j = 2
i = 4   j = 0
i = 4   j = 1
i = 4   j = 2

Process finished with exit code 0
循环控制结构

break

作用:跳出循环,不再执行跳出的循环

例子

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            //当i循环到3的时候就跳出循环,之后不再进行这次循环
            if (i == 3) {
                break;
            }
            System.out.println("i = " + i);
        }
    }
}
i = 0
i = 1
i = 2

Process finished with exit code 0

continue

作用:跳出当次循环,开始下一个循环周期

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 3; j++) {
                //当i==1的时候,直接就结束整个方法了,后面的循环已经无法执行了
                if(i == 1){
                    return;
                }
                System.out.println("i = " + i);
                System.out.println("j = " + j);
            }
        }
    }
}
i = 0
j = 0
i = 0
j = 1
i = 0
j = 2

Process finished with exit code 0

例子

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            //当i循环到3的时候就跳出当次循环,之后的循环继续
            if (i == 3) {
               continue;
            }
            System.out.println("i = " + i);
        }
    }
}
i = 0
i = 1
i = 2
i = 4

Process finished with exit code 0

return

直接结束整个函数,在一个函数中,return后面的代码无法得到执行

例子

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 3; j++) {
                //当i==1的时候,直接就结束整个方法了,后面的循环已经无法执行了
                if(i == 1){
                    return;
                }
                System.out.println("i = " + i);
                System.out.println("j = " + j);
            }
        }
    }
}

注意事项

  • break只能用于switch语句和循环语句中。
  • continue 只能用于循环语句中。
  • 二者功能类似,但continue是终止本次循环, break是终止本层循环。
  • break、 continue之后不能有其他的语句,因为程序永远不会执行其后的语句。
  • 很多语言都有goto语句, goto语句可以随意将控制转移到程序中的任意一条语句上,然后执行它。但使程序容易出错。 Java中的break和continue是不同于goto的
标签语法

作用:标识循环代码块(for,while,do-while),配合continue和break精确控制循环,一般多重循环使用较多

  • 不需要进行二次判断就可以进行循环控制,非常方便
  • 标签语句必须紧接在循环的头部。标签语句不能用在非循环语句的前面。

示例

普通嵌套循环

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //普通嵌套循环
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 2; j++) {
                System.out.println("i = " + i);
                System.out.println("j = " + j);
            }
        }
    }
}
i = 0
j = 0
i = 0
j = 1
i = 1
j = 0
i = 1
j = 1
i = 2
j = 0
i = 2
j = 1

Process finished with exit code 0

break使用标签

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //外层标签
        outer:
        for (int i = 0; i < 3; i++) {
            //内部标签
            inner:
            for (int j = 0; j < 2; j++) {
                //当i==1的时候直接跳出外层循环
                if(i == 1){
                    //跳出外层循环
                    break outer;
                }
                System.out.println("i = " + i);
                System.out.println("j = " + j);
            }
        }
    }
}
i = 0
j = 0
i = 0
j = 1

Process finished with exit code 0

continue使用标签

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //外层标签
        outer:
        for (int i = 0; i < 3; i++) {
            //内部标签
            inner:
            for (int j = 0; j < 2; j++) {
                //当i==1的时候直接跳过本次外层循环
                if(i == 1){
                    //跳过本次外层循环
                    continue outer;
                }
                System.out.println("i = " + i);
                System.out.println("j = " + j);
            }
        }
    }
}
i = 0
j = 0
i = 0
j = 1
i = 2
j = 0
i = 2
j = 1

Process finished with exit code 0

数组

定义:是多个相同类型数据按一定顺序排列的集合, 并使用一个名字命名, 并通过编号的方式对这些数据进行统一管理。

  • 数组元素类型是唯一的,可以是基本类型,也可以是引用类型
  • 数组一旦初始化,其所占的空间将会固定下来,即使是把数组元素的数据清空,但是所占的内存空间也不会清除
  • 数组一旦初始化,数组的长度是不可变的
定义数组
格式
  1. type[] arrayName
  2. type arrayName[]
注意事项
  • 两种方式都可以定义数组,但是主要推荐第一个方式,原因见下

type[] arrayName PK type arrayName[]

两种变量定义方式都可以定义变量,但是主要推荐使用前者,具体原因如下:

数组其实也是一种数据类型,例如int,它的数组类型不正对应int []吗?这样看起来就是一一对应的,可读性很高,而第二种风格是c语言的定义变量的风格,所以会导致我们很喜欢用第二种方式去定义数组(大部分人最开始学习编程语言都是c语言),但是实际上这样定义数组却可读性很差,括号在标识符后面,这样很难理解其中的意思。

  • 这个只是定义了数组,还没有初始化是不能使用的
  • 定义的时候仅仅定义了一个引用变量(定义了一个指针,此时还没有指向任何有效内存)
  • int [](其他类型也是一样的)实际上是一种引用类型,创建的是int [](其他类型也是一样的)类型的对象
初始化数组

定义:为数组的数组元素分配内存空间,并为每个数组元素赋值

分类

静态初始化:初始化时显示指定每个元素的初始值,由系统决定数组长度

动态初始化:只需要定义数组长度,由系统为数组元素分配初始值

格式

静态初始化:

arrayName = new type[]{element1,element2,element3,element4g};

动态初始化:
arrayName = new type [length];

  • 必须指定length参数,length参数为数组的长度

  • type必须和之前定义数组的的type类型一样或者是定义数组时使用type类的子类

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //定义Object数组,为其静态赋值String类型的字符串
     Object[] oj = new String[]{"陪伴是","最长情","的告白"};
     //循环输出每个变量的内容
     for(Object s : oj){
         System.out.println("s = " + s);
     }
    }
}
s = 陪伴是
s = 最长情
s = 的告白

Process finished with exit code 0
  • 动态初始化的时候每个类型都有默认的初始值,如下图:

在这里插入图片描述

  • 一般使用定义初始化一步到位的模式:
    • int [] prices = new int [5];
    • int [] prices = new int[]{1,2,23,4,5};
使用数组

一般使用数组名称加一个方括号([])来访问数组,方括号里面包含一个整型数值,那个数值就是数组下标索引(从0开始),这样使用数组的某个元素就相当于使用某个变量了

实例
/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //定义一个数组
        int[] a = new int[]{1,2,3,4,5,6,7,8};
        //a[1]的值等于2,因为数组的下标是从0开始的
        System.out.println("a[1] = " + a[1]);
    }
}
  • 记住常见的数组使用错误

    • java.lang.ArrayIndexOutOfBoundsException: N(数组访问下标越界,这个N就是你试图访问越界的下标值)
  • 每个数组都有默认的length属性,可以返回数组的长度

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //定义一个数组
        int[] a = new int[]{1,2,3,4,5,6,7,8};
        //输出a数组的长度为8
        System.out.println(a.length);
    }
}

即可以循环访问数组元素(循环访问数组的方法之一)

/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //定义一个数组
        int[] a = new int[]{1,2,3,4,5,6,7,8};
        //循环访问元素,输出每个元素的值
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
    }
}
foreach循环

定义:Java5之后提供的一种更简单的循环,可用于遍历数组和集合(在后面),优点的无需下标和长度就可以自动遍历数组和集合的每个元素

语法格式
for(type variableName : array){
    //这里就可以自动迭代访问array里面的每个元素了
}
  • variableName是一个形参名,foreach循环自动将数组元素赋值给该变量
  • 这个只能遍历数组,不能修改数组元素的值,variableName只是一个临时变量,修改没有任何意义
使用实例
/**
 * @author wangxin
 * @create 2020-07-24 9:08
 */
public class Main {
    public static void main(String[] args) {
        //定义一个数组
        int[] a = new int[]{1,2,3,4,5,6,7,8};
        //循环访问元素,输出每个元素的值
        for (int temp : a) {
            System.out.println(temp);
        }
    }
}
堆栈存储数组内存分析

Java中具有堆(Heap)内存和栈(Stack)内存,他们都是拿来存储变量的,但是存储的方式不一样,具体见如下:

  • 首先两个概念,堆内存和栈内存,如果不清楚可以这样理解,两个都是底层用于存放变量的的“容器”,它们如图所示:

在这里插入图片描述

  • 栈(Stack):

    • 用于存储基本类型变量(char,int,long)、引用类型变量(切记只是存储它的“指针”,并不是真正的实体数据)和方法函数
    • 存储的基本类型变量和对象的引用变量都是在栈内存中分配
    • 栈的优点是:存取速度比要快,仅次于寄存器,栈数据可以共享
    • 栈的缺点是:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
    • 当超过变量的作用域后,Java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。
  • 堆(Heap):

    • 用于存储实例对象(new出来的对象)和数组的实体数据
    • 在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。
    • 栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,引用变量相当于为数组或者对象起的一个别名,或者代号。
    • 引用变量是普通变量,定义时在栈中分配内存,极其类似于C语言指针
  • 一旦数组定义后,数组在堆内存中是不可以改变的!!

  • 一维数组的内存图如下:

在这里插入图片描述

多维数组

Java从实质上讲,没有多维数组,多维数组只是引用多个数据

图解

在这里插入图片描述

  • 这是一个典型的二维数组,一个指针指向多个堆内存,这样就可以表示一个二维数组了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值