Data Type And Operator - 数据类型和运算符 (JavaSE- 最详细的介绍,因为这算是我最长的一篇了)

x33g5p2x  于2021-11-22 转载在 Java  
字(24.3k)|赞(0)|评价(0)|浏览(327)

变量和类型

变量 指的是 程序运行时 的 可变的量,相当于开辟一块内存空间来保存一些数据

类型 则是 对 变量的种类 进行了 划分,不同的类型 的 变量 具有不同特性

我们所讨论的"变量"主要 和 我们的"内存"这样的硬件设备密切相关

我们先来讲讲变量。

变量就像一个个大小不一的盒子(类型不同的变量),盒子的空间里面装着不同的宝藏,
并且盒子里的宝藏是可以进行替换(覆盖)  的,只要放得下。如果放不下,咱就不要它。(Java是一门强势语言,不存在截断的情况,超出类型的取值范围的值,强行存入,程序会报错,并且程序从该处结束运行)
也就是说 不同类型的变量的空间 存储的数据 都是不同的,且变量的值是可以改变的

而变量的存储空间从何而来?这里我们就要讲讲 内存

打个比方

内存 就像 一个长长的街道,街道上住着形形色色的人(各种各样的变量)
就好比 类型不同 值相同 且变量不同 的数据[两个年纪相同的人,但是,是两个人不是一个人,也不是一个家庭的成员 char a = 10;int b = 10;]

和 类型相同值不同  且变量不同 的数据(生在同一个家庭,有兄弟姐妹,他们独特的存在。 int a =10;int b =20;)
 
和 类型和值都相同  且变量不同 的数据(你可以认为就是一对双胞胎,虽然他们出生一个家庭,同时出生,长得一模一样,但确确实实是两个人,int a=0;int b =0;)

和 类型和值都不同  且变量不同 的数据(你可以认为是两个完全不搭边的人,float a=3.14;int b = 5;)

变量 就好比 一个人的唯一性,是不可重复或分裂,在程序中一个变量是不可以被重复定义的,在现实生活中,你总不能说人会分身吧。
而且变量的存储的数据 是可以被改变的,唯一不变的就是变量本身(int a;a就是变量本身),
人也是一样的,可以改变自己的,为了成为更好的自己,一直在努力的各位。唯一不变的就是 我们还是自己,不可能变成另一个人,取代别人的存在(这个别杠,少看点剧)

只要是个人都有自己的家(变量都有自己的存储空间),家是有门牌号的,而 门牌号 就相当于 变量存储空间的地址
内存就好比是这一条街道所有人的信息的汇总

切回实际

真正想要理解内存,需要理解 冯诺依曼 体系,因为现在的计算机都是以这个体系来建立我们逻辑关系的
小常识: 现代计算机之父 就是 约翰.冯.诺依曼。又是一个聪明绝顶之人’

冯诺依曼体系 由五个部分组成

1、输入设备,2、输出设备,3、外存储器,4、内存储器,5、运算器和控制器(两者组成的,也就是所谓的CPU)

冯诺依曼体系结构图

1,2这两个部分就不用我解释了(生活例子:键盘和屏幕),我们重点讲讲 外储存器 和 内存储器 有何区别?

举个列子
买手机,商家可能会问你 你是要 8G+258G 还是 4G+64G 等等。

我们可以看到两块内存(小的内存,大的外存),我们都是 小一点的内存越大,玩游戏越顺畅。后面大的那个内存,说明你可以存很多数据到手机里,如果你是258的,都不够用,我想说汝分享否?
有的人会说,为什么我苹果的内存(运行内存)没有 安卓的大,玩同一个游戏,为什么它比我卡?
因为 苹果手机的每一个部件都是为苹果手机专门制造设计的,所以系统之间的兼容性很强,所以在玩游戏的时候,所占内存较小
而安卓机,就是一个组装机,懂得都懂,一个手机可能有几个厂家的部件组装而成,所以兼容性不是很好,所以在玩游戏的时候,所占内存较大

说白了就是,苹果房子的每一块转都是无缝链接,每一块砖的大小形状都是相同的,所以墙面光滑如玉(原装就是强[贵])(打游戏,6的飞起)。
而安卓房子,就像是每一个砖之间是存在间隔(系统不兼容,导致内存有所浪费),再加上每一块砖的大小形状有着一些或很大的差别(又会占用一些内存的空间),导致墙面不光滑(卡的飞起,成为甩锅的对象)

当然国产机现在越做越好(贵)[好 == 贵].很好,我选小米
电脑内存图片示例(运行内存 RAM)

CPU(运算器和控制器)

CPU当中 运算器(逻辑运算)和  控制器(控制程序的运行【怎么运行,从哪里运行】 和 停止 【停止的条件,停止】,停止之后又该怎么做?)
这里我们不做深究,我们只是在 了解 内存的过程中 了解一下 冯洛伊曼体系 ,其重点是内存储器,也就是我们的内存。

总结:

变量 就是存储在 内存(内存储器【硬件】)当中,当变量的类型不一样,存储的数据也就不一样。它所占内存大小就不一样。
学了C的,都知道,变量在程序运行时,才在内存中申请空间,程序结束之后,要将空间还给 内存。
所以 变量的空间的创造和销毁(回收),都与我们的内存储器【硬件】有这密切的关系
这样就回到我们的最初的标题注释的内容,"变量"主要和我们的 "内存"这样的硬件设备密切相关

拓展

变量的命名:
小驼峰形式 intMax,第一词的首字符小写,后面词的首字符大写(见附图 驼峰)
在Java中 标识符由数字、字母、下划线、$,组成
表示开头不能是数字( int a2;right,  int 2a;error)
注意 $ 和 下划线, 虽然可以这么写 int $a,int _a, 但不建议(别给别人挖坑,保持良好代码习惯)。

举个例子,有一个二货这么写 int ______a=0; ,你告诉我这有几个下划线?,所以别这么写

JavaSE(Java Platform, Standard Edition - Java平台标准版的简称) 中的 八大基本数据类型

1.整形变量( 4 byte)

基本语法格式

int 变量名 = 初始值;
代码示例
public class DataTypeAndOperator{
	public static void main(String[] args){
		int num = 10;// 定义一个整形变量,变量就相当于有一个箱子是a,它的类型int,存储的数据是 整数 10
		/* 另外注意 在Java中,int 就是 4个字节 的大小,与操作系统是多少位无关,这一点请牢记。 这是Java中的一个特点:可移植性强,就是 不管你的电脑是多少位操作系统,你把我的字节码文件拿过去,都可以跑起来 */
        System.out.println(num);// (这里)直接放入你想要输出打印的变量,就OK了,没有像C一样,有打印格式要求
        
        // 如果还是像 C 一样也可以,如下
        System.out.printf("%d\n",num);

	}//效果图如下,在这里跟大家回顾上一篇博客的内容
	java一共有三种打印方式
	//System.out.println("打印换行,这种打印方式用的最多");
	//System.out.print("打印不换行");
	//System.out.printf("跟C语言一样,以格式化的形式进行输出。这种打印方式用的最少");
}
效果图

