零基础搞定JavaSE语法(1)-----数据类型和运算符
变量和类型
先让我们区分一下变量和类型的概念:
变量指的是程序运行时可变的量,相当于开辟一块内存空间来保存一些数据,类型则是对变量的种类进行了划分
我们所讨论的变量主要和我们的内存这样的硬件设备密切相关,上图
先来对Java中的变量及其类型做一个整体的了解吧!
在Java中数据类型基本分为两类:(1)基本/内置类型 (2)引用类型
我们今天重点了解基本类型,引用类型后面会讲到,还望大家持续关注哦
这就是Java中所用的基本类型一个概述,下面我们细细道来,详解每一个类型
整型变量
基本语法格式
int a = 99;
基本上和C语言差不多,但在Java 中, 一个 int 变量占 4 个字节. 和操作系统没有直接关系。标识符可以是字母、数字、下划线以及组成(与C不同的可以由$组成)
使用以下代码查看 Java 中的整型数据范围:
System.out.println(Integer.MAX_VALUE); //int的最大值
System.out.println(Integer.MIN_VALUE); //int的最小值
长整型变量
基本语法格式
long a = 10L;
初始化设定的值为10L,(大小写都可以),但建议加上L,只写10的话,表示的是整型
这个数据范围远超过 int 的表示范围. 足够绝大部分的工程场景使用.
双精度浮点型变量(小数默认类型)
基本语法格式
double num = 1.0;
神奇的代码1:
int a = 1;
int b = 2;
System.out.println(a / b);
//执行结果 0
在Java中int的值除以int的值任然是int(会直接舍弃小数部分),如果想得到0.5,需要用double类型来计算
double a = 1.0;
double b = 2.0;
System.out.println(a / b);
//执行结果 0.5
神奇的代码2:
double num = 1.1;
System.out.println(num * num);
//执行结果 1.2100000000000002
Java中的double虽然也是8个字节,但是浮点数的内存布局和正数差别很大,不能单纯地用2^n的形式表示数据范围
Java 的 double 类型的内存布局遵守IEEE754标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势必会存在一定的精度误差
单精度浮点类型变量
基本语法格式:
float f = 12.5f; //编译能通过
float f = 12.5;//编译不能通过
Java是强类型语言,等号左右类型不匹配就会出错
float在Java中占四个字节,同样遵守IEEE754标准,由于表示的数据精度范围比较小,一般在工程上用到浮点数都优先考虑double,不太推荐使用float
字符类型变量
基本语法格式
char a = '姚';
char a = 'Z';
Java中使用Unicode表示字符,因此一个字符占2个字节,可以用来表示中文(C语言不可以)
字节类型变量
基本语法格式
byte value = 0;
字节类型表示的也是一个整数,但是只占一个字节,表示范围比较小
字节类型和字符类型互不相干
短整型变量
基本语法格式
short value = 0;
这个表示范围比较小,一般不推荐使用
布尔类型变量
基本语法格式
boolean value = true;
注意事项:
1.布尔类型的变量只有两种取值,true表示真,false表示假
2.Java中不存在0表示真,非0表示假的这种说法
3.JVM标准并没有明确规定boolean类型占几个节点
字符串类型变量
基本语法格式
String name = "TianYing";
//name是引用变量,里面存放的是地址
字符串的+操作,表示字符串的拼接
代码示例1:
int a = 10;
Syatem.out.println("a = " + a); //a = 10
int b = 20;
System.out.println(a + b + "haha"); //30haha
System.out.println("haha" + a + b); //haha1020
System.out.println("a = " + a + ",b = " +20); //a = 10,b = 20
当一个+表达式中存在字符串的时候,都是执行字符串的拼接行为
常量
常量指的是运行时类型不能发生改变,不能在运行时发生修改
常量主要有一下两种体现形式:
<1>字面值常量
<2>final关键字修饰的常量
final a = 99;
a = 10; //编译出错
变量的作用域
变量的作用域即该变量能生效的范围,一般是变量定义所在的代码块
代码示例:
class Test {
public static void main(String[] args) {
{
int x = 10;
System.out.println(x); // 编译通过;
}
System.out.println(x); // 编译失败, 找不到变量 x.
}
}
注意:
1.局部变量在使用的时候,一定要先初始化,否则编译不能通过
2.给任何数据类型赋值时 字面值 一定不能超过这种类型的取值范围
int i = 2147483647 + 1 ; //编译通过
int i = 2147283648 ; // 报错
变量的命名规则
硬性指标:
1.一个变量名只能包含数字、字母、下划线、$
注意: 虽然语法上也允许使用中文/美元符($)命名变量, 但是 强烈 不推荐这样做
2.数字不能开头
3.变量名是大小写敏感的,即num和Num是不一样的
软性指标:
1.变量名要具有描述性,见名知意
2.变量名不宜使用拼音,但是也不绝对
3.变量命名推荐 小驼峰命名法 ,即当一个变量名由多个单词构成的时候,除了第一个单词之外,其他单词首字母都大写
int minValue = 999999;
int studentNum = "小莹";
运算符
算术运算符
1.基本四则运算符 :+ ,- ,* ,/ , %
规则比较简单,但值得注意的是:
a. /
int / int 结果还是 int
0不能作为除数
b.%
不仅可以对 int 来取模,也可以对 double 来取模
2.增量赋值运算符 :+= ,-= ,/= , *= ,%=
注意:复合运算符可以自动进行类型的转换
short sh = 19 ;
sh = sh + 19 ; // 报错
sh += 19 ; // 通过
3.自增/自减运算符 :++ , –
a.如果不取自增/自减运算的表达式的返回值, 则前置自增/自减和后置自增/自减没有区别.
b.如果取表达式的返回值, 则前置自增/自减的返回值是自增/自减之后的值, 后置自增/自减的返回值是自增/自减之前的值
关系运算符
关系运算符主要有六个:==, !=, < ,>, <= ,>=
关系运算符的表达式返回值都是boolean类型的
逻辑运算符
逻辑运算符主要有3个:&& , ||,!
逻辑运算符的操作数(操作数往往是关系运算符的结果)和返回值都是 boolean
a. 逻辑与&&
规则: 两个操作数都为 true, 结果为 true, 否则结果为 false.
表达式1 && 表达式2
<1>这两个表达式一定只能是布尔表达式
<2>短路求值,即如果表达式1为假,则就不执行表达式2
int a = 10 ;
int b = 20 ;
int c = 30 ;
System.out.println(a < b && b < c); //true
b.逻辑或||
规则: 两个操作数都为 false, 结果为 false, 否则结果为 true
表达式1 || 表达式2
<1>同样,这两个表达式一定只能是布尔表达式
<2>短路求值,即如果表达式1为真,则就不执行表达式2
int a = 10;
int b = 20;
int c = 30;
System.out.println(a > b || b > c); //false
c.逻辑非!
规则: 操作数为 true, 结果为 false; 操作数为 false, 结果为 true(这是个单目运算符, 只有一个操作数).
d.& 和 | (不推荐使用)
& 和 | 如果操作数为 boolean 的时候, 也表示逻辑运算. 但是和 && 以及 || 相比, 它们不支持短路求值.
位运算符
位运算符主要有四个:& ,| , ~, ^
Java 中对数据操作的最小单位不是字节, 而是二进制位.
位操作表示 按二进制位运算. 计算机中都是使用二进制来表示数据的(01构成的序列), 按位运算就是在按照二进制位的每一位依次进行计算.
a.按位与&
规则: 如果两个二进制位都是 1, 则结果为 1, 否则结果为 0.
int a = 10;
int b = 20;
System.out.println(a & b); //
首先要把10 和 20转换为二进制,分别为1010 和 10100,再进行按位运算
b.按位或|
规则: 如果两个二进制位都是 0, 则结果为 0, 否则结果为 1
运算方式和按位于类似
c.按位异或^
规则: 如果两个数字的二进制位相同, 则结果为 0, 相异则结果为 1.
d.按位取反~
规则:如果该位为 0 则转为 1, 如果该位为 1 则转为 0
移位运算
移位运算符有三个: << ,>>, >>> 都是按照二进制位来运算.
a.左移 <<
规则:最左侧位不要了, 最右侧补 0.
int a = 0x10; //以0x为前缀的数字为十六进制数字.十六进制可以看成是二进制的简化表示方式. 一个十六进制数字对应 4 个二进制位
System.out.printf("%x\n", a << 1);
// 运行结果(注意, 是按十六进制打印的) 20
b.右移 >>
规则: 最右侧位不要了, 最左侧补符号位(正数补0,负数补1)
c.无符号右移 >>>
规则: 最右侧位不要了, 最左侧补 0
注意:
- 左移 1 位, 相当于原数字 * 2. 左移 N 位, 相当于原数字 * 2 的N次方.
- 右移 1 位, 相当于原数字 / 2. 右移 N 位, 相当于原数字 / 2 的N次方.
- 由于计算机计算移位效率高于计算乘除, 当某个代码正好乘除 2 的N次方的时候可以用移位运算代替.
- 移动负数位或者移位位数过大都没有意义.
条件运算符
条件运算符只有一个 : 表达式1 ? 表达式2 : 表达式3
规则: 当 表达式1 的值为 true 时, 整个表达式的值为 表达式2 的值; 当 表达式1 的值为 false 时, 整个表达式的值为 表达式3 的值
Java 中唯一的一个 三目运算符, 是条件判断语句的简化写法
运算符之间是有优先级的. 具体的规则我们不必记忆. 在可能存在歧义的代码中加上括号即可
最后加个餐,再来介绍一下数值提升,这个还是很重要的
理解类型转换
Java 作为一个强类型编程语言, 当不同类型之间的变量相互赋值的时候, 会有教严格的校验.
为了方便大家直观理解,直接看代码示例吧,并从中总结规律
(1)
int a = 10 ;
long b = 20 ;
double c = 1.0;
b = a; //编译通过
a = b; //编译出错
c = a ; //编译通过
a = c ; //编译出错
//long 表示的范围更大, 可以将 int 赋值给 long, 但是不能将 long 赋值给 int.
double 表示的范围更大, 可以将 int 赋值给 double, 但是不能将 double 赋值给int
结论: 不同数据类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型, 反之则不行
(2)
int a = 10;
boolean b = true;
b = a; // 编译出错, 提示不兼容的类型
a = b; // 编译出错, 提示不兼容的类型
结论: int 和 boolean 是毫不相干的两种类型, 不能相互赋值.
(3)
byte a = 100; // 编译通过
byte b = 256; // 编译报错, 提示 从int转换到byte可能会有损失
//byte表示的数据范围是 -128 -> +127,256已经超过范围,而 100 还在范围之内
结论: 使用字面值常量赋值的时候, Java 会自动进行一些检查校验, 判定赋值是否合理
(4)
int a = 0;
double b = 10.5;
a = (int)b;
int a = 10;
boolean b = false;
b = (boolean)a; // 编译出错, 提示不兼容的类型.
结论:
1.使用 (类型) 的方式可以将 double 类型强制转成 int. 但是强制类型转换可能会导致精度丢失. 如刚才的例子中, 赋值之后, 10.5 就变成 10 了, 小数点后面的部分被忽略.
2. 强制类型转换不是一定能成功, 互不相干的类型之间无法强转
类型转换小结:
3. 不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型.
4. 如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失.
5. 将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查
理解数值提升
(1)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 来接收结果, 就需要使用强制类型转换.
(2)byte 和 byte 的运算
byte a = 10;
byte b = 20;
byte c = a + b;
System.out.println(c);
// 编译报错
Test.java:5: 错误: 不兼容的类型: 从int转换到byte可能会有损失
byte 和 byte 都是相同类型, 但是出现编译报错. 原因是, 虽然 a 和 b 都是 byte, 但是计算 a + b 会先将 a 和 b 都提升成 int, 再进行计算, 得到的结果也是 int, 这时赋给 c, 就会出现上述错误
结论:由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据. 为了硬件上实现方便, 诸如 byte 和 short 这种低于4 个字节的类型, 会先提升成 int, 再参与计算.
正确的写法:
byte a = 10;
byte b = 20;
byte c = (byte)(a + b);
System.out.println(c);
类型提升小结:
1.不同类型的数据混合运算, 范围小的会提升成范围大的.
2. 对于 short, byte 这种比 4 个字节小的类型, 会先提升成 4 个字节的 int , 再运算.
int 和 String 之间的相互转换
(1)int 转成 String
int num = 10;
// 方法1
String str1 = num + "";
// 方法2
String str2 = String.valueOf(num);
(2)String 转成 int
String str = "100";
// 方法1
int num = Integer.parseInt(str);
// 方法2
int num = Integer.valueOf(str);
这期内容就介绍到这里啦,希望能对大家有所帮助,还望多多支持,下期更精彩