day02-变量和运算符

214 阅读19分钟

;day02-变量和运算符

今日学习内容:

  • 常量
  • 数据类型
  • 变量的定义和使用
  • 基本数据类型的转换
  • 算术运算符
  • 赋值运算符
  • 比较运算符
  • 三元运算符
  • 逻辑运算符

今日学习目标:

  • 必须掌握变量的定义和赋值
  • 掌握什么是表达式
  • 掌握基本数据类型的自动转换
  • 掌握基本数据类型的自动提升
  • 掌握基本数据类型的强制转换
  • 掌握算术运算符的使用
  • 了解什么是前置++和后置++的区别
  • 掌握赋值运算符的使用,以及它的底层含义
  • 掌握比较运算符的使用
  • 必须掌握三元运算符的语法和使用
  • 掌握逻辑运算符的使用(常用 && 、|| 、!)
  • 了解位与(&)和短路与(&&)的区别,记住结论使用&&即可
  • 了解运算符的优先级
听课方法提醒:
1> 课前做好预习
2> 如果遇到听不懂的,记下来,放过去。专心听下一个知识点。

2. Java入门基础下

2.1 数据类型、常量、变量

2.1.1.常量(掌握)

常量(const),程序运行过程中固定不变化的值。

常量分类:

  • 字面量: 就表示直接给出的一个值(可以是整数、小数等),也有人称之为直接量。如整数常量1,2,3,小数常量3.14等。
  • 使用final定义的变量(后讲)
2.1.2. 数据类型(重点)

生活中,数据都是有类型这个概念的,比如张三18岁,18这个数字就是整型的,买了2.5斤菜,2.5就是小数类型的,在Java中每一个数据也有数据类型。

人为地把8个二进制位称为1个字节。(1 byte = 8 二进制位)

1个二进制位 可以存储 0  或者  1
2个二进制位 可以存储 00 或者 01 或者 10 或者 11
3个二进制位 可以存储  000 / 001 / 010 / 011 / 100 / 101 /  110 / 111
...
1字节 = 8 个二进制位  可以存储28次方个数, 范围是[0,255] , 共256个数,如果都是表示整数,范围是[0,255],如果也可以表示负数,那么把256个数均分,一半是[-128,-1] ,一半是[0,127]     

8种基本数据数据类型的范围和占内存大小(了解):

No数据类型占内存字节数所能表示的数据范围
1byte1-128 ~ 127
2short2-32768 ~ 32767
3int4-2^31^ ~ 2^31^-1 约21亿
4long8-2^63^ ~ -2^63^ - 1
5float4-3.4 x 10^38^ ~ 3.4 x 10^38^
6double8-1.7 x 10^308^ ~ 1.7 x 10^308^
7char20 ~ 2^16^ - 1
8boolean1位true 、 false

提醒:开发者需要明确记住每个类型所占字节数(内存大小)。

整数类型常量

在 java 中,整数类型的常量JVM默认使用 int 类型来存储 。

public class Test01IntType {
    public static void main (String[] args) {
        // 控制台输出10,这个10是一个常量,默认使用int存储。
        System.out.println(10);
        
        // 控制台输出20,这个20如果想以long类型存储,需要加L
        System.out.println(20L);
    }
}

所以,如果要存储long类型常量,要加L或者l,建议加L。常用的整数类型是int和long,byte和short基本不用。

小数类型类型

在 java 中,小数类型的常量JVM默认使用 double 类型来存储 。

public class Test02DoubleType {
    public static void main (String[] args) {
        // 控制台输出3.14,这个3.14是一个小数常量,默认使用double存储。
        System.out.println(3.14);
        
        // float类型常量,使用F/f后缀
        System.out.println(3.14f);
    }
}

如果要存储 float 类型常量,要加f或者F。

float类型又被称作单精度类型,尾数可以精确到6-7位有效数字,在很多情况下,float类型的精度很难满足需求,double更常用,double表示小数的数值精度是float类型的两倍,又被称作双精度,绝大部分应用程序都采用double类型。尾数可以精确到15-16位有效数字.

不管是float 类型和double类型在有效数字内都存在精确问题。

// float 类型只能精确到6-7,其中第六位是一定可以精确到的,第7可能精确到,也可能精确不到。
System.out.println(3.141592653f);
// a = 3.1415927