整形变量的取值范围

提醒:
在 Java中,是没有无符号类型的(unsigned ),统一是 有符号的(signed ),就是 有符号数【正负数】,
也就意味着我们的数值转化为二进制时,最高位永远都是符号位
例子
int 为 4 byte,即 32 bit 位,即 32位 二进制数
(8 bit = 1 byte; 1024 byte = 1 kb; 1024 kb = 1mb; 1024 mb = 1gb; 1024 gb = 1 tb; 1024 tb = 1pb.)

最高位为符号位,那么剩下的31位,都是数值位,就是能表示出 2^31 个数字
最高位【符号位】为 0,表示为正,数值位全部取1,得到最大值 2^31-1,
因为0也算一个数字了,所以它能表达的最大值,就是 能表达数字的个数 减去一个1.(照理说是从1算起的,那么就是2^31),所以我们要减一(附图)
最高位【符号位】为 1,表示为负,数值位全部全1,得到最小值【-2^31,这个就是从-1算起,所以是-2^31】(图10)
附图

那么在 Java中 如何求 取值范围的最大值和最小值?

在此之前,我们需要 integer 是什么?
int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。

小知识点,

  1. 除了 int 和 char,的封装类分别是 Integer,Character 之外
    其它 6 个原始数据类型 都是首字符大写(Byte、Short、Float、Double、Long、Boolean)
  2. 八 个原始数据类型: byte(1)、 char(2)、short(2)、 int(4)、 float(4)、 double(8)、 long(8), 、boolean[布尔类型] (没有明确规定它的大小。在JVM中 1字节 或者 1 bit)
    int的默认值为0,而Integer的默认值为null
  3. 即Integer可以区分出未 未赋值 和 值为0 的区别,int则无法表达出未赋值的情况,例如,要想表达出 没有参加考试 和 考试成绩为0 的区别,则只能使用 Integer
  4. 另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。

程序例子:

int的默认值为0,而Integer的默认值为null,

public class DataTypeAndOperator{
	public static void main(String[] args) {
		int a;
		System.out.println(a);
	}
}
效果图

程序出错,不应该输出为 0吗?
因为在 Java中 一个局部变量,没有进行初始化赋值,那么就不能够使用它,如果运行,程序会报错。
这里体现出 Java的安全性
ps:在Java中是没有全局变量的,这点请记住

另外注意一点,在方法(main方法)中,定义的量叫做变量
在类的内部,方法的外部的变量,叫做属性(又称 成员变量),
比如说 我就在 DataTypeAndOperator 的花括号后面建立 int a 的变量
这时,a就是成员变量(属性),它的默认值就是 0。

现在我们来在Java中求 int 类型 所能存储最大值和最小值

public class DataTypeAndOperator{
	public static void main(String[] args){
		System.out.println(Integer.MAX_VALUE);
		System.out.println(Integer.MIN_VALUE);
	}
}

上下两者写法师等价的。

最大值+1,最小值-1,会导致数值溢出(相当于碗就这么点大,容量有限,你非要装,肯定是会溢出的),那么效果如何?

public class DataTypeAndOperator{
	public static void main(String[] args){
		System.out.println(Integer.MAX_VALUE+1);
		System.out.println(Integer.MIN_VALUE-1);// 这里加减,没有涉及到赋值,如果将其 赋值给int类型的变量。程序会报错,停止运行
		// 因为Java的安全性很高
	}
}

从 效果图 和 圆形图 可以看出,正数 0~2^31-1,负数 -1 ~ -2^31.,-2 ^31 代替了 2^31的位置,从而形成了一个圆形范围(取值循环)

最大值加一,取得最小值;最小值减一,取得最大值

Java有一个地方狠拐。。

public class DataTypeAndOperator{
	public static void main(String[] args) {
		int 钱 = 10;
		System.out.println(钱);
	}
}

因为 Java 是Unicode字符集,它包含ASCII码字符集,拉丁文,中文 等等…
所以 在 Java 中 能以中文作为变量。
但是最好不要这么写,有点过了。。。

注意事项

  1. int 表示变量的类型是一个整形,另外 在 Java中 int 是没有无符号类型的(unsigned int),统一是 有符号的int(signed int)
  2. 变量名是变量的标识(int a,a就是变量名),后续都是通过这个名字来使用变量
  3. Java 中 = 表示赋值,意思是给变量设置一个初始值。(和数学不一样,数学里是等于的意思)
  4. 初始化操作时可选的,但是 建议 创建变量的时候都显式初始化。(尤其是局部变量,不初始化,程序会报错)
  5. 最后不要忘记分号,否则会编译失败
  6. // 表示注释,注释作为代码的解释说明部分,不参与编译运行。

2.长整形变量(长整形:long 8 byte)

基本语法格式

long 变量名 = 初始值;

注意 在Java中是没有long long类型的。

long 的取值范围

long : 8 byte == 64 bit
除去一个符号位,还剩63位,也就是说 取值范围为 -2^63 ~ 2^63-1
long类型的数据的最大值为 2^63-1,最小值为 -2^63
程序如下:
public class DataTypeAndOperator{
    	public static void main(String[] args) {
    		long a = 10l;// 10 后面加一个 大写的 L ,表示long类型的数据。
    		// 如果是小写 int a =10l,就不明显,看起来 跟 数字 1 一模一样。
    		 代码习惯!!!
    		// 所以 L 还是要大写
    		long long b =10;// long long 类型是不存在的
    		System.out.println(Long.MAX_VALUE);
    		System.out.println(Long.MIN_VALUE);
    	}
    }

注意事项

注意事项:

  1. 基本语法格式和创建 int 变量基本一致, 只是把类型修改成 long
  2. 初始化设定的值为 10L , 表示一个长整型的数字. 小写的 l,不建议写。
  3. 使用 10 初始化也可以, 10 的类型是 int, 10L 的类型是 long, 使用 10 L 更好一些.
  4. Java 中 long 类型占 8 个字节. 表示的数据范围 -2^63 -> 2^63-1

3 双精度浮点型变量(8 byte)

基本语法

double 变量名 = 初始值;

代码示例

public class DataTypeAndOperator{
	public static void main(String[] args) {
		double d = 10.1;
		System.out.println(d);
	}
}

拓展代码1

public class DataTypeAndOperator{
	public static void main(String[] args) {
		int a =1;
		int b =2;
		System.out.println(a/b);
	}
}

