java基础(01)

数据类型和变量

数据类型用于对数据归类,以便于理解和操作。对Java语言而言,有如下基本数据类型。

  • 整数类型:有4种整型byte/short/int/long,分别有不同的取值范围;
  • 小数类型:有两种类型Hoat/doublc,有不同的取值范围和精度;
  • 字符类型:char,表示单个字符;
  • 真假类型:boolean,表示真假。

为了操作数据,需要把数据存放到内存中。所谓内存在程序看来就是一块有地址编号的连续的空 间,数据放到内存中的某个位置后,为了方便地找到和操作这个数据,需要给这个位置起一个名字。编程 语言通过变量这个概念来表示这个过程。

变量就是给数据起名字,方便找不同的数据,它的值可以变,但含义不应变。

基本数据类型

整数类型

整数类型有byte、short、int和long,分别占1、2、4、8个字节

image-20211216225240791

赋值操作很简单,只需要把对应的值赋给定义的变量即可,但是要注意赋值的范围不能超出变量类型的最大取值范围。

1
2
3
4
5
6
byte b = 23; 
short s = 3333;
int i = 9999;
long 1 = 32323;
// 但是,在给long类型赋值时,如果常量超过了int的表示范围,需要在常量后面加大写或小写字母L, 即L或1
long a = 3232343433L;

小数类型

小数类型有float和double,占用的内存空间分别是4和8字节,有不同的取值范围和精度,double表示 的范围更大,精度更高,E表示以10为底的指数,E后 面的+号和-号代表正指数和负指数,例如:1.4E-45表示1.4乘以10的-45次方。

image-20211216230055879

赋值操作

1
2
3
double d = 333.33;
// 但对于float,需要在数字后面加大写字母F或小写字母f
float f = 333.33f;

真假类型

真假(boolean)类型很简单,直接使用true或false赋值,分别表示真和假

1
boolean b = true; b = false;

字符类型

字符类型char用于表示一个字符,这个字符可以是中文字符,也可以是英文字符,char占用的内存空 间是两个字节。赋值时把常,字符用单引号括起来,不要使用双引号

1
char c = 'c';

前面介绍的赋值都是在声明变量的时候就进行了赋值,但这不是必需的,可以先声明变量,随后再 进行赋值。

1
2
3
4
int a = 1;
int b = 2;
//2乘以a的值再加上b的值赋给c
int c = 2 * t + b;

本质

char本质上是一个固定占用两个字节的无符号正整数,这个正整数对应于Unicode编号,用于表示那个Unicode编号对应的字符。

由于固定占用两个字节,char只能表示Unicode编号在65536以内的字符,而不能表示超出范围的字符。

那超出范围的字符怎么表示呢?使用两个char。类String有一些相关的方法,后续文章介绍。

数组类型

基本类型的数组有3种赋值形式

1
2
3
4
int[] arr = {1,2,3};
int[] arr = new int[]{1,2,3};
int[] arr = new int[3];
arr[0]=1; arr[1]=2; arr[2]=3;

数组的长度可以动态设置,但是长度一旦设置成功是不可以更改的,但只能读,不能改。

image-20211216231353239

数组和基本类型的区别

一个基本类型变量,内存中只会有一块对应的内存空间。但数组有两块,一块用于存储数组内容本身,另一块用于存储内容的位置。用一个例子来说明,有一个int变量a,和一个int数组变量arr

image-20211216232517756

为什么数组要用两块空间

1
2
3
4
int[] arrA = {1,2,3};

int[] arrB = {4,5,6,7};
arrA = arrB;

这个代码中,arrA初始的长度是3,arrB的长度是4,后来将arrB的值赋给了arrA。如果arrA对应的内存空间是直接存储的数组内容,那么它将没有足够的空间去容纳arrB的所有元素。

用两块空间存储,这个就简单的多,arrA存储的值就变成了和arrB的一样,存储的都是数组内容{4,5,6,7}的地址,此后访问arrA就和arrB是一样的了,而arrA {1,2,3}的内存空间由于无人引用会被垃圾回收

由上,也可以看出,给数组变量赋值和给数组中元素赋值是两回事。给数组中元素赋值是改变数组内容,而给数组变量赋值则会让变量指向一个不同的位置

image-20211216232936531

运算

给数据赋值,有了初始值之后,可以对数据进行运算。计算机之所以称为”计算”机,是因为发明它的主要目的就是运算。运算有不同的类型,不同的数据类型支持的运算也不一样,本文介绍Java中基本类型数据的主要运算。

  • 算术运算:主要是日常的加减乘除
  • 比较运算:主要是日常的大小比较
  • 逻辑运算:针对布尔值进行运算

加减乘除注意事项

运算时要注意结果的范围,使用恰当的数据类型。两个正数都可以用int表示,但相乘的结果可能就会超,超出后结果会令人困惑,例如:

1
2
int a = 2147483647*2; //2147483647是int能表示的最大值
// a = -2 超出int最大范围,具体 -2 在后面详解

需采用long的形式作为运行变量的接受变量,只改为long也是不够的,因为运算还是默认按照int类型进行,需要将至少一个数据表示为long形式,即在后面加L或l:

1
long a = 2147483647*2L;

整数相除不是四舍五入,而是直接舍去小数位,例如:

1
double d = 10/4;

结果是2而不是2.5,如果要按小数进行运算,需要将至少一个数表示为小数形式,或者使用强制类型转化,即在数字前面加(double),表示将数字看做double类型,如下所示任意一种形式都可以:

1
2
double d = 10/4.0;
double d = 10/(double)4;

自增(++)/自减(–)

