【JavaSE】数据类型和运算符

简介: Java中一共有8中基本数据类型,此外还有很多引用数据

一. 数据类型

Java中一共有8中基本数据类型,此外还有很多引用数据,它们如下图所示:

03cc726e061548ec9eec85b4cdd9e32e.png


1. 整数类型

注意:Java当中的整数没有所谓的无符号(unsigned)类型,统一都是有符号的。


1.1 整型(int)

下面定义一个整型变量:


int num = 10;


注意事项:


变量指的是程序运行时其值可以改变的量

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

变量名是变量的标识,后续都是通过这个名字来使用变量

int 表示变量的类型是一个整型

Java中 = 表示赋值(和数学不一样,数学中表示等价),意思是给变量设置一个初始值或重新给值。

初始化操作是可选的,但是建议创建变量的时候都显式初始化

不要忘记最后的分号,否则会编译失败

int类型的大小和表示范围


在Java中,一个int类型的变量占4个字节(即32个bit位)和操作系统没有直接关系,这充分说明了Java的可移植性强。4个字节表示的数据范围是[-2^31, +2^31-1]:

44b47ea34e6d42499ec9b4f5c8b14785.png



使用以下代码查看Java中的int数据范围:


// 输出:2147483647
System.out.println(Integer.MAX_VALUE);
// 输出:2147483648
System.out.println(Integer.MIN_VALUE);


PS:Integer是int的包装类,相当于int的puls版本。


如果运算的结果超出了int的最大范围,就会出现溢出的情况:

0d540bd7317c4e658ec5384b3373dfa9.png


1.2 长整型(long)

21亿这样的数字对于当前的大数据时代来说,是很容易超出的,针对这种情况,我们就需要使用更大范围的数据类型来表示。Java中提供了long类型。


下面定义三个长整型变量:


// long类型变量的值有以下三种写法
long num1 = 10;
long num2 = 10L;
long num3 = 10l;


注意事项:


初始化设定的值为10L表示这是一个长整型的字面常量,10l也可以。

使用10初始化也可以,10字面常量的类型是int,赋值时会发生整型提升。10L的类型是long,使用10L或者10l更好一些。

Java中没有long long类型。

long类型的大小和表示范围


Java中long类型占8个字节,表示的数据范围[-2^63, +2^63-1],使用以下代码查看Java中长整型的数据范围:


// 输出:9223372036854775807
System.out.println(Long.MAX_VALUE);
// 输出:-9223372036854775808
System.out.println(Long.MIN_VALUE);


这个数据范围远超过int的表示范围,足够绝大部分的工程场景使用。


1.3 字节类型(byte)

只占一个字节的byte类型只能表示整数;注意和C/C++中的char区分开,char表示出来的是字符。


byte num = 1;

注意事项:


字节类型和字符类型互不相干。

字节类型表示的也是整数。只占一个字节, 表示范围较小[-128, +127]。

在Java当中,整数类型都是有取值范围的,存储数据的时候,不要超过那个范围,编译器会针对类型对变量的值进行检查是否在合法范围内。

17208ea5d2fd4b31a5e7219d93fa98cc.png


1.4 短整型(short)

和C/C++一样,Java中也有short类型。


short num = 10;

注意事项:


short类型占用2个字节,表示的数据范围是[-32768,+32767]。

这个表示范围比较小,一般不推荐使用。

2. 浮点数类型

浮点数类型有两种:float、double,它们能表示的精度不一样,后者要大一些。


2.1 双精度浮点型(double)

double a = 1.0;
double b = 2.0;
System.out.println(a / b);// 0.5


Java中的double是8个字节,但实际上浮点数的内存布局和整数差别很大,我们看下面这段代码:


double num = 1.1;
// 输出 1.2100000000000002
System.out.println(num * num);


Java中double类型的内存布局遵守IEEE 754标准(和C语言一样),尝试使用有限的内存空间表示可能的无限小数,这势必会存在一定的精度误差,所以不能单纯地用2^n形式表示来表示浮点数的数据范围。


2.2 单精度浮点型(float)

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


float num = 1.1f;// 写作1.1F也可以,但不能不写