所以,实际开发过程中,小数类型一定要在有限数字范围内使用。

float,double 的数据不适合在不容许舍入误差的金融计算领域。如果需要进行不产生舍入误差的精确数字计算,需要使用 BigDecimal 类 (后面学) 。

字符类型常量

字符表示Unicode(万国码)编码表中的每一个符号,每个符号使用单引号引起来,其中前128个符号和ASCII表相同,如下图。

这张表要记住的几个符号,A在码表的顺序是65,a在码表的顺序是97。

public class Test03CharType {
    public static void main (String[] args) {
         // 控制台输出字符A,字符在内存中以两个字节存储。
        System.out.println('A');
    }
}

布尔类型常量

boolean 类型只有两个值,true 和 false , 在未来的开发中用于逻辑判断。

public class Test04BooleanType {
    public static void main (String[] args) {
        System.out.println(true);
    }
}

字符串类型

所谓字符串就是多个字符合在一起,使用双引号引起来。例如 : 我们在开发中要输出一个用户的名字就可以使用字符串了,因为一个用户的名字是由多个字符构成的。

public class Test05String {
    public static void main (String[] args) {
        System.out.println("wolfcode");
        
        // 需求:尝试输出你的姓名?
        // 思考:一个字符一个字符的输出,还是一下子就输出?
    }
}

字符串类型属于引用数据类型,不属于8大基本数据类型范畴,不在今天课程讨论范围内,后续会学习。但今天我们会写即可。

不同数据类型的常量:

  • 整数常量,所有整数,如1、2、3、100、200等
  • 小数常量,所有小数,如1.2、2.7、3.14等
  • 字符常量,0~65535之间的整数或用单引号括起来的符号如,'A'、'a'、'龙' 等
  • 布尔常量,只有true和false,分别表示对与错
  • 字符串常量,使用双引号括起来的内容如:“Will”、“wolfcode”等

需求:定义每一种数据类型的常量

public class TypeDemo{
    public static void main(String[] args) {
​
        // int类型常量
        System.out.println("十进制" + 20);
        System.out.println("二进制" + 0B00010100);
        System.out.println("八进制" + 024);
        System.out.println("十六进制" + 0x14);
​
        // long类型常量,使用L后缀
        System.out.println(20L);
​
        // float类型常量,使用F后缀
        System.out.println(3.14F);
​
        // double类型常量
        System.out.println(3.14);
​
        // char类型常量
        System.out.println(65);
        System.out.println('A');
​
        // boolean类型常量
        System.out.println(true);
        System.out.println(false);
​
        // String类型常量
        System.out.println("你好");
    }
}
2.1.3.变量(重点)

通过一张不完整的房屋租赁合同,引出变量。

案例:张三需要租赁李四的房屋,租赁合同如下:

上述合同,相当不正规,因为正规的合同上,租客和房东都是有变动的,不能写死,在整个合同中应该是使用甲方来表示房东,乙方来表示租客,只会在最后的时候签名甲方是谁,乙方是谁。

2.1.3.1 变量概述(了解)

变量指在程序运行过程中,值可以发生变化的量。

变量表示一个存储空间,可用来存放某一类型的常量,没有固定值,并可以重复使用。变量是内存中一块区域,可以往该区域存储数据,修改里面的数据,也可以获取里面的数据。

变量声明的语法

数据类型 变量名 [= 初始值];

变量的特点:

  • 占据着内存中的某一块存储区域
  • 该区域有自己的名称(变量名)和类型(数据类型)
  • 可以被重复使用
  • 该区域的数据可以在同一类型范围内不断变化
2.1.3.2 变量定义和赋值(重点)

需求:定义一个int类型变量,并赋值。

public class VarDemo{
	public static void main(String[] args) {
        // 方式一,先变量,后赋值,再使用
        // 1.数据类型  变量名; 
        int age;
        // 2.变量名 = 常量值;
        age = 17; // 定义一个int类型变量,初始值为17
        
        // 修改age变量的值为17
        age = 22;
        // 3. 使用定义的变量
		System.out.println(age);
        
        
        // 方式二,在声明时同时赋值(推荐)
		// 数据类型 变量名 = 初始化值;	
        // 定义一个String类型的变量,初始值为wolf
        String name = "wolf";
	}
}

