说明
这是一个完善了但又不完善的笔记,或许以后会更新
可以参考但请务必超越
源文件
Tools
Java 数据类型与运算符
1.变量和类型
变量指的是程序运行时可变的量。相当于开辟一块空间来保存一些数据。
类型则是对变量的种类进行了划分,不同的类型的变量具有不同的特性
(这一块其实没什么好讲的,实在不懂百度都可以。我就写一下重点什么的。)
这里要注意一点,变量主要和内存这样的硬件设备密切相关。
冯诺依曼体系(建议直接百度)
1.1 变量命名规则
我在这里首先把命名放到了最前面。因为这他妈的真的很重要!
硬性指标:
- 一个变量名只能包含数字, 字母, 下划线,美元符号
- 数字不能开头
- 变量名是大小写敏感的. 即 num 和 Num 是两个不同的变量
注意: 虽然语法上也允许使用中文/美元符($)命名变量, 但是 强烈 不推荐这样做。(合法但不合理)
小驼峰 maxMax 大驼峰 MaxMax
软性指标:
- 变量命名要具有描述性, 见名知意.
- 变量名不宜使用拼音(但是不绝对).
- 变量名的词性推荐使用名词.
- 变量命名推荐 小驼峰命名法, 当一个变量名由多个单词构成的时候, 除了第一个单词之外, 其他单词首字母都大写.
这里可以查看阿里巴巴的Java开发手册,很详细的规定了许多内容。
1.2 类型大小 取值范围 初始化
字节
- 字节是计算机中表示空间大小的基本单位.
- 计算机使用二进制表示数据. 我们认为 8 个二进制位(bit) 为一个字节(Byte).
- 我们平时的计算机为 8GB 内存, 意思是 8G 个字节.
- 其中 1KB = 1024 Byte, 1MB = 1024 KB, 1GB = 1024 MB.
- 所以 8GB 相当于 80 多亿个字节.
每一个类型都有他的大小,例如int。在Java中,一个int变量占4个字节,和操作系统没有直接关系。
取值范围
首先,在Java当中没有无符号类型,统一都是有符号数。所以除去首位都会少一位。
那么占据了这样一个空间,能够取到的数值范围是多少呢?
例如int:
System.out.println(Integer.MAX_VALUE);//int 的最大值
System.out.println(Integer.MIN_VALUE);//int 的最小值
4个字节表示的数据范围就是-2^31 - 2^31-1
也就是-2,147,483,648到2,147,483,647。游戏中看到bug出现数据错误变成的21亿的数字就是这个了。
存储数据的时候,不要超过类型的表示范围。
注意,小数和整数也不一样,具体看下面
初始化
注意了,在Java中变量定义是不可以不初始化的。
Java是完善且安全的语言,相对于C/C++,Java比较安全。
如果不初始化就使用,编译器就会报错。
1.3 整型变量
int 变量名 = 初始值;
类型大小:4个字节
int i = 0;
数据范围:-2^31 - 2^31-1
21亿这样的数字对于当前的大数据时代来说,是很容易超出的。针对这种情况,我们就需要使用更大范围的数据类型来表示了。Java 中提供了 long 类型。
包装类
这里会提到int的一个plus版本
Integer;
当然还会有其他的包装类,以后会专门讲
1.4 长整型变量
long 变量名 = 初始值;
类型大小:8个字节
long l = 10L;//定义一个长整型变量,初始值写作10l也可以。
数据范围:-2^63 - 2^63-1
2^63=9,223,372,036,854,775,808
Java没有long long类型。
1.5 双精度浮点型变量
double 变量名 = 初始值;
类型大小:8个字节
double d = 1.0;
注意,在大多数编程语言中,整型除以整型还是整型,也就是说1/2等于0。
在Java中不同的类型就会报错
int a = 1.0;//err
int b = 2.0;//err
程序中的小数
小数本身在程序中是没有一个精确的数字的,他只能精确到几位。
double a = 1.1;
System.out.println(a*a);//1.2100000000000002
Java 中的 double 虽然也是 8 个字节, 但是浮点数的内存布局和整数差别很大, 不能单纯的用 2 ^ n 的形式表示数据范围.
Java 的 double 类型的内存布局遵守 IEEE 754 标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势必会存在一定的精度误差.
1.6 单精度浮点型变量
float 变量名 = 初始值;
类型大小:4个字节
float f = 1.0f;//写作1.0F也可以。
这里如果不写f的话,就会报错。
Java是强类型语言,不写f就会默认是double类型。C语言属于弱类型语言,可能就撑死报个警告。
1.7 字符类型变量
char 变量名 = 初始值;
类型大小:2个字节(C语言是1个字节)
char ch = ‘艹’
数据范围:-2^15 - 2^15-1
- Java 中使用 单引号 + 单个字母 的形式表示字符字面值。
- 计算机中的字符本质上是一个整数. 在 C 语言中使用 ASCII 表示字符, 而 Java 中使用 Unicode 表示字符. 因此一个字符占用两个字节, 表示的字符种类更多, 包括中文。
注意哦,既然是2个字节,那么ASCII码值中的97=a肯定就没用了
那么1个字节的类型又是什么呢?
1.8 字节类型变量
byte 变量名 = 初始值;
类型大小:1个字节
byte b = 0;
数据范围:-2^7 - 2^7-1
1.9 短整型变量
short 变量名 = 初始值;
类型大小:2个字节
short s = 0;
数据范围:-2^15 - 2^15-1
1.10 布尔类型变量
boolean 变量名 = 初始值;
boolean value = ture;
在C语言中真为非0假为0。
但是在Java中,只有true和false
boolean类型的变量只有两种取值,true表示真,false表示假
表示真假判断的表达式就是boolean表达式(布尔表达式)
注意:
- Java 的 boolean 类型和 int 不能相互转换, 不存在 1 表示 true, 0 表示 false 这样的用法。也不能用来运算。
- boolean 类型有些 JVM 的实现是占 1 个字节, 有些是占 1 个比特位, 这个没有明确规定。
1.11 字符串类型变量(重点)
String 变量名 = "初始值";
单引号引起的是字符 - 'a'
那么
- Java 使用 双引号 + 若干字符 的方式表示字符串字面值.
- 和上面的类型不同, String 不是基本类型, 而是引用类型(后面重点解释).
- 字符串中的一些特定的不太方便直接表示的字符需要进行转义.
数据类型
Java有两种数据类型,一是数值类型,二是引用类型。
数值类型又分为前面的整数、浮点数、字符、布尔等等基本数据类型。
引用类型就很多了,这里的String字符串类型,数组、类、接口、枚举等等。变量里存储的是地址的话,那就是引用类型了。(等到后面数组及以后,就可以理解了。)
注意问题
在写字符串的时候有几种情况
System.out.println("hello"+"world");//+代表一个拼接
System.out.println("hello"+10+20);//其他数据类型和字符串使用+拼接,结果就是一个字符串。属于字符串加+字符串
System.out.println(10+20+"hello");//30hello 计算机在运算的时候是从左向右,属于整数+字符串
System.out.println("hello"+(10+20));//括号
System.out.println(10+""+20+"hello");//中间加一个双引号
当然还有转义
String s1 = "\"bit\"";// \转义
String s2 = "\\bit\\";// \转义一个斜杠
String s3 = "\\\\bit\\\\";// \转义两个斜杠
// \n换行 \t 水平制表符-tab \' 单引号 \" 双引号 \\ 斜杠
1.12 变量的作用域
变量分为成员变量和局部变量,成员变量又分为普通成员变量和静态成员变量。这里就先讲局部变量,等到类和对象的时候再讲成员变量。
作用域 - 作用范围
public static void main(String[] args){
int a = 0;//在此花括号内起作用,这个花括号就是a变量的作用域
}
找作用域的时候去找所在花括号就可以了。
public static void main(String[] args){
int a = 0;
{
a = 10;//赋值了个寂寞
}
{
System.out.println(a);//打印了个寂寞
}
System.out.println(a);//编译通过
}
1.13 常量
上面是各种类型的变量,每种类型的变量也对应着一种相同类型的常量。
int a = 10;
变量a 赋予初始值 常量10
常量指的是运行时类型不能发生改变的量。
1.字面值常量
10 // int 字面值常量(十进制)
010 // int 字面值常量(八进制) 由数字 0 开头. 010 也就是十进制的 8
0x10 // int 字面值常量(十六进制) 由数字 0x 开头. 0x10 也就是十进制的 16
10L // long 字面值常量. 也可以写作 10l (小写的L)
1.0 // double 字面值常量. 也可以写作 1.0d 或者 1.0D
1.5e2 // double 字面值常量. 科学计数法表示. 相当于 1.5 * 10^2
1.0f // float 字面值常量, 也可以写作 1.0F
true // boolen 字面值常量, 同样的还有 false
'a' // char 字面值常量, 单引号中只能有一个字符
"abc" // String 字面值常量, 双引号中可以有多个字符
就很简单
2.final修饰的变量->常量
和C语言的count一样
final int a = 10;//此时a为常量
a = 20;//err,只能初始化一次
注意:一般只要是常量,final修饰,我们都写成大写
final int SIZE = 10;
常量不能在程序运行过程中发生修改
在程序编译的时候,就已经确定其值是什么了。而变量则是程序运行的时候才知道里面是几
1.14 理解类型转换
int a = 10;
long b = a;
System.out.println(b);
小赋大可以,大赋小不行。C语言可能行,但是Java会报错。就算是C语言,编译器例如VS2019可能也会报错
Java本身是一个强类型语言 C语言是弱类型语言。C语言的检查没这么强硬。
但是,站在巨人的肩膀上可能会越来越好,但是有一些还是不能代替巨人的。
如果非要把大的值放进小的类型里去呢?
强转
强制类型转换:是有一定风险的
int c = (int)b;//打包票,一定能放得下
注意类型的取值范围!
例如byte的取值范围为-128 ~ 127
byte b = 128;//err
还有布尔类型!
不同的类型无法转换
布尔类型肯定不行。压根就不是一种类型。
CPU整型提升
现在科技太发达了,一般桌面级电脑都性能过剩。
那么
1.CPU她在小于4字节运算的时候,会提升为int整型类型!
(CPU:啊我这么厉害,你就给我算个这?不行,我最少也得算4字节!)
byte a = 1;
byte b = 2;
byte c = a + b;//err,此时a和b被整型提升
System.out.println(c);//err
那Java又是强类型语言,a+b是int赋值给byte的c,就会报错。
解决方法也就是强转。
byte c = (byte)(a+b);
当然直接使用字面值常量是可以的
byte c = 1 + 2;//byte c = 3;
1和2因为是字面值常量,在程序编译的时候这里就已经被编译为3了。
CPU这么做其实是提升了运算效率的,因为小变大补位就可以了,大变小肯定不行会有损失。那么同样的
2.CPU在大于4字节运算的时候,会提升为最大类型!
(CPU:啊这小的加大的,位数都对不齐,算起来太麻烦了,那直接全变大的吧。)
int i1 = 10;
long l1 = 20;
int i2 = (int)(i1+l1);//一样的,i1变成了long类型,需要强转
小结:
由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据。为了硬件上实现方便, 诸如 byte 和 short 这种低于4 个字节的类型,会先提升成 int,再参与计算。
- 不同类型的数据混合运算, 范围小的会提升成范围大的。
- 对于 short,byte 这种比 4 个字节小的类型,会先提升成 4 个字节的 int,再运算
精度丢失
这里还有要注意,关于强转把范围大类型赋值给范围小类型
还存在浮点数的情况
例如
double d = 1.5;
a = (int)d;
System.out.println(a);//0.5丢失了,只打印1
double是要比int大的,所以赋值需要强转,但是int压根就没有小数,所以0.5就丢失了。这就是精度丢失。
1.15 int和String之类的相互转换
字面意思,如何把一个int变量和String字符串相互转换
int 转 String
方法一
int num = 10;
String ret = String.valueOf(num);
这里使用了一个String.valueOf的方法
我们可以使用idea先看一下String,按住ctrl选择String点击打开
可以看到,String也是一个类(class)
那么String.valueOf这个方法,其实就相当于String的一个功能
方法有很多,我们可以使用jdk1.8文档查询,有官方英文文档和汉化的文档,这里就不多说了,因为太多了。
我这里使用大佬集成翻译好的文档搜索一下
方法二
就是字符串使用+加号拼接,相当于凑巧了
String ret2 = num+"";//凑巧,虽然也行,但是不可取
System.out.println(ret2);
String 转 int
想反过来,有一个字符串怎么把它转成int呢?
String str = "123";
int ret = Integer.valueOf(str);
System.out.println(ret);
这里就体现了包装类的好处
我们ctrl点击Integer看一下
如果使用int就需要像C语言一样自己写一个代码把整型改成字符串,如果使用Integer这个包装类中的一个方法就可以直接改变
8种基本数据类型的包装类
除了int和char不一样,其他的都是首字母大写
int -> Integer
char ->Character
byte -> Byte
short -> Short
long -> Long
float -> Float
double -> Double
boolean -> Boolean
2.运算符
运算符其实都很好理解,也很常用
单目运算符双目运算符和三目运算符,也就是操作数的不同
2.1 算数运算符
基本四则运算符
+-*/%
我靠这个小学数学不难理解吧
特别需要注意的就是除法和取模
除法
int a = 10;
int b = 0;
System.out.println(a / b);//err
在Java里面除数不能是0,如果是0就会抛出异常(术语,也就是错误)。程序直接就停下来了
异常也有非常多的种类。除数为0属于算术异常
异常会最后讲,要慢慢接触,慢慢来。
取模
取余 求模 取余数 求余数
除不尽就把余数算出来
Java中比较特殊的一点是可以对double取模
System.out.println(11.5%2);//1.5
增量赋值运算符
+= -= *= /= %=
复合运算符
在Java中也没什么好说的,不过有一点
short s = 10;
s = (short)(s+9);
//注意强转
//但是
s+=9;
//哎我操,Java神奇的魅力
这就是复合运算符的好处,他可以自动进行强制类型转换。
自增/自减运算符
++ --
这个也没什么好说的,注意
- 如果不取自增运算的表达式的返回值, 则前置自增和后置自增没有区别。
- 如果取表达式的返回值, 则前置自增的返回值是自增之后的值, 后置自增的返回值是自增之前的值。
int a = 10;
int b = 10;
a++;
System.out.println(a);
++b;
System.out.println(b);
//单独出来是一样的
如果
int i1 = a++;
int i2 = ++b;
System.out.println(i1);
System.out.println(i2);
//这就有区别了
2.2 关系运算符 逻辑运算符(重点)
== != < > <= >=
&& || !
把这2种运算符放在一起,内容不多,但很重要,尤其是逻辑运算符。我曾经在逻辑运算符和后面的位运算符吃过大亏,虽然简单但也要着重学习。
- 逻辑与&&:“和”,两个操作数都为true,结果为true,否则结果为false(只要有一个false,结果就是false)
- 逻辑或||:“或者”,两个操作数都为false,结果为false,否则结果为true(只要有一个true,结果就是true)
- 逻辑非!:“不、反”,这个就简单了,英语就是NO。!=也就是不等于
在Java中这两种运算符也和布尔类型息息相关。
注意:关系运算符的表达式返回值都是boolean类型
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);
在Java中,判断语句if()里面只能是布尔类型,和C语言不一样
还有逻辑或和逻辑与以及逻辑非
if(布尔表达式){
}else if(布尔表达式){
}
[表达式1] && [表达式2]
//这两个表达式全部都是布尔表达式
//且支持短路:如果表达式1为假,就不执行表达式2了
逻辑或也一样
[表达式1 || 表达式2]
//也全部都是布尔表达式,且支持短路
//还有逻辑非!
!false = true
!true = false
//不是真就是假嘛
短路求值
&&和||遵守短路求值的规则
这里有一点,0作为除数不是会异常吗,那么如果先短路了,就不会运行到异常
System.out.println(10 > 20 && 10 / 0 == 0);
// 打印 false
System.out.println(10 < 20 || 10 / 0 == 0);
// 打印 true
&和|也是可以这样写的,但是不推荐使用。不支持短路求值,写出来也很怪
2.3 位运算符
& | ~ ^
按位与&:二进制对应位都是1 结果就是1
按位或|:二进制对应位只要有1 结果就是1
按位异或^:二进制对应位一样 结果就是0 不一样就是1
按位取反~:二进制反正只有0和1...
2.4 移位运算符
<< >> >>>
这个就简单了,不过注意移动的是二进制位
- 左移就左边不要了,右边补0。相当于乘法,十进制乘10二进制乘2嘛。
- 右移就右边不要了,左边补符号,正数补0,负数补1。正数相当于除法,十进制除以10二进制除以2嘛,但是如果是负数就不是了。如果全是1就不会变了。
在Java中,多了一个无符号右移>>>
- 无符号右移是说不管正负,右边不要了,左边都补0。这个是真的相当于除法,二进制除2。
唉?那么问题来了,为什么没有无符号左移>>>呢?
无语...
左边压根就没有符号位,还是补0,那不就是<<
注意
- 左移 1 位, 相当于原数字 * 2。左移 N 位,相当于原数字 * 2 的N次方。
- 右移 1 位, 相当于原数字 / 2。右移 N 位,相当于原数字 / 2 的N次方。
- 由于计算机计算移位效率高于计算乘除,当某个代码正好乘除 2 的N次方的时候可以用移位运算代替。
- 移动负数位或者移位位数过大都没有意义。
2.5 条件运算符
表达式1?表达式2:表达式3
这也是Java中唯一的一个三目运算符
表达式全部为布尔表达式
2.6 运算符的优先级
这个其实有表来说明完整的优先级
不过基本上不需要也不必须记忆,如果存在歧义的代码加括号就行。
3.注释
三种
单行注释://注释内容(用的最多)
多行注释:/ 注释内容 /(一般不推荐)
文档注释:/** 文档注释 */(常见于方法和类之上描述方法和类的作用),可用来自动生成文档
注释规范
- 内容准确: 注释内容要和代码一致, 匹配, 并在代码修改时及时更新.
- 篇幅合理: 注释既不应该太精简, 也不应该长篇大论.
- 使用中文: 一般中国公司都要求使用中文写注释, 外企另当别论.
- 积极向上: 注释中不要包含负能量(例如 领导 SB 等).
自己看看什么的就算了,在工作公司中,一个代码项目肯定是所有人都看得见的。
例如游戏行业,程序猿看不下去了为玩家用户发声//SB策划我*
策划也就是产品经理一类职业,那要是看见了...
如果你写一个//领导SB
如果领导大度或者说也遇见过别的SB领导,不计较就算了。如果惹怒了领导...
4.关键字
关键字以后会慢慢都学习到,这个确实没什么必要现在啃
小头图版权:《》by ゆに* 2021年10月20日晚上11点00分 pid:93576939