注意:float类型的变量在初始化给值时一定要加上f或F的标识。不然会报错:java: 不兼容的类型: 从double转换到float可能会有损失,因为在Java中浮点数字面常量值的类型默认是double(8字节)的,如果直接把它赋值给float(4字节)变量会有数据损失。


4. 字符类型(char)

char ch = 'A';
// 打印字符A的三种方法
System.out.println(ch);// 通过char类型变量来打印
System.out.println('A');// 通过字符的字面常量来打印
System.out.println((char)65);// 通过'A'的Unicode码来表示


注意事项:


Java中使用单引号 + 单个字母的形式表示字符的字面常量。

计算机中存储的字符本质上还是一个整数,在C语言中使用ASCII来表示字符,而Java中使用Unicode表示字符,因此在Java中一个字符占用两个字节,两个字节的话可以表示的字符种类更多,包括中文。

c4f1407355154b9b994303bcdd4bea86.png


4. 字符串类型(String)

和上面的类型不同,String不是基本类型,而是引用类型。Java中使用双引号 + 若干字符的方式表示字符串常量值:

ce6a35b31cfa40abab58fdc51203a115.png


注意事项:


字符串中的一些特定的不太方便直接表示的字符需要进行转义:

16010bfe395341adaff56bfc86628bf9.png


字符串的 + 操作,表示字符串拼接:


873e758e8b354a7ca789bc277d8987c7.png

当一个 + 表达式两边中存在至少一个字符串操作数的时候,执行的都是字符串拼接行为:


5. 布尔类型(boolean)

相当于C++中的bool类型,在Java中叫做boolean,不过二者还是有区别的。


boolean flag = true;

注意事项:


boolean类型的变量只有两种取值:true和false,不能再有其他取值。

Java中的boolean类型和int不能相互转换,不存在0表示false,非0表示true这样的说法。


fa9403acc7ab47bb8046bd1720398d5f.png

在JVM的规范当中,并没有规定布尔类型的大小。有些书会说1bit,有些书又说是1byte,这个没有明确规定。

6. 几点补充

6.1 变量命名规则

硬性规则(必须遵守):


变量名必须由数字、字母(大小写都可)、下划线构成,不能包含其他特殊符号。

数字不能开头:

5b32efc42c8c45ab9f244882c94e985b.png


变量名不能和Java的“关键字”重复。

Java中的变量名是大小写敏感的,例如num和Num是两个不同的变量。

软性规则(建议遵守):


变量名的词性推荐使用名词。

变量命名要具有描述性,能够见名知义。

当我们使用一个单词描述不清楚的时候,可以使用多个单词来命名。这时变量命名推荐小驼峰命名法,即除了第一个单词之外,后面单词的首字母都大写,如下图所示:

6268c744a0184e3794d62c353216bbd3.png


6.2 区分常量和变量

108537d2d2fe45b8a54cfafe9c230f23.png

6.3 理解类型转换

Java作为一个强类型编程语言,当不同类型之间的变量相互赋值的时候, 会进行较严格的校验,先看以下几个代码场景:


场景一:int 和 long/double 相互赋值


int a = 10;
long b = 20;
a = b; // 编译出错,提示可能会损失精度
b = a; // 编译通过
int a = 10;
double b = 1.0;
a = b; // 编译出错, 提示可能会损失精度.
b = a; // 编译通过.


分析:


long表示的范围更大,可以将int赋值给long,但是不能将long赋值给int。

double表示的范围更大,可以将int赋值给double,但是不能将double赋值给 int。

结论:不同数字类型的变量之间赋值:精度可以扩大但不能缩小,即使类型改变了也要尽可能的地保护数据安全。


场景二:int 和 boolean 相互赋值


int a = 10;
boolean b = true;
b = a; // 编译出错, 提示不兼容的类型
a = b; // 编译出错, 提示不兼容的类型

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


场景三:整型字面值常量给 byte 赋值

/ PS: 1、byte表示的数据范围是[-128, +127]
//     2、256已经超过了byte的范围, 而100还在范围之内
byte a = 100; // 编译通过
byte b = 256; // 编译报错, 提示:从int转换到byte可能会有损失

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


整数的话,会检查字面常量值是否在变量类型所能表示范围之内。

浮点数的话,会检查是否会有精度丢失,注意浮点数字面常量值类型默认是double,如果要赋值给float的话需要在数字最后加上F或f表示这个浮点数字面常量是float类型的。