使用变量注意:

  • 变量必须先声明,并且初始化后才能使用
  • 定义变量必须有数据类型
  • 变量从开始定义到所在的花括号结束之内可以使用,离开花括号就不能使用了
  • 同一作用域内,变量名不能重复定义

记: 语法格式

  • String,表示类型,这里可以写任何的类型
  • name:变量名,和我们的姓名一样理解, 没有为什么
  • =:赋值运算符,后面会讲,意思是将右边的值赋值给左边的变量
  • “wolf”:一个字符串类型的值,如果是其他类型,不要加引号

需求:定义每一种数据类型的变量

public class VarDemo{

	public static void main(String[] args) {

		// byte类型变量
		byte b = 20;
		System.out.println(b);

		// short类型变量
		short s = 20;
		System.out.println(s);

		//int类型变量
		int i = 20;
		System.out.println(i);

		//long类型变量,使用L后缀
		long l = 20L;
		System.out.println(l);

		//float类型变量,使用F后缀
		float f = 3.14F;
		System.out.println(f);

		//double类型变量
		double d = 3.14;
		System.out.println(d);

		//char类型变量
		char c = 'A';
		System.out.println(c);

		//boolean类型变量
		boolean bb = true;
		System.out.println(bb);

		//String类型变量
		String str = "你好";
		System.out.println(str);
	}
}

需求:交互两个相同类型变量的值

1、把num1的值存储到临时变量temp中去

2、把num2的值赋给num1变量

3、把temp存储的值赋给num2变量

public class ChangVarDemo{

	public static void main(String[] args) {
		int num1 = 10;
		int num2 = 20;
		System.out.println("num1=" + num1);
		System.out.println("num2=" + num2);
		// --------------------------------		
		// 交换过程
		int temp = num1;
		num1 = num2;
		num2 = temp;
		//--------------------------------		
		System.out.println("num1=" + num1);
		System.out.println("num2=" + num2);
	}

}

综合案例 : 存储一个手机信息

public class Test05Var {

    public static void main(String[] args){

        /**
         * 手机信息如下:
         * 名称:iphone xr
         * 价格:5899.00
         * 重量: 300(g)
         * 颜色: 白
         * 屏幕尺寸: 5.99
         * 是否支持5G : 能
         */

        String phoneName = "iphone xr";
        double phonePrice = 5899.00;
        int phoneWeight = 300;
        char phoneColor = '白';
        float phoneSize = 5.99f;
        boolean isSupport5G = true;


        /**
         * 标识符命名规则:
         * 1> 标识符可以有字母、数字、下划线、$构成
         * 2> 数字不能开头
         * 3> 不能使用java关键字和保留字
         *      // int int = 10; 错误
         */

        // 需求:给班级人数取名字
        int classPersonNum = 100;
        int class_person_num = 100;
        int _classpersonnum = 100;
        int $classPersonNum = 100;
        int class$person$num = 100;

        /** 变量命名规范
         * 1> 使用驼峰命名法(一般第一个单词的首字母小写,后续单词的首字母都大写)
         * 2> 命名时见名知意。
         */

    }
}

2.2 表达式(先掌握概念)

表达式(expression),是由数字、常量、变量、运算符、括号等组合以能求得结果的式子,表达式在开发过程中用于计算结果。

表达式举例(下列a、b、x、y、z都表示变量)。

  • a + b
  • 3.14 + a
  • (x + y) * z + 100

2.3 基本数据类型转换(掌握)

在8大基本数据类型中,boolean不属于数值类型,所以不参与转换,其他类型的转换规则如下图。一般的,byte、short、char三种类型相互之间一般不参与。

按照转换方式,有两种(注意:boolean类型不参与类型转换):

  • 自动类型转换:范围小的数据类型直接转换成范围大的数据类型 (小 => 大)。
  • 强制类型转换:范围大的数据类型强制转换成范围小的数据类型 (大 => 小)。

问题:三个大小不同容器,能相互把盛装的水倒给对方吗?