讲道理 结果应该是0.5, 但是在Java中整数除以整数,结果只能是整数。
所以 结果取 0.5 整数位 0

那么我么想得到 0.5,该怎么写?
代码如下
public class DataTypeAndOperator{
	public static void main(String[] args) {
		double a =1.0;// 占 8个字节
		double b =2.0;

		 如果这样写呢?
		// int a = 1.0;小数默认占8个字节,int 肯定是 放不下的
		// int b = 2.0;
		System.out.println(a/b);
		//只有 a 和 b都是小数的情况下,结果才是 我们想要的 0.5
	
	}
}

拓展代码2

public class DataTypeAndOperator{
	public static void main(String[] args) {
		double a =1.1;//小数 默认 占 8个字节,而 double 也是 8 个字节大小,所以放的下 
		double b =2.0;
		System.out.println(a*a);
	}
}

照理说 结果应该为 1.21
但是结果为 1.2100000000000002,后面多了一个 2,这是为什么呢?
因为在程序里,小数是没有精确的数字的
也就是说 小数本身是没有一个精确的数字的。它只能精确到几位

// float类型,只能精确到小数点后 6 位
	// double类型,只能精确到小数点后 16 位

4 单精度浮点型变量(4 byte)

基本格式:

float 变量名 =初始值;

代码示例

public class DataTypeAndOperator{
	public static void main(String[] args) {
		float a =1.0f;// 占 4 个字节

		 为什么不这样写?
		//float a = 1.0;
	     因为小数是默认 占 8 字节,也就是默认 double类型	
	     你需要知道 Java是一门强势语言,赋值一定要类型相同,否则代码进行编译时,是不会通过的,会报错。
		 所以在 java 当中,对 单精度浮点型,也就是对float类型的变量,进行赋值时,小数后面一定要加上 小写 f 或 大写 F
		 12.5f 或 12.5F 这样写,就表明了 小数 12.5 是一个单精度浮点型数据,而非双精度浮点型数据
		System.out.println(a);

	}
}

注意:

float 类型在 Java 中占四个字节, 同样遵守 IEEE 754 标准. 由于表示的数据精度范围较小, 一般在工程上用到浮点数都
优先考虑 double, 不太推荐使用 float

5 字符类型变量( 2 byte)

基本格式:

char 变量名 = 初始值;

代码示例

public class DataTypeAndOperator{
	public static void main(String[] args) {
		char a ='w';
		char b = '强';
		System.out.println(a);
        System.out.println(b);
	}
}

由效果图可知 char 类型能够存的下 汉字
一个汉字占 2 个字节,也就意味着 char 在 Java 当中,所占内存大小为 2 字节

代码2

public class DataTypeAndOperator{
	public static void main(String[] args) {
		char a =97;// 97 是 字符 a 的 ASCII 码值
		System.out.println(a);
	}
}

由图可知 在 Java 中,将 整数 赋给char类型的变量,Java会将 整形数据 转换成 ASCII码值,再将其打印,其结果是 ASCII码值 所对应的 字符

注意事项:

  1. Java 中使用 单引号 + 单个字母 的形式表示字符字面值.
  2. 计算机中的字符本质上是一个整数. 在 C 语言中使用 ASCII 表示字符
    而 Java 中使用 Unicode 表示字符. 因此一个字符占用两个字节, 表示的字符种类更多, 包括中文.

6 字节类型变量(相当于 C语言里面的char,内存大小 1 byte)

基本语法格式:

byte 变量名 = 初始值

代码如下:

public class DataTypeAndOperator{
	public static void main(String[] args) {
		byte a =9;

		 另外 和 int 它们一样,赋值超过它的取值范围,程序会报错
		 1 byte = 8 bit
		 除去符号位,取值范围为 -2^7 ~ 2*7-1(-128~127)
        byte b = 130;
		System.out.println(b);// 附图1
		 由图可知,130 超出去 byte 能存储的值,系统会认为该值的类型 是 其他类型,且所占字节比它大。
		 两者之间无法进行赋值

		 注意: 在Java中,所有数据,都是这样,拥有属于它们自己的取值范围, 一个类型的变量,只能存储该类型的取值范围以内的值
		 超出了,我就存不了。
		 就是说 多一分不行,少一分可以,因为我放得下
		 类型 所占字节大的,可以放下 比它 所占字节要小的类型的值
		 就是说 一个类型的取值范围比另一个类型的取值范围 要大时, 取值范围大的类型,可以存放 取值范围小的类型的所有取值
		 说白了 就是 大吃小,小吃不下大。// 附图3


		System.out.println(a);// 附图2
	}
}
附图1

附图2

附图3(用 long 和 int 做比较)

另外 提示一下, 在Java当中,是没有sizeof 这种操作符的。

就是说 在 Java 中,  类型所占字节的大小,你需要自己记住

注意事项:

  1. 字节类型表示的也是整数. 只占一个字节, 表示范围较小 ( -128 -> +127 )
  2. 字节类型 和 字符类型 互不相干 (不要混淆)

7 短整型变量(2 byte)

基本语法格式

short 变量名 = 初始值;
代码示例
public class DataTypeAndOperator{
	public static void main(String[] args) {
		short a = 2;
		 2 字节 == 16 byte
		 除去了符号位
		 它的取值范围为 -2^15 ~ 2^15-1( -32768 ~ 32767)
		System.out.println(a);
	}
}

8 布尔类型变量

基本语法格式:

boolean 变量名 = 初始值;

代码示例:

public class JavaFirst {
    public static void main(String[] args) {
        boolean flag = true;
        System.out.println(flag);//附图1
        boolean flag3 = false;
        System.out.println(flag3);// 附图3
                 相信大家都是有一定的C语言基础的
         在 C语言中,0为假, 非零为真

        那么我这么写。
        boolean flag2= 2;
         这样写是不行的
         在Java当中 boolean 类型,只有 2个取值
         要么是 true,要么是 false
         附图2
        
         
 我可以这样写吗?
          boolean flag5 = true +1;
          boolean flag6 = false+1;
           图 4 

    }
}
附图1

附图2

那么 boolean 的值 只能为 ture 和 false

附图3

附图4

还有一个原因,true 和 false 根本就不是 一个数,所以根本无法相加

注意事项:

1. boolean 类型的变量只有两种取值, true 表示真, false 表示假.
    2. Java 的 boolean 类型和 int 不能相互转换, 不存在 1 表示 true, 0 表示 false 这样的用法.
    3. boolean 类型有些 JVM 的实现是占 1 个字节, 有些是占 1 个比特位, 这个没有明确规定

     假如
      有一天 你碰到了一道题,有4个选项,让你找出那个是对的(问布尔类型的大小)
