疯狂Java讲义 第三章 Java数据类型和运算符

jefxff 153,578 2020-03-10

1. 注释

1.1 为什么注释

  1. 增加代码的阅读性及思路;
  2. 可读性第一,效率第二;
  3. 规范源代码。

1.2 注释分类

  1. 单行注释:使用双斜线(//)放在需要注释的内容之前;

  2. 多行注释:使用"/*"和"*/"将需要注释的内容包含起来;

  3. 文档注释:用于生成API的文档用来说明类、方法、成员变量的功能;使用"/**"开始,以"*/"结束,中间部分全都是文档注释,会被提取到API文档中。

    // 例:这是单行注释
        System.out.print("hello World");
        /*
         * 这是多行注释,
         * 我想学会Java和Python
         */

    //例:(书中43页示例文档注释)
        package lee;
        /**
          * Description:
          * <br>网站:<a href="http://www.crazyit.org">疯狂Java联盟</a>
          * <br>Copyright (C),2001-2015, Yeeku.H.Lee
          * <br>This program is protected by copyright laws.
          * <br>Program Name:
          * <br>Date:
          * @author Yeeku.H.Lee kongyeeku@163.com
          * @version 1.0
          */
            
        public class javadocTest
        {
            /**
                * 简单测试成员变量
                */
            protected String name;
            /**
                * 主方法,程序的入口
                */
            public static void main(String[] args)
            {
                System.out.printin("Hello World!");
            } 
        }   
        package yeeku;
        /**
            * Description:
            * <br>网站:<a href="http://www.crazyit.org">疯狂Java联盟</a>
            * <br>Copyright (C),2001-2015, Yeeku.H.Lee
            * <br>This program is protected by copyright laws.
            * <br>Program Name:
            * <br>Date:
            * @author Yeeku.H.Lee kongyeeku@163.com
            * @author Yeeku.H.Lee kongyeeku@163.com
            * @version 1.0
            */
            
        public class Test
        {
            /**
                * 简单测试成员变量
                */
            public int age;
            /**
                * Test 类的测试构造器
                */
            public Test()
            {
            } 
        }   

1.3 使用 javadoc 工具

  1. 用法: javadoc 选项 Java源文件|包 (javadoc 工具用于提取程序中的文档注释来生成API文档)

  2. javadoc 命令的常用选项:

    • -d :指定一个路径,用于将生成的API文档放到指定目录下 -d 后面的名字就是生成的目录名
    • -windowtitle :指定一个字符串,设置API文档的浏览器窗口标题
    • -doctitle :指定一个HTML格式的文本,用于指定概述页面的标题
    • -header :指定一个HTML格式文本,包含每个页面的页眉
  3. javadoc用法实例:

    • 将上述两个类分别保存为JavadocTest.java 和 Test.java, 并存放在指定的目录
    • 在*.Java程序所在的目录进入CMD命令, 执行下面的命令:
      javadoc -d apidoc -windowtitle 测试 -doctitle 学习 javadoc工具的测试API文档 -header 我的类 *Test.java
  4. javadoc 常用标记:

    • @author: 指定Java程序的作者

    • @version: 指定源程序的版本

    • @deprecated:不推荐使用的方法

    • @param: 方法的参数说明信息

    • @return: 方法的返回值说明信息

    • @see: "参见", 用于指定交叉参考的内容

    • @exception: 抛出异常的类型

    • @throws: 抛出的异常, 和@exception同义

    • 可以出现在类或者接口文档注释的有: @see, @deprecated, @author, @version

    • 可以出现在方法或构造器文档注释中的有: @see, @deprecated, @param, @return, @throws,@exception

    • 可以出现在成员变量的文档注释的有: @see, @deprecated


2. 标识符和关键字

2.1 分隔符

分号(;)、花括号({})、方括号([])、圆括号(())、空格 、圆点(.)都具有特殊的分割作用,被统称之为分隔符

分号(;)
  1. Java语言里对语句的分隔不使用回车,而是采用(;)作为语句的分隔,因此每个java语句必须使用分号作为结尾
  2. Java程序允许一行书写多个语句,每个语句之间以分号隔开即可;一条语句也可以跨多行,只要在最后结束的地方使用分号结束即可
  3. 注意:一个字符串、变量名不能跨越多行。也尽量避免一行书写多条语句
    int age = 25; String name = "李刚";
    // 下面的代码是错误示范, 不要这样子写
    String hello = "你好!" + 
        "Java";
花括号({})
  1. 作用:
    定义一个代码块,一个代码块就是指“{” 和 “}” 所包含的代码,代码块在逻辑上是一个整体。
  2. 需要注意的点:
    • 花括号都是成对出现的;
    • Java语言,类定义部分必须放在一个代码块里面,方法体部分也必须放在一个代码块里面;
    • 条件语句中的条件执行体和循环语句中的循环体通常也放在代码块里。
方括号([])
  1. 方括号的主要作用是用于访问数组元素,方括号通常紧跟数组变量名,而方括号里指定希望访问的数组元素的索引。
    // 下面代码试图为名为a的数组的第四个元素赋值
	a[3] = 3;
圆括号(())
  1. 定义方法时必须使用圆括号来包含所有的形参声明;
  2. 调用方法时必须使用圆括号来传入实参值;
  3. 将表达式中某个部分括成一个整体,保证这个部分优先计算;
  4. 作为强制类型转换的运算符
  5. 等等等等.......
空格( )
  1. Java语言的空格包含空格符(Space),制表符(Tab)和回车(Enter)等,使用空格来合理缩进,提高可读性。
圆点(.)
  1. 圆点通常用作类/对象和它的成员(包括成员变量、方法和内部类)之间的分隔符,表明调用某个类或实例的指定成员。

2.2 标识符规则

  1. 规则
    标识符就是用于给程序中变量、类、方法命名的符号。Java语言的标识符必须以字母、下划线(_)、美元符($)开头。Java语言区分大小写;
  2. 注意规则:
    • 标识符可以由字母、数字、下划线和美元符组成,其中能以数字开头;
    • 标识符不能是Java关键字和保留字,但可以包含关键字和保留字;
    • 标识符不能包含空格;
    • 标识符只能包含美元符($),不能包含@,#等其他特殊字符,(但是尽量不药用$符号开头)

2.3 Java 关键字

  1. Java语言中具有一些特殊用途的单词被称之为关键字(keyword),定义标识符的时候,不可以让关键字和标识符相同;Java的所有关键字都是小写。
  2. Java 50个关键字:
    abstract  continue  for  new  switch  assert  default  if  package 
    synchronized  boolean  do  goto  private  this  break  double  
    implements  protected  throw  byte  else  import  public  throws
    case  enum  instanceof  return  transient  catch  extends  int  
    short  try  char  final  interface  static  void  class  finally  
    long  strictfp  volatile  const  float  native  super  while  

3. 数据类型分类

3.1 Java属于强类型的含义:

  1. 所有的变量必须先声明、后使用;
  2. 指定类型的变量只能接受类型与之匹配的值。
  3. Java声明变量的语法:
    type varName[ = 初始值];
  4. 定义变量至少需要指定变量类型和变量名两部分。

3.2 Java语言支持的数据类型:

  1. 基本类型(Primitive Type):包括boolean类型和数值类型(数值类型包括整数类型(byte, short, int, long, char)和浮点类型(float, double))
    注意: char代表字符型, 实际上字符型也是一种整数类型, 相当于无符号整数类型.
  2. 引用类型(Reference Type):类, 接口, 数组, null类型

4. 基本数据类型

				    |--整数类型  |--1个字节  : byte    8位
				    |		    |--2个字节  : short  16位
				    |		    |--4个字节  : int    32位
				    |		    |--8个字节  : long   64位
	                |
	Java基本数据类型 |--字符类型--2个字节  : char	16位Unicode字符
				    |
				    |--浮点类型 |--4个字节 : float  32位
				    |		    |--8个字节 : double 64位
                    |
                    |--布尔类型 : boolean

4.1 整形

分类:
  1. byte 一个byte类型整数在内存里占8位
  2. short 一个short类型整数在内存里占16位
  3. int 一个int类型整数在内存里占32位
  4. long 一个long类型整数在内存里占64位
整形注意问题:
  1. int是最常用的整数类型,因此,直接给出一个整数值默认就是int类型, 即在内存中占32位。
  2. 较小的值(byte或者short范围内)系统会自动把这个整数值当成byte或者short类型来处理;
  3. 如果要将巨大的整数值(超出int范围)当做long类型来处理,就要在这个整数值后面增加L作为后缀。
Java中整数的4中表示方式:
  1. 十进制: 就是日常生活中应用的十进制数字 例如: 123, 9527
  2. 二进制: 二进制的整数以 0b 或者 0B 开头 例如: 0b10010, 0B00000001
  3. 八进制: 八进制的整数以 0 开头 例如: 04
  4. 十六进制: 十六进制的整数以 0x 或者 0X 开头, 其中10~15分别以 a~f来表示 例如: 0xa125
二进制源码, 补码, 反码:
  1. 补码计算: 正数的补码和源码完全相同, 负数的补码是其反码加1, 反码是对源码按位取反, 只是最高位(符号位)保持不变.
  2. 正数: 源码 ---等于---> 反码 ---等于---> 补码
  3. 负数: 源码 ---符号位不变, 其他位取反---> 反码 ---加1---> 补码
  4. 负数在计算机中是以补码的形式存在

4.2 字符型

含义:
  1. 字符型通常用于表示单个的字符, 字符型的值必须使用单引号(')括起来. Java语言使用16位的Unicode字符集作为编码的方式.
  2. 字符集: 就是给所有字符编号的组成总和.
表示形式:
  1. 直接通过单个字符来指定字符型值, 'A', '9', '0' 等等
  2. 通过转义字符表示特殊字符型值, '\n' 换行符, '\t' 制表符, '\b' 退格符, '\r' 回车符, '"' 双引号, ''' 单引号, '\' 反斜线 等等
  3. 直接通过 Unicode 值来表示字符型值, 格式: '\uXXXX' 其中XXXX代表一个十六进制的整数
特殊的char类型:
  1. char类型的值可以直接作为整型值来使用. char类型的变量, 值完全可以参与加, 减, 乘, 除等数学运算,也可以比较大小---实际上是用该字符对应的编码参与运算.
字符串:
  1. Java没有提供表示字符串的基本数据类型, 而是通过String类来表示字符串, 字符串需要使用双引号("")来括起来.
  2. char类型使用单引号括起来, 字符串使用双引号来括起来.

4.3 浮点型

类型:
  1. 单精度浮点数 (4字节 32位) float : 第一位是符号位, 接下来8位表示指数, 再接下来23位表示尾数;
  2. 双精度浮点数 (8字节 64位) double : 第一位是符号位, 接下来11位表示指数, 再接下来52位表示尾数.
浮点型注意问题:
  1. Java中 只有浮点类型的数值才可以使用科学计数法
  2. java语言默认的浮点类型是 double 类型, 如果想将一个浮点值当成float处理, 应在浮点类型的值后面紧跟一个f或者F
  3. 三个特殊的浮点数值: 正无穷大, 负无穷大, 非数 用于表示溢出或者出错. 所有的正无穷数值相等,所有的负无穷数值相等, 而NaN 不与任何值相等, 包括他自己.
  4. 正无穷大: 用正整数除以0, 用Double 或Float类的POSITIVE_INFINITY表示;
  5. 负无穷大: 用负数除以0, 用Double 或Float类的NEGATIVE_INFINITY表示;
  6. 非数: 用0.0 除以 0.0 或者对一个负数开方, 用Double 或Float类的NaA表示.
  7. 只有浮点数除以 0 才可以得到正无穷大或者负无穷大, 因为 Java 语言会自动把和夫ID安书运算的0(整数)当成0.0(浮点数)处理

4.4 布尔型

含义:
  1. 布尔型只有一个boolean类型, 用于表示逻辑上的"真"或者"假". Java中boolean类型的数值只能是true或者false, 不能用0或者非0来代表, 其他基本类型的的值也不能转换为boolean类型
注意:
  1. 字符串的 "true"和"false"不会直接转换成boolean类型, 但如果使用一个boolean类型的值和字符串进行连接运算, 则boolean类型的值将会自动转换成字符串.
  2. boolean类型的值或变量主要用来做旗标进行如下流程控制:if 条件控制语句; while 循环控制语句; do 循环控制语句; for 循环控制语句

5. 基本类型的类型转换

Java语言有7种数值类型之间的相互转换, 有两种转换的方式: 自动类型转换和强制类型转换

5.1 自动类型转换:

自动类型转换含义:
  1. 把某种基本类型的值直接赋给另外一种基本类型的变量, 则这种方式叫做自动类型转换.
自动类型转换注意问题:
  1. 把一个表数范围小的数值或变量直接赋给另外一个表数范围大的变量时, 系统将可以进行自动类型转换;
    否则就需要强制转换.
        //例如这个流程图:(流程中箭头左边的数值类型可以自动转换为箭头右边的数值类型)
                    char-->
                            \
        byte --> short --> int --> long --> float --> double
  1. 当把任何基本类型的值和字符串值进行连接运算的时候, 基本类型的值将自动类型转换为字符串类型,
    虽然字符串类型不是基本类型, 而是引用类型.
  2. 和学JavaScript 的时候一样, 数值加数值加字符, 会先计算数值, 但是字符加数值加数值, 会将数值
    当作字符串来进行运算
    例子:
        // 1. 自动类型转换1 整数
        int a = 6;
        // int类型可以自动转换为float类型
        float f = a;
        System.out.println(f);  // out: 6.0
        // 定义一个byte类型整数变量
        byte b = 9;
        // 下面代码将出错, byte类型不能自动转换为char类型
        char c = b;
        // byte 类型可以自动转换为double类型
        double d = b;
        System.out.println(d);  // out: 9.0
        
        // 2. 自动类型转换2 其他类型
        // 一个基本类型的值和字符串进行连接运算的时候, 基本类型的值自动转换为字符串
        String str2 = 3.5f + "";
        System.out.println(str2);   // out: 3.5
        System.out.println(3 + 4 + " Hello")  //输出: 7 Hello
        System.out.println("Hello " + 3 + 4)  //输出: Hello 34

5.2 强制类型转换:

强制类型转换含义:
  1. 如果想将上面流程箭头右边的类型转换为左边的类型, 则必须进行强制类型转换. 当进行强制类型转化的时候,类似于把一个大瓶子里面的水倒入一个小瓶子, 如果大瓶子里面的水不多还好, 但是如果大瓶子里面的水很多,将会溢出, 从而造成数据丢失. 这种转换也称之为" 缩小转换(Narrow Conversion)"

  2. 语法格式:

        (targetType)value  //强制类型转换的运算符是圆括号(), 结合下面的例子理解
  1. 例子:
        // 1. 强制类型转换的例子
        public class NarrowConversion
        {
            public static void main(String[] args)
            {
                int iValue = 233;
                // 将32位的int类型转换为8位的byte, 发生了溢出, 
                byte bValue = (byte)iValue;
                System.out.println(bValue);  // out: -23
                
                double dvalue = 3.98;
                // 把一个浮点数强制转换为整数时, Java将直接截断浮点数的小数部分, 只取整数部分.
                int tol = (int)dValue; 
                Syetem.out.println(tol); // out: 3
            }
        }
        
        // 2. 生成一个6位的随机字符串
        public class RandomStr
        {
            public static void main(String[] args)
            {
                // 定义一个空字符串
                String result = "";
                // 进行6次循环 , 和刚学的js循环条件的代码一某一样
                for (int i = 0; i < 6; i++)
                {
                    // 生成一个97~122之间的 int整数类型
                    int intVal = (int)(Math.random() * 26 + 97);
                    // 将 intValue 强制转换为 char 类型后连接到 result 的后面
                    result = result + (char)intVal;
                }
                输出6位的随机字符串
                System.out.println(result);
            }
        }
        
        // 3. 浮点型转换的例子
        float a = 5.6;  
        // 上面这句代码是错误的, 因为浮点数默认是double类型的, 要强制转换成浮点型如下:
        float b = (float)5.6;

        // 4. 使用Integer方法将一个字符串转换为int类型
        String a = "45";
        int iValue = Integer.parseInt(a);
        Syetem.out.println(iValue);  // out: 45

5.3 特殊说明

  1. 通常情况下, 字符串不能直接转换为基本类型, 但通过基本类型对应的 包装类 则可以实现把字符串转换成基本类型Java有8种基本类型都有对应的包装类: boolean 对应 Boolean, byte对应Byte, short对应Short,int对应Integer, long对应Long, char对应Character, float对应Float, double对应Double, 8个包装类都提供一个 parseXxx(String str) 静态方法将字符串转换为基本类型

5.4 表达式类型的自动提升

提升规则:
  1. 所有的byte类型, short类型和char类型将被提升到 int类型
  2. 整个算术表法式的数据类型自动提升到与表达式中最高等级操作数同样的类型
  3. 例子:
        // 1. (错误转换: 高等级--->低等级)
        // 定义一个short类型变量
        short svalue = 5;
        // 表达式中sValue将自动提升到int类型, 则右边的表法师类型为int
        // 将一个int类型的值赋给short类型的变量将发生错误
        sValue = sValue - 2;   
        System.out.println(sValue);  // out: 错误: 不兼容的类型: 从int转换到short可能会有损失
    
        // 如果想强制转换, 就是用强类型转换
        short sValue = 5;
        sValue = (short)(sValue - 2);   
        System.out.println(sValue);   // out: 3 

        // 2.(正确的自动提升, 表达式的类型将严格保持和表达式中最高等级操作数相同的类型)
        /*
         * 再熟悉一下流程图:
         *         char-->
         *                 \
         * byte --> short --> int --> long --> float --> double
         */
         
        // 示例代码1:     
        byte b = 40;
        char c = 'a';
        int i = 23;
        double d = 0.314;
        // 右边表达式最高等级操作数为d (double 类型)
        // 则右边表达式的类型为double类型, 故赋给一个double类型变量
        double result = b + c + i + d;
        System.out.println(result);  // out: 160.314

        // 示例代码2:
        int val = 3;
        // 右边表达式中两个操作数都是int类型, 故右边表达式的类型为int
        // 虽然 23/3 不能除尽, 但依然得到一个int类型的整数
        int intResult = 23 / val;
        System.out.println(intResult); // out: 7
        // 说明: 上述的代码表明:当两个整数相除的时,如果不能整除,得到的结果将会是把小数部分截断取得整数部分.
            
                
        // 示例代码3:
        // 输出字符串Hello!a7
        System.out.println("Hello!" + 'a' + 7);
        // 输出字符串 104Hello!
        System.out.println('a' + 7 + "Hello!");
        // 说明: 
        //     1. 对于一个表达式 "Hello!" + 'a' + 7 , 先进行"Hello!" + 'a'运算, 把'a'转换成字符串,
        //      拼接成字符串 Hello!a, 接着进行 "Hello!a" + 7 运算, 这也是一个字符串运算, 得到的结果 
        //      是 Hello!a7
        //     2. 第二个表达式, 先进行 'a' + 7 运算, 其中'a' 自动提升到int类型, 变成 a 对应的ASCII
        //      值:97, 从97 + 7 将得到104, 然后进行 104 + "Hello!"运算, 104会自动转换成字符串,将变成
        //      两个字符串的拼接运算, 从而得到的是 104Hello! 

6. 直接量的类型

6.1 含义:

  1. 直接量是指在程序中通过源代码直接给出的值, 例如: int a = 5; 表示: 为变量 a 所分配的初始值5就是一个直接量.
  2. 说明:并不是所有的数据类型都可以直接指定直接量, 能指定直接量的通常只有三种类型: 基本类型, 字符串, 和 null 类型.

6.2 8种类型的直接量:

  1. int 类型的直接量: 在程序中直接给出的整数数值, 可分为二进制(0b或0B), 十进制, 八进制(以 0 开头)
    和十六进制(0x或0X);
  2. long 类型的直接量: 在整形数值后添加l或者L后变成long类型的直接量. 例如: 3L, 0x12L等(默认加L)
  3. float 类型的直接量: 在一个浮点数后添加f或F就变成float类型的直接量, 可以是标准小数, 或者科学
    计数法形式. 例如: 5.34F, 3.14E5f 等等
  4. double 类型的直接量: 直接给出一个标准小数形式或科学计数形式的浮点数就是 double 类型的直接量,
    例如: 5.34, 3.14E5 等等
  5. boolean 类型的直接量: boolean 类型的直接量只有 true 和 false 两种
  6. char 类型的直接量: char类型的直接量有三种类型, 分别是用双引号括起来的字符, 转义字符和 Unicode
    值表示的字符, 例如: 'a', '\n', '\u0061'
  7. String 类型的直接量: 一个用双引号括起来的字符序列就是 String 类型的直接量.
  8. null 类型的直接量: 这个类型的直接量只有 null 一个值. 且这个值可以赋给任何类型的变量, 用以表示
    这个引用类型变量中保存的地址为空, 即还未指向任何有效的对象

6.3 直接量的赋值

        // 直接量的赋值直接看例子:
            int a = 5;
            char c = 'a';
            boolean b = true;
            float d = 5.12f;
            double d = 4.12;
            String author = "jeff";
            String book = "我正在写JAVA!";

6.4 注意:

  1. Java还支持数值间的自动类型转换, 因此允许把一个数值直接量直接赋给另外一个类型的变量, 这种赋值必须是上面箭头左边的类型可以直接付给箭头右边, 但是箭头右边的值要赋给箭头左边就要使用强制类型转换, (可能丢数据)
  2. String 类型的直接量不能赋给其他类型的变量, boolean类型的直接量不能赋给其他任何类型的变量只能赋给boolean类型的变量
  3. 当一个字符串由多个字符串常量连接而成的时候, 在编译期就被解析成一个字符串常量.

7. 运算符

  1. 含义:
    运算符是一种特殊的符号, 用以表示数据的运算, 赋值和比较等, Java语言使用的运算符将一个或多个操作
    数连缀成执行性语句, 用以实现特定功能.
  2. 分类:
    算数运算符, 赋值运算符, 比较运算符, 逻辑运算符, 位运算符, 类型相关运算符

7.1 算符运算符

Java有7个基本算数运算符:

+ : 加法运算符
    //例子:基本加法
        double a = 5.2;
        double b = 3.1;
        double sum = a + b;
        System.out.println(sum);  // out: sum = 8.3 
    // 也可以作为字符串的链接运算符
        String str1 = "hello";
        String str2 = "jeff";
        String str3 = str1 + str2;
        System.out.println(sum);
- : 减法运算符
    //例子:
        double a = 5.2;
        double b = 3.1;
        double sub = a - b;
        System.out.println(sub);  // out: sub = 2.1 
* : 乘法运算符
    //例子:
        double a = 5.2;
        double b = 3.1;
        double multuply = a * b;
        System.out.println(multuply);  // out: multuply = 16.12 
/ : 除法运算符
  1. 除法运算符有些特殊, 如果除法运算符的两个操作数都是整数类型, 则计算的结果也是整数,就是将自然数除法的结果截取整数部分, 例如: 19/4的结果是4, 而不是5. 并且除法运算符的两操作数都是整数类型, 则除数不可以为0, 否则会引发除以零的异常;
  2. 两个操作数有一个浮点数, 或者两个浮点数, 则计算结果也是浮点数, 这个结果就是自然除法的结果, 而且此时的允许除数为0, 或者0.0 得到的结果是正无穷大或者负无穷大
    //例子:
        public class DivTest
        {
            public static void main(String[] args)
            {
                double a = 5.2;
                double b = 3.1;
                double div = a / b;
                System.out.println(div);  // out: div = 1.6774193548387097
                
                // 输出正无穷大: Infinity
                System.out.println("5除以0.0的结果是:" + 5 / 0.0);
                
                // 输出正无穷大: -Infinity
                System.out.println("-5除以0.0的结果是:" + -5 / 0.0);
                
                // 下面代码将出现异常
                // java.lang.ArithemticException: / by zero
                System.out.println("-5除以0的结果是:" + -5 / 0);  
                
            }
        }                    
% : 求余运算符
  1. 两个整数相除, 首先不允许除数为0(会引发异常), 结果是整除后剩下的值就是余数;
  2. 有一个浮点数或者两个浮点数相处, 允许第二个数为 0 或者 0.0, 这样的得到的求余运算结果是非数: NaN;
  3. 0 或者 0.0 对零以外的任何数求余都将的得到0 或者 0.0
    //例子: 
        public class DivTest
        {
            public static void main(String[] args)
            {
                double a = 5.2;
                double b = 3.1;
                double mod = a % b;
                System.out.println(mod);  // out: mod = 2.1 
                                            
                System.out.println("5对0.0求余的结果是:" + 5 % 0.0);  // out: 输出非数: NaN
                System.out.println("-5对0.0求余的结果是:" + -5 % 0.0);  // out: 输出非数: NaN
                System.out.println("0对5.0求余的结果是:" + 0 % 5.0);  // out: 输出非数: 0.0
                System.out.println("0对0.0求余的结果是:" + 0 % 0.0);  // out: 输出非数: NaN
                // 下面的代码将出现异常: java.lang.ArithemticException: / by zero
                System.out.println("-5对0求余的结果是:" + -5 % 0); 
            }
        } 
++ : 自加
  1. 自加是单目运算, 只能操作一个操作数;
  2. 自加运算符只能操作单个数值型(整型, 浮点型都可以)的变量, 不能操作常量或者表达式;
  3. 操作符在左边表示: 先把操作数加1, 然后才把操作数放入表达式中运算;
  4. 操作符在右边表示: 先把操作数放入表达式中运算, 然后才把操作数加1;
    //例子:
        // 运算符在左边, ++a , 表示先自增, 再执行算术运算
        int a = 5;
        // 让a先自增, 再执行算术运算
        int b = ++a + 6;
        System.out.println(a + "\n" + b); out: a = 6, b = 12
        
        // 运算符在右边, a++ , 表示先执行算术运算, 再自增
        int a = 5;
        // 让a先自增, 再执行算术运算
        int b = a++ + 6;
        System.out.println(a + "\n" + b); out: a = 6, b = 11 
-- : 自减
  1. 也是单目运算,自减和自增的用法基本相似, 只是将操作数的值减1;
  2. 自加和自减只能用于操作变量, 不能用于操作数值直接量, 常量或表达式, 例如: 5++, --4等写法都是错误的.
其他如乘法, 开方, 求负等运算:
    //例子:
        public class MathTest
        {
            public static void main(String[] args)
            {
                double a = 3.2; // 定义变量 a 为3.2
                // 求 a 的 5次方, 并将结果赋值给b
                double b = Math.pow(a, 5);
                System.out.println(b);
                
                // 求 a 的平方根, 并将结果赋值给c                         
                double c = Math.sqrt(a);
                System.out.println(c);
                
                // 计算随机数, 返回0~1之间的伪随机数
                double d = Math.random();
                
                // 求1.57的sin函数值, 1.57被当成弧度数
                double e = Math.sin(1.57);
                System.out.println(e);  // 输出接近1
                
                // 定义double变量x, 其值为 -5.0
                double x = -5.0;
                x = -x;  // 将x求负, 其值变成 5.0 
                
            }
        } 

7.2 赋值运算符

赋值运算符说明:
  1. 赋值运算符用于为变量指定变量值, 使用赋值运算符将一个直接量赋值给变量, 也可以将一个变量赋值给另外一个变量.
  2. 赋值表达式是有值的, 赋值表达式的值就是右边被赋的值, 例如: String str2 = str 表达式的值就是 str.
  3. 赋值运算符支持连续赋值, 通过使用多个赋值运算符, 可以一次为个变量赋值.
  4. 赋值运算符还可以将表达式的值赋给变量.
  5. 例子:
        string str = "Java";  // 为变量str赋值 Java
        double pi = 3.14;  // 为变量pi赋值 3.14
        boolean visited = true;  // 为变量visited赋值 true 
        
        // 为多个变量赋值
        int a;
        int b;
        int c;
        a = b = c = 7;
        
        // 将表达式的值赋给变量
        double d1 = 12.34;
        double d2 = d1 + 5;  // 将表达式的值赋给d2
赋值运算符扩展:
  1. 说明: 记住要使用扩展赋值运算符, 因为不仅具有更好的性能, 而且还可以让代码更健壮
    +=   : 对于x += y,   即对应于 x = x + y
    -=   : 对于x -= y,   即对应于 x = x - y
    *=   : 对于x *= y,   即对应于 x = x * y
    /=   : 对于x /= y,   即对应于 x = x / y
    %=   : 对于x %= y,   即对应于 x = x % y
    &=   : 对于x &= y,   即对应于 x = x & y
    |=   : 对于x |= y,   即对应于 x = x | y
    ^=   : 对于x ^= y,   即对应于 x = x ^ y
    <<=  : 对于x <<= y,  即对应于 x = x << y
    >>=  : 对于x >>= y,  即对应于 x = x >> y
    >>>= : 对于x >>>= y, 即对应于 x = x >>> y

7.3 位运算符

  1. 位运算符只能操作整数类型的变量或值(实际操作的都是二进制的数据)
& : 按位与
  1. 当两位同时为1时才返回1
    例子:
        System.out.println(5 & 9);   // out: 1
        // 程序执行过程: 5的二进制码是00000101(省略前面的24个0), 
        //   而9的二进制码是00001001(省略前面的24个0),两位相同的时候返回1, 否则返回0

    如图:        00000101
                &00001001
                ---------
                 00000001
| : 按位或
  1. 只要有一位为1即可返回1
    例子:
        System.out.println(5 | 9);   // out: 13
        //程序执行过程: 5的二进制码是00000101(省略前面的24个0), 
        //  而9的二进制码是00001001(省略前的24个0),两位只要有一位为1即返回1, 否则返回0
        如图:    00000101
                |00001001
                ---------
                 00001101
            00001101b = 2**3*1 + 2**2*1 + 2**1*0 + 2**0*1 = 8 + 4 + 1 = 13
~ : 按位非
  1. 单目运算符, 将操作数在计算机底层的二进制码按位(包括符号位)取反
    例子:
        System.out.println(~-5);   // out: 4
        // 执行过程: 由于负数在计算机中以补码的形式存储, 所以 ~-5是对-5的补码进行按位取反的操作,
        // -5的原码: 10000000000000000000000000000101
        // -5的反码: 11111111111111111111111111111010  // 源码除符号位外取反得到反码
        // -5的补码: 11111111111111111111111111111011  // 反码加1得到补码
                    --------------------------------
                ~-5: 00000000000000000000000000000100  // 对-5的补码按位取反得到的是正数
                0100b = 2**2*1 = 4
^ : 按位异或
  1. 当两位相同时返回0, 不同时返回1
    例子: 
        System.out.println(5^9);   // out: 12
        // 执行过程: 二进制的两位相同时返回0, 不同时返回1
            5 : 00000000000000000000000000000101
            9 : 00000000000000000000000000001001
               ------------------
         5^9 : 00000000000000000000000000001100 
            001100b = 2**3*1 + 2**2*1 = 8 + 4 = 12 
<< : 左移运算符
  1. 将操作数的二进制码整体左移指定位数, 左移后右边的空出来的位以0补充, 左边移出去的位截掉
    例子:
        System.out.println(5 << 2);   // out: 20
        System.out.println(-5 << 2);   // out: -20
        -5的计算过程: 
                -5 :    11111111111111111111111111111011
           -5 << 2 : 11|11111111111111111111111111101100
>> : 右移运算符
  1. 把第一个数的二进制码右移指定位数后, 左边空出来的位以原来的符号位填充, 即第一个操作数原来是正数, 则左边补0; 如果操作数是负数, 左边补1.
    例子:
        System.out.println(-5 >> 2);  // out: -2
>>> : 无符号右移运算符

1.** 将第一个操作数的二进制码右移指定位数后, 左边空出来的位总是以 0 填充**

    例子: 
        System.out.println(-5 >>> 2);  // out: 1073741822
进行位运算遵循的规则:
  1. 对于低于 int 类型(byte, short 和 char) 的操作数总是先自动类型转换为int类型后再移位;
  2. 对于int类型的整数移位 a>>b, 当b>32时, 系统先用b 对 32求余(因为int类型只有32位), 得到的结果才是真正移位的位数;例子: a>>33 和 a>>1的结果完全一样, 而a>>32的结果和a相同
  3. 对于long类型的整数移位a>>b, 当b>64时, 总是先用b对64求余(因为long类型是64位), 得到的结果才
    是真正移位的位数;
  4. 注意: 当进行位运算的时, 只要被移位的二进制码没有发生有效的数字丢失(对于整数而言, 通常指被移出的位全部是0), 左移n位就相当于乘以2的n次方, 右移n位相当于除以2的n次方, 移位运算不是改变操作数本身, 只是得到了一个新的运算结果, 而原来的操作数本身是不会改变的.

7.4 比较运算符

  1. 含义: 比较运算符用于判断两个变量或者常量的大小, 比较运算符的结果是一个布尔值(true或者false)

  2. > : 大于, 只支持左右两边操作数是数值型, 如果前面变量的值大于后面变量的值, 则返回true, 否则返回false

  3. >= : 大于等于, 只支持左右两边操作数是数值型, 如果前面变量的值大于等于后面变量的值, 则返回true,否则返回false

  4. < : 小于, 只支持左右两边操作数是数值型, 如果前面变量的值小于后面变量的值, 则返回true, 否则返回false

  5. <= : 小于等于, 只支持左右两边操作数是数值型, 如果前面变量的值小于等于后面变量的值, 则返回true,否则返回false

  6. == : 等于, 如果进行比较的两个操作数都是数值类型, 即使他们的数据类型不同, 只要他们的值相等,也都将返回true, 例如: 97 == 'a'; 返回true, 5.0 == 5 也返回true; 如果两个操作数都是引用类型, 那么只有当两个引用变量的类型具有父子关系时才可以比较, 而且这两个引用必须指向同一个对象才会返回true,Java也支持boolean类型的值进行比较, 例如: true == false , 将返回false.

  7. != : 不等于, 如果进行比较的两个操作数都是数值类型, 无论他们的数据类型是否相同, 只要他们的值不相等,也都将返回true, 如果两个操作数都是引用类型, 只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就返回true

    //例子: 
        public class ComparableOperatorTest
        {
            public static void main(String[] args)
            {
                System.out.println("5是否大于4.0: " + (5 > 4.0));   // out: true
                System.out.println("5和5.0是否相等: " + (5==5.0));   // out: true
                System.out.println("97和a是否相等: " + ( 97 == 'a'));   // out: true
                System.out.println("true 和 false 是否相等: " + (true == false));  // out: false
                
                // 创建2个ComparableOperatorTest对象, 分别赋给t1 和 t2 两个引用
                ComparableOperatorTest t1 = new ComparableOperatorTest();
                ComparableOperatorTest t2 = new ComparableOperatorTest();
                // t1 和 t2 是同一个类的两个实例引用, 所以可以比较
                // 但 t1 和 t2 引用不同的对象, 所以返回false
                System.out.println("t1 和 t2是否相等: " + (t1 == t2));  // out: false
                
                // 直接将t1的值赋给 t3, 即让t3指向t1指向的对象
                ComparableOperatorTest t3 = t1 
                // t1 和 t3 指向同一个对象, 所以返回true
                System.out.println("t1 和 t3是否相等: " + (t1 == t3));   // out: true
            }
        }

7.5 逻辑运算符

  1. 含义: Java逻辑运算符有6个, 主要用于操作两个布尔型的变量或者常量.

  2. && : 与, 前后两个操作数必须都是 true 才返回 true, 否则返回false.

        //例子:
            // 5>3 返回 true, '6'转换为整数为54, '6'>10返回true, 求与后返回true
            System.out.println(5>3 && '6'>10);   // out: true
  1. & : 不短路与, 作用与&&相同, 但不会短路

  2. || : 或, 只要两个操作数有一个是true, 就可以返回true, 否则返回false

        //例子:
            System.out.println(4>=5 || 'c'>"a");   // out: true 
  1. | : 不短路或, 作用与|| 相同, 但不会短路

  2. ! : 非, 只需要一个操作数, 如果操作数为true, 则返回false, 如果操作数为false, 则返回true

        //例子:
            System.out.println(!fasle);   // out: true 
  1. ^ : 异或, 当两个操作数不同时才返回true, 如果两个操作数相同则返回false
        //例子:
            System.out.println(4>=5 ^ 'c'>"a");   // out: true 
  1. 注意及说明:
    • 或 || 和 不短路或 | 的区别:
      1. 对于短路逻辑||或而言, 如果第一个操作数返回true, ||将不再对第二个操作数求值, 直接返回true
      2. 而不短路或|总是执行前后两个操作数.
    • 与 && 和 不短路与 & 的区别:
      1. &总会计算前后两个操作数, 而&&先计算左边的操作数, 如果左边的操作数为false, 则直接返回false,
        根本不会计算右边的操作数.

7.6 三目运算符

说明:
  1. 大部分情况下, 三目运算符都是作为 if else 的精简写法.他们的区别在于, if 后的代码块可以有多个语句,但三目运算符是不支持多个语句的.
  2. 三目运算符是可以嵌套的, 嵌套后的三目运算符可以处理更复杂的情况.
语法格式:
 (expression) ? if-true-statement : if-false-statement;
规则:
  1. 先对逻辑expression求值, 如果逻辑表达式返回true, 则返回第二个操作数的值, 如果逻辑表法师返回false, 则返回第三个操作数的值.
    //例子:
        // 最简单的三目运算符
        String str = 5 > 3 ? "5大于3" : "5不大于3";
        System.out.println(str);  // out: 5大于3

        // 三目运算符的嵌套
        int a = 11;
        int b = 12;
        System.out.println(a>b ? "a大于b" : (a<b ? "a小于b" : "a等于b"));   // out: a小于b

7.7 运算符的结合性和优先级

含义:
  1. Java语言中大部分运算符也是从左向右结合的, 只有单目运算符,赋值运算符,三目运算符是从右向左结合的,也就是从右向左运算.
  2. 乘法和加法是两个可结合的运算, 这两个运算符左右两边的操作数可以互换位置而不会印象结果.
运算符优先级
  1. ** 从上到下优先级下降(可以使用括号()来改变优先级):**
                        分隔符 :  . [] () {} , ;
                    单目运算符 : ++ -- ~ !
            强制类型转换运算符 : (type)
                乘法/除法/求余 : * / %
                     加法/减法 : + -
                    移位运算符 : << >> >>>
                    关系运算符 : < <= >= > instanceof
                    等价运算符 : == !=
                        按位与 : &
                      按位异或 : ^
                        按位或 : |
                        条件与 : &&
                        条件或 : ||
                    三目运算符 : ?:
                          赋值 : = += -= *= /= &= |= ^= %= <<= >>= >>>= 

# Java