科普了解:
float4个字节为什么比long8个字节大?
--->因为底层的实现方式不同
浮点数的32位并不是简单直接表示大小,而是按照一定标准分配的。
第1位,符号位,即S
接下来8位,指数域,即E。
剩下23位,小数域,即M,取值范围为[1 ,2 ) 或[0 , 1)
然后按照公式:V = (-1) ^ s * M * 2 ^ E  
也就是说浮点数在内存中的32位不是简单地转换为十进制,而是通过公式来计算而来,通过这个公式虽然,只有4个字节,但浮点数最大值要比长整型的范围要大。
2.3.1 自动类型转换(掌握)

自动类型转换,也称为“隐式类型转换,就是把范围小的数据类型直接转换成范围大的数据类型。

转换规则:byte、short、char—>int—>long—>float—>double

注意事项:byte、short、char相互之间不转换,他们参与运算首先转换为int类型

语法格式

范围大的数据类型 变量 = 范围小的数据类型值;

语法举例:

public class Test07TypeConvert {
    public static void main(String[] args){
        // 1> 自动类型转换 :范围小的数据类型可以直接转换为范围大的数据类型
        int intNum1 = 10;
        long longNum2 = intNum1;

        long longNum3 = 100L;
        float floatNum4 = longNum3;

        float floatNum5 = 3.14f;
        double doubleNum6 = floatNum5;

        /** 总结
         * 自动类型转换 => 范围小的数据类型可以直接转换为范围大的数据类型
         * long类型8字节,float类型4字节,但是float表示的数据范围比long类型大。
         */
        
        // jvm优化
        // 在java中,可以把范围大的常量直接赋值给范围小(byte,short,char)的变量,只要不超过范围。
        byte byteNum7 = 100;

        // 错误的操作
        // int intNum8 = 100;
        // byte byteNum9 = intNum8;
    }
}
2.3.2 自动类型提升(掌握)

当一个算术表达式中,包含多个基本数据类型的常量或变量(boolean除外)时,整个算术表达式的结果类型将在出现自动提升,其规则是:

  • 所有的byte、short、char类型被自动提升到int类型,再参与运算
  • 整个表达式的最终结果类型,被提升到表达式中类型最高的类型
System.out.println('a' + 1);// 98

byte b = 22;
b = b + 11;// 编译出错,此时结果类型应该是int

double d1 = 123 + 1.1F + 3.14 + 99L ;

结论:算数表达式结果的类型就是其中范围最大的数据类型。

public class Test08TypeConvert {
    public static void main(String[] args){

        // 要点1:所有的byte、short、char类型被自动提升到int类型
        byte byteNum1 = 10;
        short shortNum2 = 20;
        int r = byteNum1 + shortNum2;

        // 要点2:整个表达式的最终结果类型,被提升到表达式中类型最高的类型
        float floatNum3 = .14f;
        double doubleNum4 = 1.0;
        double r2 = byteNum1 + shortNum2 + floatNum3 + doubleNum4;

        // 思考:
        char c2 = 'a';
        int num = 1;
        int r3 = c2 + num;
        System.out.println(r3);
    }
}
2.3.3 强制类型转换(掌握)

强制类型转换,也称为“显式类型转换”,就是把范围大的数据类型强制转换成范围小的数据类型。

语法格式:

范围小的数据类型  变量 = (范围小的数据类型)范围大的数据类型值;

注意:一般情况下不建议使用强转,因为强转有可能损失精度

public class Test09TypeConvert {
    public static void main(String[] args){
        // 强制类型转换
        float floatNum1 = 3.14f;
        int r1 = (int)floatNum1;
        System.out.println(r1);

        // 应用:根据消费金额计算vip积分(规则:一块钱积2分)
        float totalPrice = 998.88f;
        int vipScore = (int)totalPrice * 2;
        System.out.println(vipScore);

        // 思考题
        char c = 97;
        int num = 1;
        char r = (char)(c + num);
        System.out.println(r); // b
    }
}

16.30

2.4运算符

对常量和变量进行操作的符号称为运算符

常用运算符:

  • 算术运算符
  • 赋值运算符
  • 比较运算符
  • 逻辑运算符
  • 三元运算符
2.4.1 算术运算符(掌握)

用来四则运算的符号,和小学学习的加减乘除无异。

2.4.1.1 加减乘除余(了解)

对于字符串而言,+符号表示连接操作,任何类型的数据和字符串相连接,结果都是字符串。