你看其他三项是不是明确错误的(就是  一个选项 是 1 byte,其它的 都是 几个字节,那就选 1字节的,懂吧)

至此Java的8大基本数据类型结束了。

下面我们来讲讲其他类型

字符串类型变量

字符串类型 是Java特有的类型,不属于 8大基本数据类型。
字符串 就是把 一些字符 放到一起。

基本语法格式:

String 变量名 = "初始值";

代码示例:

public class JavaFirst {
    public static void main(String[] args) {
        String str = "hello";
        System.out.println(str);// 效果见附图
    }
}

知识点, String 是 字符串类型,又称 引用类型

在 Java 中 数据类型 主要分为 2部分:

数值类型(基本数据类型) : 整数(byte、short、int、long)、浮点数(float、double)、字符(char)、布尔(boolean)

引用类型: String、数组、类、接口、枚举

  怎么判断 一个变量 是不是 引用类型,你就看这个变量存储的值,是不是一个地址
  细品!! 提示一下 数组名是什么? 嗯~~~

拓展

public class JavaFirst {
    public static void main(String[] args) {
         1
        System.out.println("hello"+"world");// 图 6
         从效果图可以看出 它们拼接成一个字符串
         也就是说 在 Java 中,两个字符串相加,就能拼接成一个字符串。
         即  + 号, 等于 拼接 命令

         2
        System.out.println("hello"+10+20);// 图 7
         由 结果得知, 字符串和其它数据类型int 10 和 int 20,使用 + 拼接,其结果就是拼接成一个字符串
          语法格式:字符串 + 其他数据类型(将其后的面的数据,不进行处理,转换成字符串,进行拼接)

          3
        System.out.println(10+20+"hello");// 图 8
         由结果得知, 其他类型数据int 30  和 字符串,使用 + 拼接
         虽然结果还是一个字符串, 但 其他类型的数据,在拼接之前,就已经 处理过了。

         4
        System.out.println(10+""+20+"hello");// 图 9
         由结果得知, 当 一个 非字符串类型int 10 与 "" ,使用 + 拼接时,会成为 一个字符串(就相当于 10 带上一个头套)
         那么 这就是  第二种情况( 字符串"10" 和 其他类型数据(int 20) 拼接,其结果还是字符串["1020"])
         和 第一种情况(字符串("1020")和 字符串("hello") 拼接), 其结果 就是 "1020hello"

         a = 10; b = 20(取巧)
        System.out.println("a = " + 10 + "; b = " + 20);// 图10
         运用了   1  和 2  两种情况
         字符串("a = ")和 其他类型数据 int 10 ,使用 + 号,进行拼接,使其成为一个字符串 “a = 10”
         字符串("a = 10") 和 字符串 ("; b = "),使其成为一个字符串“a = 10; b = ”
         字符串("a=10; b=") 和 其他数据类型 int 20,使用 + 号,进行拼接,使其成为一个字符串 "a = 10; b = 20"

    }
}

图6

图7

图8

图 9

图 10

注意事项:

  1. Java 使用 双引号 + 若干字符 的方式表示字符串字面值.
  2. 和上面的类型不同, String 不是基本类型, 而是引用类型(后面重点解释).
  3. 字符串中的一些特定的不太方便直接表示的字符需要进行转义.

转义字符

转义字符释义
1 。  \ ?在书写连续多个问号时使用,防止他们被解析成三字母词
2,   \ ’用于表示字符常量’
\“用于表示一个字符串内部的双引号
3.    \ \用于表示一个反斜杠,防止它被解释为一个转义序列符。
\a警告字符,蜂鸣
\b退格符
\f进制符
\n换行
\r回车
\t水平制表符
\v垂直制表符
\dddddd表示1~3个八进制的数字。 如: \130 X
\xdddd表示2个十六进制数字。 如: \x30 0

注意!! 标有123的,转义字符中间是没有空格,因为我不给空格 它显示不了 \ 的。

程序实例

public class JavaFirst{
    public static void main(String[] args) {
        String s1 = "bit";
        System.out.println(s1);// bit

        // 如果我想输出 "bit",怎么写
// String s2 = ""bit"";// "bit"? erorr,因为 编译器会认为 两个相邻的发双引号,先结合。将其当做一个整体。图11
        // 正确写法
        String s2 = " \"bit\" ";// 这里的 \ 就是转义字符,使上式中,两个相邻的双引号分离。成一个单独双引号
        // 后面的斜杠也是一样,使其分离成为一个单独的双引号,而这里分离出来的双引号,与bit 结合("bit",注意这不是一个字符串,你可以这双引号,看作两个单独的字符),
        // 最后剩下来的左右最外面的两个双引号,将其("bit")转换成 字符串 “ “bit” ”
        System.out.println(s2);// 图 12

        // 如果我想输出 \bit\
        //String s3 = "\bit\"; // 结果与s2的错误写法的一样, 双引号 与 \ 结合成一个整体,所以,idea编译器 会提示 在 "\ 的后面缺少一个分号。 见图 13
        //正确写法
        String s3 = "\\bit\\";// 与s2同理,使两个斜杠与双引号分离,与bit先结合\bit\,最后外面的双引号的作用,是将其(\bit\)当做一个字符串存入 s3
        System.out.println(s3);// 图14

        // 想输出 \\bit\\,现在就很简单了
        String s4 = "\\\\bit\\\\";// 一个斜杠管一个字符(斜杠),这每边有 4个斜杠, 所以每边最后剩下 2个斜杠
        // 最后剩下的两个双引号,将其(\\bit\\)当做一个字符存入 s4
        System.out.println(s4);
        // 图 15
    }
}

图11

图12

图13

图 14

图15

变量的作用域

就是该变量能生效的范围, 一般是变量定义所在的代码块(定义在大括号里
如果 该变量 出了(不在) 创建它的 大括号里,来到外道大括号外面,该变量就不能使用)

讲到这里 我需要提醒一下的是

在 Java中 变量 分为两种:

1.成员变量;普通成员变量,静态成员变量(在后面讲类和对象的时候,会重点讲解)
 
 2.局部变量

我们今天所讲的 主要就是 局部变量的作用域

程序一
public class JavaFirst{
           int b =0; 
           此时 b 就是成员变量,也就是说,在 类的里面,main方法的外面 定义的变量,称为成员变量
    public static void main(String[] args) {
       int a = 10;// a 就是一个局部变量
    }

    public static void main2(String[] args) {
        // 注意这 main2, 和 main 完全是两码事,我只是偷个懒,
        // public static void func(String[] args) {} 这里 func 和 main2,就是通一个意思
        System.out.println(a);

    }
}
图16

程序二
public class JavaFirst{
    public static void main(String[] args) {
        {// 请注意,这只是举例子,这种写法,是不被允许的,以后别写这种代码
            int a =10;
        }
        System.out.println(a);
    }
}
图 17

