目录
1、什么是常量?
1.1 Java常量分类:
2、基本数据类型
2.1 类型的基本认识:
2.2 为什么会出现数据类型?
3、变量和数据类型
3.1 什么是变量?
3.2 标识符的命名规则
3.3 整型家族变量
3.4 浮点家族变量
3.5 布尔类型变量
4、类型转换
4.1 什么是类型转换?
4.2 隐式类型转换
4.3 强制类型转换
5、类型提升
5.1 int与long之间的那些事
5.2 小于四个字节的类型变量如何运算
本期我们正式开始进入 Java 的学习,在正式开始之前,我们需要简单的认识下 Java 中的常量。
Java常量的定义:在程序中永恒不变的值,同时也不能被改变的值我们称为常量。
整型常量:像我们计算机所能识别的二进制,以及我们生活中常用的十进制等等,都是整型常量,但我们要注意,我们为了区分不同的进制,八进制是以0开头,十六进制则以0x开头,当然表示十进制数不能用0开头!
浮点数常量:我们生活中用到的小数都可以算是浮点数常量,在 Java 中浮点数又为单精度浮点型和双精度浮点型,用 float 和 double 来表示,而且默认是 double,而且浮点常量还可以用指数来表示例如:4.9E-324
字符常量:在 Java 中也有字符常量,而且只用来表示单个字符,如果你看到是用一对英文单引号引起来的单个字符,那肯定就是字符常量了,但也不排除用转义序列来表示的特殊字符。
字符串常量:这个相信就很好理解了,字符串常量也就是用英文双引号引起的字符串例如:"hello world" ,同时你也可以不包括任何字符:"" 这样就为一个空字符串,也就是长度为0的字符串。
布尔常量:此常量主要就是用来区分真假的,在一个逻辑表达式中,他最终得出的结果也就是 true或者false,而且 Java 中并不存在 0 为假 非0 为真!
空常量(null):空常量主要用于表示对象的引用为空,而且他只有一个值:null
在 Java 中我们一共有两类数据类型:基本数据类型和引用数据类型,但是我们今天主要是来认识基本的数据类型:
类型 | 关键字 | 空间大小 | 取值范围 |
---|---|---|---|
字节型 | byte | 1 字节 | - 2^7 ~ 2^7-1 |
字符型 |
char | 2 字节 | 0 ~ 2^16-1 |
短整型 | short | 2 字节 | - 2^15 ~ 2^15-1 |
整型 | int | 4 字节 | - 2^31 ~ 2^31-1 |
长整型 | long | 8 字节 | - 2^63 ~ 2^63-1 |
单精度浮点型 | float | 4 字节 | - 3.4E38 ~ 3.4E+38 |
双精度浮点型 | double | 8 字节 | 一般不关注 |
布尔型 | boolean | 没有明确规定 | true 和 false |
可能有的小伙伴以前没接触过C语言,一来就开始接触 Java,估计有很多小伙伴会觉得,整那么多数据类型干嘛?又难记,我搞一个笼统的类型,就用一两个数据类型就解决了多好,还省时省力。
那么这里我们就来讨论下为什么需要那么多的数据类型?
我不知道大家伙有没有带过帽子,我记得我路过商店的时候,有许多人在买帽子,每个人呢都会拿起帽子在戴在头上看一看,试试合不合适,有的人头大买大帽子,有的人头小买小帽子,那么这里问题来了!
如果张三的头很小,他买一个大帽子,可以吗?可以!但是不好看,戴着也不舒服,还浪费了帽子的充裕的空间,说不定还挡住眼睛。
如果张三的头很大,他买一个小帽子,可以吗?不可以!因为张三根本戴不进去!那不难受死了吗?除非张三愿意舍弃他的帅气的造型去剃光头!
那我们想想,数据类型有大有小,你一个很小的值放入一个 long 类型是不是会造成空间浪费?就比如我只需要打印 99乘法表,最大才是 81,那不白白浪费了空间吗?那如果我们有一个很大的值,比如 10000,我们就想把它放入 byte 类型中,放得下吗?放不下!有的人说编译器会自动截断!这 Java 语法可比 C语言严谨,还有的人说强制类型转换,那肯定可以,那就好比你只要舍得剃光头,就能戴上那顶帽子!
总结:有了不同了类型,确定了变量的大小,系统更容易分配空间,也可以更方便程序员用不同的类型去实现不同的需求防止空间浪费
变量其实来源于数学,相信大家都听过一句话,x 自变量, 还有什么自变量越大函数值越小等,那么在计算中,变量是可以通过变量名来访问的,也就是 Java 中常说的标识符,我们定义一个变量的名字也就叫做标识符。既然是变量,那肯定是能被改变的量,但是也有例外,比如在纯函数语言Haskell 变量就有可能是不可变的,但是今天我们只讨论 Java。张三今天心情好,定义了一个字符串类型 String str = "I am happy!";突然有一天张三心情变差了,就把 str 字符串变量改成 str = "I am very unhappy!";这就是变量,你想变就能变。(字符串类型后续讲解,属于引用数据类型)
注:Java中变量要赋初值,不然编译会报错!
【硬性规则】
【建议遵守】
目前就先建议这么多,后面碰到了我们再提一嘴,一个良好的编程规范对你我都好!
这里还想强调一点, Java 中的代码风格,左括号前是不换行的,右括号如果后面有 else 也是不换行的,如果你不遵守这些软性规定,那如果我作为面试官,是会给你扣分的!遵守统一的代码风格,对团队开发你我都好!
public class TestDemo {
public static void main(String[] args) {
int a = 10;
System.out.println(Integer.MAX_VALUE); //打印 int 能存储的最大值
System.out.println(Integer.MIN_VALUE); //打印 int 能存储的最小值
short s = 20;
System.out.println(Short.MAX_VALUE); //打印 short 能存储的最大值
System.out.println(Short.MIN_VALUE); //打印 short 能存储的最小值
long l = 30L;
System.out.println(Long.MAX_VALUE); //打印 long 能存储的最大值
System.out.println(Long.MIN_VALUE); //打印 long 能存储的最小值
char c = 'w';
System.out.println(Character.MAX_VALUE); //打印 char 能存储的最大值(符号)
System.out.println(Character.MIN_VALUE); //打印 char 能存储的最小值(符号)
}
}
这里我们有几点要注意:
public class TestDemo {
public static void main(String[] args) {
float f = 10.2F;
System.out.println(Float.MAX_VALUE); //打印 float 能存储的最大值
System.out.println(Float.MIN_VALUE); //打印 float 能存储的最小值
double d = 12.5;
System.out.println(Double.MAX_VALUE); //打印 double 能存储的最大值
System.out.println(Double.MIN_VALUE); //打印 double 能存储的最小值
}
}
double 和 float 类型的内存布局遵守 IEEE 754 标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势必会存在一定的精度误差,因此浮点数是个近似值,并不是精确值。
public class TestDemo {
public static void main(String[] args) {
boolean b = false;
System.out.println(b);
}
}
这里有几点需要注意:
在我们之前学习C语言的时候,就已经接触过类型转换了,类型转换简单来说,就是把一个数据类型转换成不同的类型, Java作为一个强类型编程语言,在不同类型变量之间相互赋值的时候,会有比C语言更严格的校验。
举一个很简单的例子,在C语言中,你把一个 double 变量直接赋给一个 int 变量时编译器最多报一个 warning 但是仍然可以编译通过,而在Java中则会直接编译失败,这是我们就需要用到强制类型转换!
所谓隐式类型转换,就是我们不需要手动转换,编译器已经帮我们转换了,最显然的例子就是,当一个数据范围小的存到数据范围大的中编译器会自动帮我们完成转换:
public class TestDemo {
public static void main(String[] args) {
/**
* 隐式类型转换 -> 数据范围小的数转为数据范围大的时候!
* 注意:不相关的类型不能互相转化 例如:布尔类型和值类型
*/
int a = 10;
long l = 100;
l = a; //编译器会将 a 转换为 long,然后进行赋值
float f = 3.14F;
double d = 5.12;
d = f; //编译器会将 f 转换为 double,然后进行赋值
}
}
强制类型转换,就好比一个水壶它只能装1升水,但是你硬要装2升水,显然多的水会溢出,也就是被丢弃,在计算机中,当一个数在一个类型能表示的范围之外,那么强制类型转换显然是可能会丢失数据的!
public class TestDemo {
public static void main(String[] args) {
/**
* 显式类型转换 -> 数据范围大的数转为数据范围小的时候需要显式类型转换
* 注意:不想关的类型不能互相转化 例如:布尔类型和值类型
*/
int a = 10;
long l = 100;
a = (int)l; //long -> int 数据范围由大到小,需要强转,否则编译失败
byte = (byte)288; //288默认是int,超过了byte的存储范围,需要强转,否则编译失败
}
}
在Java中,针对类型检查是很严格的,就比如上面,如果你把一个类型大的放到类型小的就会报错,那如果我们将 int类型与long类型相加会发生什么呢?
public class TestDemo {
public static void main(String[] args) {
int a = 10;
long l = 100;
int c = a + l; //编译报错
long l2 = a + l; //编译通过
}
}
我们先来看到编译报错那条语句,为什么会编译报错?当我们在进行不同类型运算的时候,范围小的会被提升成范围大的,在这个代码中,也就是 a 被提升成 long 类型进行运算,long + long 最后的结果肯定是一个 long 类型的值,所以在赋值给一个 int 类型变量会报错,我们可以将他们最后的结果强转成 int 但是可能是会造成数据丢失。
当然,如果我们 int 类型变量与 double类型变量运算,也是会先把 int 提升到 double 的,这个下来自己可以动手去一一测试一下。
目前我们已知小于四个字节的类型有:byte,char,short 那么他们之间的变量运算又是怎么一回事呢?
这里发现报错了,int 转到 byte 显然是不行的,通过代码,我们可以看到,在不满足4个字节大小的类型变量,会先提升到 int 类型,在进行运算,那么显然他们的计算结果肯定也是 int 当一个 int 类型值放入一个 byte 类型变量中肯定是不行的,所以这里有两个解决办法:将他们的结果强制类型转换,或者拿一个整型变量来接收他们计算的结果值。
下期预告:【Java SE】运算符详解