public class Test07Operation1 {
    public static void main(String[] args) {
        // 算术运算符
        // +  -  *
        // /
        // %
        // + 作为算术运算符
        int intNum1 = 10;
        int intNum2 = 20;
        int r1 = intNum1 + intNum2;
        System.out.println(r1);

        // + 作为字符串连接符
        // + 两边的表达式或值只要有一个是字符串,+ 就是字符串连接符
        int intNum3 = 30;
        String str = "intNum3:" + intNum3;
        System.out.println(str);

        // / 整除操作 :
        int r2 = 5 / 2;
        System.out.println("r2 = " + r2);
        int num = 5;
        double r3 = num * 1.0 / 2;
        System.out.println("r3 = " + r3);
        /** 总结
         * 1> 如果/两边的表达式都是整形,结果一定是整形
         * 2> 0不能作为除数
         */

        // % : 取模,求余数
        System.out.println(5 % 2);
        System.out.println(1 % 5);
        // 需求: 给定47天,问47天中有__月(30)__天
        int days = 47;
        int month,day;
        month = days / 30;
        // day = days - month * 30;
        day = days % 30;
        System.out.println(month);
        System.out.println(day);
        
    }
}
2.4.1.2 自增和自减(掌握)

自增:++,递增操作符,使变量值增加1,有前置和后置之分,只能操作变量。

自减:-- ,递减操作符,使变量值减去1,有前置和后置之分,只能操作变量。

自增和自减具体操作是一样的,仅仅是一个是加1,一个是减1而已,现在单讲++。

代码 result ++和 ++result,结果都是result变量的值加1。

唯一的区别是:

  • 前置(++result): 表示对result加1之后的结果进行运算
  • 后置(result++): 表示对result变量加1之前的值(原始值)进行运算。

如果仅仅执行简单的递增操作(只写result++或++result),那么选用任意一个都可以。

public class Test07Operation2 {
    public static void main(String[] args) {
        // 自加
        // i++ / i-- : 遇到i++/i--,i先参与运算,运算后自增1/自减1
        // 情况1(必须掌握):
        /*int i = 10;
        i++;
        System.out.println("i = " + i);*/

        // 情况2(必须掌握):
        /*int i = 10;
        int j;
        j = i++;
        System.out.println("i = " + i);
        System.out.println("j = " + j);*/
    }
}

比较权威的解释:

  • ++a表示取a的地址,增加它的内容,然后把值放在寄存器中;
  • a++表示取a的地址,把它的值装入寄存器,然后增加内存中的a的值;

如果不理解什么是寄存器,简单记住,都可以表示当前变量自身加1,区别是:

  • 前置++:先增加后使用
  • 后置++:先使用后增加
2.4.2 赋值运算符(掌握)
变量 = 表达式的值或者常量值

public class AssigningOperatorDemo {
	public static void main(String[] args) {
		// 把常量17赋值给int类型的变量a
		int a = 17;
		System.out.println("a=" + a);
		// += 把左边和右边的数据进行运算,最后赋值左边变量
		a += 10;// 相当于a = a + 10
		System.out.println("a=" + a);
        
		short s = 5;
		s += 2; //底层相当于 s = (short) (s + 2)
		System.out.println("s=" + s);
	}
}
2.4.3 比较运算符(掌握)

用于比较变量或常量、表达式之间的大小关系,其结果是boolean类型(要么为true,要么为false)。

其操作格式为 :

boolean  result  = 表达式A  比较运算符  表达式B;

注意:>=符号,表示大于或者等于。

public class ComparisonOperatorDemo {
	public static void main(String[] args) {
		//直接操作常量
		System.out.println(10 > 5);//true
		System.out.println(10 >= 5);//true
		System.out.println(10 >= 10);//true
		System.out.println(10 < 5);//false
		System.out.println(10 <= 5);//false
		System.out.println(10 <= 10);//true
		System.out.println(10 == 10);//true
		System.out.println(10 != 10);//false
		
        //使用变量操作
		int a = 10;
		int b = 5;
		boolean result = a > b;
		System.out.println(result);//true
	}
}
2.4.4 三元运算符(掌握)

三元运算符,表示有三个元素参与的表达式,所以又称为三目运算符,其语义表示if-else(如果什么情况就做什么,否则做什么)。 如果...那么...否则...

语法格式:

数据类型 变量 = boolean表达式 ?  结果A :结果B
  • 如果boolean表达式结果:

    • 为true,则三元运算符的结果是结果A;
    • 为false,则三元运算符的结果是结果B;

注:三元运算符必须定义变量接受运算的结果,否则报错

三元运算符结果的类型由结果A和结果B来决定的,结果A和结果B的类型是相同的。

需求1:判断一个数99是不是偶数

public class TernaryOperatorDemo1{
	public static void main(String[] args) {
		int a = 99;
		String result = a % 2 == 0 ? "偶数" : "奇数";
		System.out.println("a为" + result);
	}
}

需求2:求99和20两个数中的最大值

public class TernaryOperatorDemo2{
	public static void main(String[] args) {
		int a = 99;
		int b = 20;
		int result = a > b ? a : b;
		System.out.println("最大值:"+result);
	}
}

需求3:一共55条数据,每页10条数据,一共分多少页

public class TernaryOperatorDemo3{
	public static void main(String[] args) {
		int totalCount = 54;
		int pageSize = 10;
		int totalPage = totalCount % pageSize == 0 
					? totalCount / pageSize 
					: totalCount / pageSize + 1;
		System.out.println("一共分" + totalPage + "页");
	}
}
2.4.5 逻辑运算符(掌握)

逻辑运算符用于连接两个boolean表达式,结果也是boolean类型的。

语法格式为:

boolean  result = boolean表达式A  逻辑运算符  boolean表达式B;

运算规则如下:

规律:

  • 非:取反,!true则false,!false则true
  • 与:有false则false
  • 或:有true则true
  • 异或:^ 相同则false,不同则true
& 与运算,可以理解为 "并,并且"
true  & true  => true
true  & false => false
false & true  => false
false & false => false
总结 : & 运算,只要两边的表达式有一个为false,结果就为false

&& 短路与
&& 运算,只要两边的表达式有一个为false,结果就为false,如果第一个表达式为false,后续表达式不再运算;

| 或运算,可以理解为 "或,或者"
true  | true  => true
true  | false => true
false | true  => true
false | false => false
总结 : | 运算,只要两边的表达式有一个为true,结果就为true

|| 短路或
|| 短路或运算,只要两边的表达式有一个为true,结果就为true,如果第一个表达式为true,后续表达式不再运算;

! 非运算,可以理解为 取反
!true = false
!false = true
2.4.5.1 基本使用(掌握)
public class LogicalOperatorDemo1 {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int c = 30;
		//与操作
		System.out.println((a > b) & (a > c));// false	&	false
		System.out.println((a > b) & (a < c)); // false	&	true
		System.out.println((a < b) & (a > c)); // true	&	false
		System.out.println((a < b) & (a < c)); // true	&	true
        
		//或操作
		System.out.println((a > b) | (a > c));// false	|	false
		System.out.println((a > b) | (a < c)); // false |	true
		System.out.println((a < b) | (a > c)); // true	|	false
		System.out.println((a < b) | (a < c)); // true	|	true
		
        //相反操作
		System.out.println((a > b)); // false
		System.out.println(!(a > b)); // !false
		System.out.println(!!(a > b)); // !!false
	}
}
2.4.5.2 &和&&的区别(掌握)

& :&左边表达式无论真假,&右边表达式都进行运算;

&& :如果&&左边表达式为真,&&右边表达式参与运算,否则&&右边表达式不参与运算,故称短路与。

| 和 || 的区别同理,||,左边为真,右边不参与运算。

public class Test05LogicOperator2 {
    public static void main(String[] args) {
        // 逻辑运算符
        // 短路运算 && ||
        int m = 10;
        int n = 20;
        // boolean r1 = false && false;
        boolean r1 = (m > n) && (++m > 1);
        System.out.println("r1 = " + r1);
        System.out.println("m = " + m);


        boolean r2 = (m > n) | (m < 1);
        System.out.println("r2 = " + r2);
    }
}

上述代码,一行一行的测试,测试完,注释该行代码。

2.4.6 运算优先级(了解)

表达式的运算都是有优先级的,基本上和数学中的优先级类似,这里需要注意的是,赋值符号。

注意:赋值符号最后运算的,并且是从右向左运算的。

()的优先级最高,赋值运算符优先级最低

赋值运算符的运算方向从右向左