这样也不行,因为 局部变量 a 的作用域,只在创建它的大括号里能用,出了大括号就不能用

接着上一个例子,那如果我这样写呢?
public class JavaFirst{
    public static void main(String[] args) {
        int a =0;
        {
            a = 99;
        }
        System.out.println(a);
    }
}
图18

由图可知,是可以输出a 的值,且a的值为 99,这是因为 a == 99,和输出语句,都在 局部变量 a 的作用域内(在创建局部变量a,所在的大括号里)

如何判断变量的作用域?

去找 离该变量最近的大括号,该大括号所包含的范围,就是 变量的作用域

变量的命名规则

硬性指标:

1. 一个变量名只能包含数字, 字母, 下划线
    2. 数字不能开头.
    3. 变量名对大小写很敏感. 即 num 和 Num 是两个不同的变量.
    注意: 虽然语法上也允许使用中文/美元符($)命名变量, 但是 强烈 不推荐这样做.</font>.

软性指标:

1. 变量命名要具有描述性, 见名知意(英文).
    2. 变量名不宜使用拼音(但是不绝对,最好别用就对了).
    3. 变量名的词性推荐使用名词(英文).
    4. 变量命名推荐 小驼峰命名法, 当一个变量名由多个单词构成的时候, 除了第一个单词之外, 其他单词首字母都大
    写.

程序1

public class JavaFirst{
    public static void main(String[] args) {
        int 3a = 0;
        int a3 = 0;
    }
}
图19

由图可知 符合 变量的命名规则 硬性指标 第二条 不能以数字开头

程序2

public class JavaFirst{
    public static void main(String[] args) {
        int Num = 1;
        int num = 2;
        System.out.println(Num);
        System.out.println(num);
      
    }
}
图20

由结果得知 符合 变量命名规则 硬性指标 第三条 变量名对大小写很敏感. 即 num 和 Num 是两个不同的变量.

常量

每种类型的变量 也对应着 一种相同类型 的 常量.

常量 指的是运行时类型不能发生改变.

常量主要有以下两种体现形式:

1.字面值常量

10int 字面值常量(十进制)
010int 字面值常量(八进制) 由数字 0 开头. 010 也就是十进制的 8
0x10int 字面值常量(十六进制) 由数字 0x 开头. 0x10 也就是十进制的 16
10Llong 字面值常量. 也可以写作 10l (小写的l)
1.0double 字面值常量. 也可以写作 1.0d 或者 1.0D
1.5e2double 字面值常量. 科学计数法表示. 相当于 1.5 * 10^2
1.0ffloat 字面值常量, 也可以写作 1.0F
trueboolen 字面值常量, 同样的还有 false
‘a’char 字面值常量, 单引号中只能有一个字符
“abc”String 字面值常量, 双引号中可以有多个字符.

2. final 关键字修饰的常量

public class JavaFirst{
    public static void main(String[] args) {
        int a = 10;// a 此时是一个变量
        a = 99;//变量是可以改变的
        System.out.println(a);

        // 如果在前面加个一个 final
        final int b = 10;// 是它具有常量属性,不可被改变,这点跟C语言中的const 是一样的功能
        b = 20;
        System.out.println(b);
    }
}
图21

由图可知, b 现在就相当于是 整形常量,值是无法改变的(另外体现出:常量的值,只能初始化一次,不像变量可以重复赋值)。

另外:
我建议常量标识符 用大写好一点,小写也行。你可以认为这是一种默认代码习惯
即:final int B = 10;
System.out.println(B);// 10

小知识点:

常量 在程序编译时,就已经确定了其值是什么

代码示例

public class JavaFirst{
    public static void main(String[] args) {
        int a =10;// a 是变量,是在程序运行时,才确定其值是什么
        final int b =20; // b就是一个常量,它的值,在程序还没有运行之前,在编译阶段就已经确定了其值是什么
         意味着  常量 的 值 确定的速度非常快
         有多快,比变量快(变量已经哭晕在厕所)
    }
}

类型转换

java 作为一个强类型编程语言, 当不同类型之间的变量相互赋值的时候, 会有教严格的校验

int 和 long/double 相互赋值

public class JavaFirst{
    public static void main(String[] args) {
        int a =10;
        long b =20;
        a=b;// 编译出错,提示 数值精度可能有所损失
        // 因为 long 8个字节,int是 4个字节,int 肯定是放不下long的

        b=a;// 编译通过
        // 因为 long 8个字节,int是 4个字节,long肯定是放得下int的。

        //有的人可能会说 我一个int类型,怎么可能放不下20,我int类型表示不服!
        //但你们要明白,你知道,不代表编译器知道,在程序执行之前,系统是不知道你输入数据有多大的
        // 所以 在Java中,Java为了提高代码的安全性,只要是类型不匹配的值,所占字节大的类型 是无法对 所占字节小的类型,进行赋值的
        // 而 所占字节小的类型 是可以对 所占字节大的类型进行赋值的。(就是所谓的 大吃小,小吃不下大)
        // 统统在编译时,不给予通过,程序报错并结束运行。
        
  (图22)// 其实在编译之前,它就提示你,一个类型所占字节大的 和 另一类型所占字节小的,大的无法对小的进行赋值
        // 也就是说 不存在 值的大小 是否存的下,只看类型之间,谁吃谁,大吃小没问题,小吃大,容易被撑死
        // 这里又在一次体现出 Java 的安全性,也体现出Java是一门强势语言,对类型的检查非常严格
           你程序还没运行,就提示你有错误,你想出错都难(注意 a = b 下面的红色波浪线就是在提醒你的写法出错了)
    }
}

图22

那么 你说,我就想 把 b 的值 存入 a 里面,好的,没问题,这就需要强制类型转换

public class JavaFirst{
    public static void main(String[] args) {
        int a =10;
        long b = 20;
        a = (int)b;// 把 b 的类型强制类型转换成 int,然后赋给a
        // 相当于 一个人给你打包票,我做事没问题!

        System.out.println(a);//图 23
      
    }
}
图23

结果得知,是可行的。
但是注意一点,任何强制类型转换都是有风险的,你再牛逼也有翻车时候

结论:

不同 数字类型 的 变量 之间赋值, 表示 范围更小的类型能隐式转换成范围较大的类型, 反之则不行.

int 和 boolean 相互赋值

public class JavaFirst{
    public static void main(String[] args) {
        int a = 10;
        boolean b = true;
        b = a; // 编译出错, 提示不兼容的类型
        a = b; // 编译出错, 提示不兼容的类型
   // 因为 boolean 根本就不是一个数字或者说类型都不一样,所以两者根本就无法进行相互赋值
        // 图 24
    }
}

图24