创建四:使用强制类型转换


int a = 0;
double b = 10.5;
a = (int)b;// 编译通过
int a = 10;
boolean b = false;
b = (boolean)a; // 编译出错, 提示不兼容的类型


结论:


强制类型转换可能会导致精度丢失,如上面的例子中,赋值之后,10.5 就变成10了,小数点后面的部分被丢弃。

强制类型转换不是一定能成功,互不相干的类型之间就无法强转。

类型转换小结


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

不同数字类型的变量之间赋值,如果需要把范围大的类型赋值给范围小的,需要强制类型转换,但是可能会发生精度丢失。

将一个字面值常量进行赋值的时候,Java会自动针对这个数字和变量的类型所能表示的范围进行检查:

整数的话,会检查字面常量值是否在变量类型所能表示范围之内。

浮点数的话,会检查是否会有精度丢失,注意浮点数字面常量值类型默认是double,如果要赋值给float的话需要在数字最后加上F或f表示这个浮点数字面常量是float类型的。

6.4. 理解类型提升

不同数字类型的变量在运算时会发生数值提升,具体看下面两个场景:


场景一:int 和 long 混合运算


int a = 10;
long b = 20;
int c = a + b; // 编译出错,提示将long转成int会丢失精度
long d = a + b;// 编译通过

分析:


当int和long混合运算的时候,int会提升成long,得到的结果仍然是long类型,需要使用long类型的变量来接收结果。

如果非要用int来接收结果,就需要进行强制类型转换。

场景二:byte 和 byte 的运算

142a613a9d0f4fbc822f859fe9598270.png


分析:

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

byte和byte都是相同类型,但是出现编译报错,原因是:虽然a和b都是 byte,但是计算a+b时会先将a、b都提升int,再进行计算,最终得到的结果也是int,这是赋给c,就会出现上述错误。

而右边10和20都是普通的整型字面常量,最终结果30也是一个普通字面常量,所以不会报错。

类型提升小结


不同数字类型的变量混合运算,范围小的会提升成范围大的,最后得到的结果是一个类型范围最大的临时变量。

对于short、byte这种小于4个字节数字类型,会先提升成4个字节的int再做运算。

6.5 int和String之间的相互转换

int转成String:利用String包装类的valueOf()方法,即可返回一个String类型的由整数转化而来的字符串,注意 valueOf 中的O是大写的。


int num = 10;
String s = String.valueOf(num);

String转成int:利用Integer包装类的parseInt()方法,把需要转化的字符串作为参数传入即可,注意 parseInt 中的I是大写的。


String s = "10";
int num = Integer.parseInt(s);

小结:对标C++中的转换


2efe27c385404e3dab324668d08f42b4.png

二. 运算符

PS:运算符之间是有优先级的,我们不需要去记忆谁的优先级高或低,只需根据自己的逻辑加上括号即可。


1. 算术运算符

算术运算符包括如下三个大类:

279ed9c5b2a2458fa50ff8e7f3cf5127.png

注意事项:


%表示取余,不仅仅可以对int求模,也能对double来求模

d2c9af15032b4b8792467228084a021c.png


取模就是取余数,最终结果的正负号取决于余数

c40e7e27ef2040499e1896c7c683af5d.png


0不能作为除数和取模数

cbf5967e26f3466abc5f92ec95bb3a69.png


自增/自减运算符,都有各自的前置和后置形式。自增使用时注意以下两点:

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

如果取表达式的返回值,则前置自增的返回值是自增之后的值,后置自增的返回值是自增之前的值。

2. 关系运算符

关系运算符主要有六个:> < >= <= == !=,注意关系运算符的表达式返回值都是boolean类型。


int a = 10;
int b = 20;
System.out.println(a == b);// false
System.out.println(a != b);// true
System.out.println(a < b); // true
System.out.println(a > b); // false
System.out.println(a <= b);// true
System.out.println(a >= b);// false


3. 逻辑运算符

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


逻辑与 &&:全true才true,都则为false,这是个双目运算符


// 对于&&,如果左侧表达式值为false,
// 则表达式的整体的值一定是false,无需计算右侧表达式
System.out.println((10 > 20) && (10/0 == 0));// 打印 false

逻辑或 ||:全flase才false,否则为true,这是个双目运算符


