说明

这是一个完善了但又不完善的笔记,或许以后会更新

可以参考但请务必超越

源文件


Tools


Typora
PicGo

Java 数据类型与运算符

1.变量和类型

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

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

(这一块其实没什么好讲的,实在不懂百度都可以。我就写一下重点什么的。)

这里要注意一点,变量主要和内存这样的硬件设备密切相关。

冯诺依曼体系(建议直接百度)

1.1 变量命名规则

我在这里首先把命名放到了最前面。因为这他妈的真的很重要!

硬性指标:

  1. 一个变量名只能包含数字, 字母, 下划线,美元符号
  2. 数字不能开头
  3. 变量名是大小写敏感的. 即 num 和 Num 是两个不同的变量

注意: 虽然语法上也允许使用中文/美元符($)命名变量, 但是 强烈 不推荐这样做。(合法但不合理)
小驼峰 maxMax 大驼峰 MaxMax

软性指标:

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

这里可以查看阿里巴巴的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

  1. Java 中使用 单引号 + 单个字母 的形式表示字符字面值。
  2. 计算机中的字符本质上是一个整数. 在 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表达式(布尔表达式)

注意:

  1. Java 的 boolean 类型和 int 不能相互转换, 不存在 1 表示 true, 0 表示 false 这样的用法。也不能用来运算。
  2. boolean 类型有些 JVM 的实现是占 1 个字节, 有些是占 1 个比特位, 这个没有明确规定。

1.11 字符串类型变量(重点)

String 变量名 = "初始值";

单引号引起的是字符 - 'a'

那么

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

数据类型

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,再参与计算。

  1. 不同类型的数据混合运算, 范围小的会提升成范围大的。
  2. 对于 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神奇的魅力

这就是复合运算符的好处,他可以自动进行强制类型转换。

自增/自减运算符

++ --
这个也没什么好说的,注意

  1. 如果不取自增运算的表达式的返回值, 则前置自增和后置自增没有区别。
  2. 如果取表达式的返回值, 则前置自增的返回值是自增之后的值, 后置自增的返回值是自增之前的值。
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种运算符放在一起,内容不多,但很重要,尤其是逻辑运算符。我曾经在逻辑运算符和后面的位运算符吃过大亏,虽然简单但也要着重学习。

  1. 逻辑与&&:“和”,两个操作数都为true,结果为true,否则结果为false(只要有一个false,结果就是false)
  2. 逻辑或||:“或者”,两个操作数都为false,结果为false,否则结果为true(只要有一个true,结果就是true)
  3. 逻辑非!:“不、反”,这个就简单了,英语就是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. 左移 1 位, 相当于原数字 * 2。左移 N 位,相当于原数字 * 2 的N次方。
  2. 右移 1 位, 相当于原数字 / 2。右移 N 位,相当于原数字 / 2 的N次方。
  3. 由于计算机计算移位效率高于计算乘除,当某个代码正好乘除 2 的N次方的时候可以用移位运算代替。
  4. 移动负数位或者移位位数过大都没有意义。

2.5 条件运算符

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

这也是Java中唯一的一个三目运算符

表达式全部为布尔表达式

2.6 运算符的优先级

这个其实有表来说明完整的优先级

不过基本上不需要也不必须记忆,如果存在歧义的代码加括号就行。

3.注释

三种

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

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

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

注释规范

  1. 内容准确: 注释内容要和代码一致, 匹配, 并在代码修改时及时更新.
  2. 篇幅合理: 注释既不应该太精简, 也不应该长篇大论.
  3. 使用中文: 一般中国公司都要求使用中文写注释, 外企另当别论.
  4. 积极向上: 注释中不要包含负能量(例如 领导 SB 等).

自己看看什么的就算了,在工作公司中,一个代码项目肯定是所有人都看得见的。

例如游戏行业,程序猿看不下去了为玩家用户发声//SB策划我*

策划也就是产品经理一类职业,那要是看见了...

如果你写一个//领导SB

如果领导大度或者说也遇见过别的SB领导,不计较就算了。如果惹怒了领导...

4.关键字

关键字以后会慢慢都学习到,这个确实没什么必要现在啃

小头图版权:《》by ゆに* 2021年10月20日晚上11点00分 pid:93576939

广告位招租
最后修改:2021 年 10 月 24 日 11 : 07 AM
如果觉得我的文章对你有用,请喂饱我!(理直气壮)