结论: int 和 boolean 是毫不相干的两种类型, 不能相互赋值

int字面值常量 给 byte 赋值

public class JavaFirst{
    public static void main(String[] args) {
        // 注意 byte 的取值范围 -128 ~127
        byte a = 100; // 编译通过

        // 只要超过 byte 的取值范围,编译器会将 赋给 byte变量的值 认为是另一个类型的值,且比 byte 所占字节大小更大的类型
        byte b = 256; // 编译报错, 提示 从int转换到byte可能会有损失
    }// 图25
}

图25

结论: 使用字面值常量赋值的时候, Java 会自动进行一些检查校验, 判定赋值是否合理

拓展

程序一

public class JavaFirst{
    public static void main(String[] args) {
        byte a = 10;
        byte b = 20;
        byte c = a+b;
         这样写是错的。
        // 因为在CPU中,两个类型的数据(类型小于4个字节的数据)在进行运算时,会整形提升
        // 也就是说 a 与 b,在进行加法运算时,发生整形提升,两者变为了 int 类型的数据
        // 其结果当然也是 int 类型,所以无法将其运算结果赋给 byte类型的 变量 c
    }// 图 26

}
图26

程序二

public class JavaFirst{
    public static void main(String[] args) {
        byte a =10;
        byte b =20;
        byte c = 10+20;
        System.out.println(c);
        这样写没错,为什么?
        // 因为在 CPU 看来,这就是 两个常量相加,而不是两个变量相加(就该程序而言:如果是两个变量相加,就需要整形提升,其结果数据是int类型)
        // CPU 将两个常量相加的结果(30) 赋给 一个类型的变量(byte c)
    }
}// 图29
图29

程序三

public class JavaFirst{
    public static void main(String[] args) {
        int a = 0;
        double b = 10.5;
        a = (int)b;
        System.out.println(a);
    }
}// 图 28
图28

结论:

使用 (类型) 的方式可以将 double 类型强制转成 int. 但是

  1. 强制类型转换可能会导致精度丢失. 如刚才的例子中, 赋值之后, 10.5 就变成 10 了, 小数点后面的部分被忽略.
  2. 强制类型转换不是一定能成功, 互不相干的类型之间无法强转

总得来说,只要是强制类型转换,都存在一定风险,正如我上面所说的 你再牛逼也会翻车。

类型转换小结

1. 不同 数字类型 的 变量之间赋值, 表示 范围更小的类型 能隐式转换成 范围较大的类型
    (这里不是整形提升,就是单纯的 大吃小:数字类型 所占字节小的变量,它的所有取值,都可以 存储到 比它所占字节更大 的 数字类型 变量 当中).

    2. 如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失.
    3. 将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查.

理解数值提升

程序实例

public class JavaFirst{
    public static void main(String[] args) {
        int a = 10;
        long b = 20;
        int c = a+b;
         这样为什么会错呢?
         因为CPU中,做类型提升时,小的类型会向大的类型进行类型提升(大的类型 所占字节 要大于4字节,否则,提升为整形)
         也就是说 a 与 b,在进行加法运算时,发生类形提升,两者变为了 long 类型的数据
         其结果当然也是 long 类型,所以无法将其运算结果赋给 int 类型的 变量 c
 需要强制类型转换才能存进去, int c = (int)(a+b);
    }// 图 27

}

图27

讲到这里,有必要说一下 整形提升的意义何在?

为了效率高!.

类型提升小结:

1. 不同类型的数据混合运算, 范围小的会提升成范围大的.
    2.由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据. 为了硬件上实现方便, 诸如 byte 和 short 这种低于
4 个字节的类型, 会先提升成 int, 再参与计算

int 和 String 之间的相互转换

int 转换 字符串

public class JavaFirst{
     public static void main(String[] args) {
         int a = 10;
         String ret = String.valueOf(a);// valueOf 小驼峰结构,第一个词的首字母不大写,后面的都大写
         // 这是Java当中,把 数字 转换成 字符串 的方法,

         System.out.println(ret);
     }
 }// 图30 31

图30

图31

字符串转换int

public class JavaFirst{
    public static void main(String[] args) {
        String ret = "123";
        int i = Integer.valueOf(ret);// valueOf 小驼峰结构,第一个词的首字母不大写,后面的都大写
        // 这是Java当中,把字符串转换成数字的方法,C语言里面用的是 atoi 库函数

        System.out.println(i);
        // 在这里再讲一次
// java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类
// Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量
        // 简单来使 Integer 是一个 类,是 int 的包装类,类里面包含这很多与int相关功能。
    }
}// 图32 33

图32

图33

运算符

算术运算符

基本四则运算符   +   -    *     /       %

+   -    *  规则比较简单, 注意的是除法

程序一
public class JavaFirst{
    public static void main(String[] args) {
        int a = 1;
        int b = 2;
        System.out.println(a / b);
    }// 图 34
}

结果为 0,为什么呢?不应该是 0.5吗?
因为 两个整数相除,其结果也是整数,
所以 取结果的整数为 0,作为最后结果。

0 不能作为除数(重点)

public class JavaFirst{
    public static void main(String[] args) {
        int a =1;
        int b =0;
        System.out.println(a/b);
    }
}// 图 35

图35

该错误被称为 异常错误(术语)
只要程序抛出 异常错误,程序在异常错误的位置,结束程序的运行

% 取余(求模/取模,说白了就是取余数)

public class JavaFirst{
    public static void main(String[] args) {
        System.out.println(10%3);
        // 10 除 3 ,取余 肯定是 1,附图36

        //在 Java中 可以对 小数 求余
        System.out.println(11.5 % 2);// 图37

    }
}

图36

图37

来看一道题

我赌你们有些人绝对会算错下面取余的题
public class JavaFirst{
    public static void main(String[] args) {
        System.out.println(-10%3);
        System.out.println(10%-3);
        System.out.println(-10%-3);
   // 结果见图 38
    }
}

图38

增量赋值运算符(复合运算符) +=   -=   *=   /=   %=

public class JavaFirst{
    public static void main(String[] args) {
        int a = 10;
        a+=1;// 等价于 a = a + 1 == 10+1 == 11
        System.out.println(a);
        // 图39

        // 但是请注意
        short s = 10;
        s= s+1;// 这样写会出错,因为涉及到运算,会进行整形提升,s(这里代表的是常量10,不是变量 s) 和 1 都为 int类型
        // 其结果也是int类型,所以无法赋给 short类型变量 s
        // 如果想要 将其结果,强制类型转换
        s = (short)(s+1);// 图 40

        //但是! 如果使用 符合运算符,奇迹再现
        s += 1;// 图 41
        // 由图可知这样写,没有出错。
        // 因为复合运算符,自带强制类型转换
    }
}

图39

图40

图41