自增/自减是对自己做加一和减一操作,但每个都有两种形式,一种是放在变量后,例如a++, a–,另一种是放在变量前,例如++a, –a。

区别在于还有其他操作的时候。放在变量后(a++),是先用原来的值进行其他操作,然后再对自己做修改,而放在变量前(++a),是先对自己做修改,再用修改后的值进行其他操作。

image-20211216234502389

比较运算

比较运算就是计算两个值之间的关系,结果是一个布尔类型(boolean)的值。

比较操作符有:大于(>),大于等于(>=),小于(<),小于等于(<=),等于(==),不等于(!=)。

首先,它使用两个等号==,而不是一个等号(=),为什么不用一个等号呢?因为一个等号(=)已经被占了,表示赋值操作。

另外,对于数组,==对于 基本数据类型 比较的是值,但是对于 对象类型 比较的是内存地址,在后续说明。

逻辑运算

逻辑运算根据数据的逻辑关系,生成一个布尔值true或者false。逻辑运算只可应用于boolean类型的数据,但比较运算的结果是布尔值,所以其他类型数据的比较结果可进行逻辑运算。

逻辑运算符具体有:

  • 与(&):两个都为true才是true,只要有一个是false就是false

  • 或(|):只要有一个为true就是true,都是false才是false

  • 非(!):针对一个变量,true会变成false, false会变成true

  • 异或(^):两个相同为false, 两个不相同为true

  • 短路与(&&): 和&类似,不同之处马上解释

  • 短路或 (||):与|类似,不同之处马上解释

运算符优先级

一个稍微复杂的运算可能会涉及多个变量,和多种运算,那哪个先算,哪个后算呢?程序语言规定了不同运算符的优先级,有的会先算,有的会后算,大部分情况下,这个优先级与我们的常识理解是相符的。

但在一些复杂情况下,我们可能会搞不明白其运算顺序。但这个我们不用太操心,可以使用括号()来表达我们想要的顺序,括号里的会先进行运算,简单的说,不确定顺序的时候,就使用括号。

整数的二进制表示与位运算

十进制

比如123,表示的1*(10^2) + 2*(10^1) + 3*(10^0),从右向左,第一位乘以10的0次方, 即1,第二位乘以10的1次方,即10,第三位乘以10的2次方,即100,依次类推。换句话说,每个位置都有一个位权,从右到左,第一位为1,然后依次乘以10,即第二位为10,第三位为100,依次类推。十进制就是正整数

正整数转成二进制

要点一定一定要记住哈:除二取余,然后倒序排列,高位补零。

image-20211218000345272

83除以2得到的余数分别为1100101,然后咱们倒着排一下,83所对应二进制就是1010011

负整数转二进制

对于正整数二进制取反+1,高位补0,整数有四种类型,byte/short/int/long,分别占1/2/4/8个字节,即分别占8/16/32/64位

  • -1:1的原码表示是00000001,取反是11111110,然后再加1,就是11111111。
  • -2:2的原码表示是00000010,取反是11111101,然后再加1,就是11111110。
  • -127:127的原码表示是01111111,取反是10000000,然后再加1,就是10000001。

小数转二进制

对小数点以后的数乘以2,有一个结果吧,取结果的整数部分(不是1就是0喽),然后再用小数部分再乘以2,再取结果的整数部分……以此类推,直到小数部分为0或者位数已经够了就OK了

1
2
3
4
5
6
7
8
9
10
11
12
13
0.12345

0.12345 * 2 = 0.2469 0

0.2469 * 2 = 0.4938 0

0.4938 * 2 = 0.9876 0

0.9876 * 2 = 1.9752 1

0.9752 * 2 = 1.9504 1

...........忽略,直至小数部分为0,排序

十六进制

二进制写起来太长,为了简化写法,可以将四个二进制位简化为一个0到15的数,10到15用字符A到F表示,这种表示方法称为16进制,如下所示:

image-20211218110855495

比如123转十六进制

123 / 16 = 7 余数 11,十六进制表示法。0x + 7B,B就是11,结果就是:0x7B

java正整数转换

1
2
3
4
5
int a = 25;
System.out.println(Integer.toBinaryString(a)); //二进制
System.out.println(Integer.toHexString(a)); //十六进制
System.out.println(Long.toBinaryString(a)); //二进制
System.out.println(Long.toHexString(a)); //十六进制

位运算

位运算是将数据看做二进制,进行位级别的操作,Java不能单独表示一个位,但是可以用byte表示8位,可以用16进制写二进制常量。比如: 0010表示成16进制是 0x2, 110110表示成16进制是 0x36。

位运算有移位运算和逻辑运算。

移位有:

  • 左移:操作符为<<,向左移动,右边的低位补0,高位的就舍弃掉了,将二进制看做整数,左移1位就相当于乘以2。
  • 无符号右移:操作符为>>>,向右移动,右边的舍弃掉,左边补0。
  • 有符号右移:操作符为>>,向右移动,右边的舍弃掉,左边补什么取决于原来最高位是什么,原来是1就补1,原来是0就补0,将二进制看做整数,右移1位相当于除以2。

例如:

1
2
3
int a = 4; // 100
a = a >> 2; // 001,等于1
a = a << 3 // 1000,变为8

逻辑运算有:

  • 按位与 &:两位都为1才为1
  • 按位或 |:只要有一位为1,就为1
  • 按位取反 ~: 1变为0,0变为1
  • 按位异或 ^ :相异为真,相同为假

大部分都比较简单,就不详细说了。具体形式,例如:

1
2
3
int a = ...; 
a = a & 0x1 // 返回0或1,就是a最右边一位的值。
a = a | 0x1 //不管a原来最右边一位是什么,都将设为1

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!