// 对于||,如果左侧表达式值为true
// 则表达式的整体的值一定是true, 无需计算右侧表达式
System.out.println((10 < 20) || (10 / 0 == 0));// 打印 true


逻辑非 !:操作数为true,结果为false;操作数为false,结果为true(这是个单目运算符,只有一个操作数)


int a = 10;
int b = 20;
System.out.println(!(a < b));// fasle

4. 位运算符

位运算符主要有四个:& | ~ ^。Java中对数据操作的最小单位不是字节, 而是二进制位,而位操作表示的就是按二进制位运算。


计算机内部都是使用二进制来存储和表示数据的(即01构成的序列), 位运算就是在按照二进制位的每一位依次进行计算。


按位与 &:这是个双目运算符。两个二进制位中有0则结果为0,都是1结果才为1。

a797c1cb53a24b42b27ebb488d87d3e5.png


按位或 |:这是个双目运算符。两个二进制位中有1则为1,都是0结果才为0。


486d2b7e7e424b198a766d6330987d71.png

按位取反 ~:这是个单目运算符,运算规则如下:


如果该二进制位为0,则转为1

如果该二进制位为1,则转为0

5. 移位运算符

移位运算符有三个:<< >> >>>,它们都是按照二进制位来运算的。


左移 <<:最左侧位不要了,最右侧补0


67d2ec55ae3349388e92c7dd0604bd52.png

右移 >>:最右侧位不要了,最左侧补符号位(正数补0,负数补1)


7feeec7e0c3b4672818ca2638861813e.png

无符号右移 >>>:最右侧位不要了,最左侧不论正负数,统一都补0


移位运算符小结


左移 1 位,相当于原数字 * 2。左移 N 位,相当于原数字 * 2的N次方

右移 1 位,相当于原数字 / 2。右移 N 位,相当于原数字 / 2的N次方

在计算机中计算移位的效率高于计算乘除,当某个代码正好乘除2的N次方的时候,我们可以用移位运算代替,这样效率会高点。

移动负数位或者移位位数过大都没有意义

6. 条件运算符

条件运算符只有一个,也是Java中唯一的一个三目运算符。其格式如下:


表达式1 ? 表达式2 : 表达式3


当表达式1的值为true时,整个表达式的结果为表达式2的值(表达式3不会被执行)

当表达式1的值为false时,整个表达式的值为表达式3的值(表达式2不会被执行)

三. 注释

注释是为了让代码更容易被读懂而附加的描述信息。不参与编译运行,但是却非常重要。

时刻牢记!代码写出来是为了给人看的,更是为了给三个月后的你自己看的。

1. 基本规则

Java中的注释主要分为以下三种:


单行注释:// 注释内容(用的最多)

多行注释:/* 注释内容 */(不推荐)

文档注释: /** 文档注释 */(常见于方法和类之上描述方法和类的作用),可用来自动生成文档。

2. 注释规范

内容准确:注释内容要和代码一致、匹配,并在代码修改时及时更新

篇幅合理:注释既不应该太精简,也不应该长篇大论

使用中文:一般中国公司都要求使用中文写注释,外企另当别论

积极向上:注释中不要包含负能量(例如:领导SB等)


相关文章
|
Java 编译器
【JAVASE】数据类型与变量(三)
【JAVASE】数据类型与变量
【JAVASE】数据类型与变量(三)
|
存储 Oracle Java
【JAVASE】数据类型与变量(二)
【JAVASE】数据类型与变量
|
存储 Java 编译器
【JAVASE】数据类型与变量(一)
【JAVASE】数据类型与变量
|
存储 Java
|
7月前
|
存储 Java 编译器
JavaSE学习--数据类型和运算符
JavaSE学习--数据类型和运算符
88 0
|
存储 机器学习/深度学习 Java
【JavaSE语法】运算符
【JavaSE语法】运算符
78 0
|
存储 Java C语言
JavaSE ---01 数据类型与运算符
JavaSE ---01 数据类型与运算符
37 0
|
存储 Java 编译器
基本语法、数据类型与运算符【JavaSE】
基本语法、数据类型与运算符【JavaSE】
34 0
|
存储 Oracle Java
【javaSE】 数据类型与变量
【javaSE】 数据类型与变量