自增/自减运算符 ++ –

后置加加

public class JavaFirst{
    public static void main(String[] args) {
        int a =10;
        int b = a++;// 先将a的值(10)赋给 b(b==10),然后自增加1,a == 11
        System.out.println(a);
        System.out.println(b);
    }//图42
}
图 42

前置加加

public class JavaFirst{
    public static void main(String[] args) {
        int a =10;
        int b = ++a;// a先自增加1,a == 11,再将其值赋给 b(b==11)
        System.out.println(a);
        System.out.println(b);
    }//图43
}
图43

后置 减减

public class JavaFirst{
    public static void main(String[] args) {
        int a =10;
        int b =a--;// 先将a的值 10 赋给 b(b=10),a再自减1 a == 9
        System.out.println(a);
        System.out.println(b);
    }// 图44
}
图 44

前置减减

public class JavaFirst{
    public static void main(String[] args) {
        int a =10;
        int b =--a;// a先自减1 a == 9,再将a的值 9 赋给 b(b=9),
        System.out.println(a);
        System.out.println(b);
    }// 图45
}
图45

结论:

1. 如果不取自增运算的表达式的返回值, 则前置自增和后置自增没有区别.
    2. 如果取表达式的返回值, 则前置自增的返回值是自增之后的值, 后置自增的返回值是自增之前的值.

关系运算符(判断数据)

关系运算符主要有六个:
  ==      !=       <        >        <=         >=
public class JavaFirst{
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        //条件为真,返回 true,否,则返回 false
        System.out.println(a == b);
        System.out.println(a != b);
        System.out.println(a < b);
        System.out.println(a > b);
        System.out.println(a <= b);
        System.out.println(a >= b);
    }
}//图46,由结果得知,所有关系运算符的返回值 都是布尔类型数据(true 和 false)

图46

拓展

在Java中,判断条件是否成立,是根据布尔类型的
public class JavaFirst{
    public static void main(String[] args) {
        if(true)//条件为真,执行if语句
        {
            ;
        }
        if(false)// 条件为假,不执行if语句
        {
            ;
        }
        //if(0) 和 if(1)// 这种写法在Java是不存在的
    }
}

逻辑运算符

逻辑运算符主要有三个:
  &&      ||      !
注意: 逻辑运算符的操作数(操作数往往是关系运算符的结果)和返回值都是 boolean 类型的数据(true 和 false)

逻辑与 &&

规则: 两个操作数都为 true, 结果为 true, 否则结果为 false

表达式1 && 表达式2,都为 true, 结果为 true, 否则结果为 false
而且 逻辑与 支持 短路
什么意思呢? 如果 表达式1 为 假,后面的表达式2就不执行了,因为没必要
逻辑或: 双true出true,有false出false
有一个false,整个表达式的结果就为 false,所以 表达式2 看与不看(执不执行)都没多大的关系

程序实例

public class JavaFirst{
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = 30;
        System.out.println(a < b && b < c);
        // a确实小于b,b也确实小于 c
        // 即 双 true 出true
        //所以输出结果为 true
    }// 图 47
}
图 47

逻辑或 ||

规则: 两个操作数都为 false, 结果为 false, 否则结果为 true

也存在 短路现象
表达式1 || 表达式2
有 true 出 true,双 false 出 false
只要表达式1 为真(true),整个表达式就为true,表达式2 就不用执行了,因为不影响结果

程序一

public class JavaFirst{
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = 30;
        System.out.println(a < b || b < c);
        // a 确实小于 b, a<b 为真(true),整个表达式为 true
        // 表达式2(b<c) 就没有被执行
    }
}// 图48
图48

逻辑非 !

规则: 操作数为 true, 结果为 false; 操作数为 false, 结果为 true(这是个单目运算符, 只有一个操作数).
public class JavaFirst {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
// System.out.println(!a<b);
        // 由图49可知,!后面跟着不是 boolean 类型的数据
        // 所以这种写法是错误的

        // 如果是这样写,就没错
        System.out.println(!(a<b));//图50
        //因为 所有关系运算符(我们这里是 < )的返回值 都是布尔类型数据(true 和 false)
    }

}
图49

图50

讲到这里,我们看到了逻辑运算符存在着“短路”的情况,现在我们来了解一下 “短路求值”

&& 和 || 遵守短路求值的规则

System.out.println(10 > 20 && 10 / 0 == 0); // 打印 false
    System.out.println(10 < 20 || 10 / 0 == 0); // 打印 true
这里值详解 逻辑与,逻辑或 大家可以自己尝试着思考
public class JavaFirst{
    public static void main(String[] args) {
        System.out.println(10>20 && 10/0 == 0);
        // 大家注意,这个表达式是存在错误的
        // 除数 是不能为 0的
        // 那么运行的结果会是如何?
        //图 51
    }
}
图51

那上面的代码这样写呢?
public class JavaFirst{
    public static void main(String[] args) {
        System.out.println(10<20 && 10/0 == 0);
        // 与上不同,这里是小于号,10 确实小于20,所以为真
        // 继续执行程序
        // 然后,它才能检测到 除数 是不能为 0的
        // 那么运行的结果可以想象
        //图 52
    }
}
图 52

结论
1. 对于 && , 如果左侧表达式值为 false,则表达式的整体的值一定是 false, 无需计算右侧表达式
    2. 对于 ||, 如果左侧表达式值为 true, 则表达式的整体的值一定是 true, 无需计算右侧表达式

位运算符

Java 中对数据的操作的最小单位不是字节, 而是二进制位(bit).
   位运算符主要有四个:
 &     |      ~      ^
位操作表示 按二进制位运算. 计算机中都是使用二进制来表示数据的(01构成的序列), 按位运算就是在按照二进制位的每一位依次进行计算.

按位与 &

直接举例子

 0000 1010
 0000 1000 上下对应着看,如果两个二进制位都是 1, 则结果为 1, 否则结果为 0
 0000 1000

结论

一个数的二进制数 与 另一个数的二进制数,相对应的二进制位上的数字,都是1,则结果为1,否则为0
假设两个数字 5 和 6,这里我们不写太多,就写 4个bit位,因为它们的数值都不是很大,就不浪费空间了
5  0101
6  0110
   0100 其结果对应的十进制数为 4

按位或 |

如果两个二进制位都是 0, 则结果为 0, 否则结果为 1
依然是假设两个数字 5 和 6
5  0101
6  0110
   0111 其结果对应的十进制数为 7

结论

一个数的二进制数 与 另一个数的二进制数,相对应的二进制位上的数字,都是0,则结果为0,否则为1

注意: 当 & 和 | 的操作数为整数(int, short, long, byte) 的时候, 表示按位运算, 当操作数为 boolean 的时候, 表示逻辑 运算.

注意!!!

&(按位与) 和 |(按位或) (不推荐使用,因为在Java当中使用的太少了,所以大家只需要了解一下就可以了)
 & 和 | 如果操作数为 boolean 的时候, 也表示逻辑运算. 但是和 && 以及 || 相比, 它们不支持短路求值
 System.out.println(10 > 20 & 10 / 0 == 0); // 程序抛出异常
 System.out.println(10 < 20 | 10 / 0 == 0); // 程序抛出异常
 不会有人这么奇怪的代码的,大家也别写!!!

按位异或 ^

如果两个数字的二进制位相同, 则结果为 0, 相异则结果为 1
依然是假设两个数字 5 和 6
5  0101
6  0110
   0011 其结果对应的十进制数为 3

按位取反 ~

如果该位为 0 则转为 1, 如果该位为 1 则转为 0
我这里写一个 32 位 二进制数
-1的补码
1111 1111 1111 1111 1111 1111 1111 1111
 进行按位取反
0000 0000 0000 0000 0000 0000 0000 0000
由结果得知:按位取反,是 数值位 和 连符号位一起取反,这一点需要注意

注意:

1. 0x 前缀的数字为 十六进制 数字. 十六进制可以看成是二进制的简化表示方式. 一个十六进制数字对应 4 个二进制位.
    2. 十六进制的f 表示 10 进制的 15, 也就是二进制的 1111
    3. printf 能够格式化输出内容, %x 表示按照十六进制输出.
    4. \n 表示换行符

小要求:需掌握 进制 之间转换

这个不讲,真要讲的话,我的习惯可能写的非常细,再加上将每个进制转换都讲清楚的话,感觉要写一篇 接近 万字的博客
你们自行了解,我就不再增长本文章的长度了

移位运算

移位运算符有三个:

<<    >>     >>>
都是按照二进制位来运算

另外 整数在内存中存的是补码,详细看这篇文章0operator(操作符)- 重置版,C语言和Java 这方面是一样的

左移 <<

最左侧的二进制位不要了,最右边补一个零
例子
依然是 5 ,只不过这次是 32位,方便你们理解
0000 0000 0000 0000 0000 0000 0000 0101  (5)
5 << 1,5的二进制位 左移1位
0000 0000 0000 0000 0000 0000 0000 101  (最左侧的零其实已经挤掉了,由于整个二进制数向左移动一位,导致最右边空出一位)
最右边空出一位,补0
0000 0000 0000 0000 0000 0000 0000 1010 转换成10进制数 为 10

右移 >>:

最右侧位不要了, 最左侧补符号位
这里我就举6
0(最高位/符号位)  000 0000 0000 0000 0000 0000 0000 0110 (6)
6 >> 1  6的二进制位 右移1位
000 0000 0000 0000 0000 0000 0000 0011(最右侧的零其实已经挤掉了,由于整个二进制数向右移动一位,导致最左边空出一位)
补位, 按照原先的6的二进制数的最高位(符号位进行补位),1为负,0为正
是 0(正)就补0,是1(负)就补1
因为 6 的原先的二进制数的最高位是 0(正),所以我们要补个零
0000 0000 0000 0000 0000 0000 0000 0011 转换成10进制数 为 3
在假设一个 负数 -1
1111 1111 这里我们只写8位
-1 >> 1
 111 1111 (最右侧的一其实已经挤掉了,由于整个二进制数向右移动一位,导致最左边空出一位)
补位, 按照原先的 -1 的二进制数的最高位(符号位进行补位),1为负,0为正
是 0(正)就补0,是1(负)就补1
因为 -1 的原先的二进制数的最高位是 1(负),所以我们要补个1
1111 1111 你会发现结果跟原来的二进制码相比,没有任何变化

无符号右移 >>>

最右侧位不要了, 最左侧补 0
这回特别点,0x ff ff ff ff
 11111111 11111111 11111111 11111111
    ff       ff       ff       ff
0xffffffff >>> 1 :意思是0xffffffff 无符号右移一位
  1111111 11111111 11111111 11111111
 最左侧补 0(无符号右移,不管你符号位是0还是1,统一补0)
 0111 1111 11111111 11111111 11111111
0x 7   f     f  f    f   f    f  f

另外请记住 在Java中是没有 无符号左移的,没有意义

左移都是补零,(因为二进制数最右边是没有符号位的,所以统一补0)

注意:

1. 左移 1 位, 相当于原数字 * 2. 左移 N 位, 相当于原数字 * 2 的N次方.
    2. 右移 1 位, 相当于原数字 / 2. 右移 N 位, 相当于原数字 / 2 的N次方.
    3. 由于计算机计算移位效率高于计算乘除, 当某个代码正好乘除 2 的N次方的时候可以用移位运算代替.
    4. 移动负数位或者移位位数过大都没有意义(二进数数只有32位,你要移动35位,没意义)

条件运算符

条件运算符只有一个:

表达式1 ? 表达式2 : 表达式3
又称 三目运算符
意思是 表达式1 为真,返回表达式2,为假,返回表达式3
意味着 表达式1必须为 布尔表达式

举个例子 求两个数的最大值

public class JavaFirst{
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int max = a > b ? a : b;
        // 该三目运算符表达的意思是
        //如果 a大于b为真(true) ,返回 a
        //否则(a其实是小于b的) 为 假(false),返回b

        // 这里 b 是大于 a的,不满足 a 大于 b的条件
        // 所以为假(false),返回 b(20)
        System.out.println(max);
    }// 图53
}
图53

运算符的优先级

程序一

public class JavaFirst{
    public static void main(String[] args) {
        System.out.println(1 + 2 * 3);
    }//结果为 7, 说明先计算了 2*3 , 再计算 1+
    // 图54
}
图 54

接着程序一, 如果你想算出 9,用小括号将 1 和 2 括起来

因为小括号的优先最高,将其括起来,编译器先计算 小括号里的内容

程序如下

public class JavaFirst{
    public static void main(String[] args) {
        System.out.println((1 + 2) * 3);
    }//结果为 9, 说明先计算了小括号里 1+2 , 再计算 *3
    // 图55
}
图 55

运算符之间是有优先级的. 具体的规则我们不必记忆. 只需要根据自己的逻辑加括号就可以

小结

1. % 操作再 Java 中也能针对 double 来计算.
    2. 需要区分清楚 前置自增 和 后置自增之间的区别.
    3. 由于 Java 是强类型语言, 因此对于类型检查较严格, 因此像 && 之类的运算操作数必须是 boolean.
    4. 要区分清楚 & 和 | 什么时候是表示按位运算, 什么时候表示逻辑运算.
    整体来看, Java 的运算符的基本规则和 C 语言基本一致

本文在这里结束了。

相关文章

微信公众号

最新文章

更多

目录