前言: 阅读完本章,你将学习到Java的基本类型、变量与常量、运算符及其进阶部分。
注:关于进阶部分将会标注 " * " , 初学者可以跳过。
目录
首先,我们先来看一段简单的Java代码:
public class Demo { //Demo为类名
public static void main(String[] args) { //Java主函数,固定写法
System.out.println("Holle Java!"); //输出语句,输出结果为:Holle Java!
} //"{ }"是语句块,表示方法(或者叫函数)从"{"开始到"}"结束
} //public、static、void 皆为关键字和修饰符,初学者暂时不用理解
这个程序十分简单,但其中有几点Java语法规则:
1 ) Java区分大小写,因此上面的 "main" 不能写成 "Main",其他的关键字也将是这样
2 ) class后面紧接类名,类名首字母必须大写
3 ) 类名即为java的文件名。运行时 javac(编译器)将 .java 编译为 .class 文件,以上段代码为 例 : Demo.java 与 Demo.class
4 ) System.out.println() 相当于C语言的 printf("\n"); System.out.print() 才相当于C语言的printf()。
5 ) // 是注释,选中代码,可以使用快捷键是 Ctrl+/ 批量注销,注释作为代码的解释说明部分, 不参与编译运行。
一, 变量与常量
变量的概念: 变量指的是程序运行时可变的量. 相当于开辟一块内存空间来保存一些数据
1.1 声明变量
int 变量名 = 初始值; //int 是Java基本数据类型中的一个,后面将会介绍其他基本数据类型
int num = 10; //例如 定义一个整型变量,将数值 10 用 "=" 赋值给变量 num
System.out.println(num) ; //输出10
1.2 变量的命名规则
1. 一个变量名只能包含数字, 字母, 下划线
2. 不能以数字开头
3. 变量名是大小写敏感的. 即 num 和 Num 是两个不同的变量
4. 不能把关键字和保留字作为标识符。如: int 不能做变量名
建议变量的命名规则:
1. 变量命名要具有描述性, 见名知意.
2. 变量名不宜使用拼音(但是不绝对).
3. 变量名的词性推荐使用名词.
4. 变量命名推荐 小驼峰命名法, 当一个变量名由多个单词构成的时候, 除了第一个单词之外, 其他单词首字母都大 写. 小驼峰命名示例:
int maxValue = 100;
String studentName = "张三";
1.3 变量初始化
声明一个变量后,必须对变量进行初始化,使用未初始化的变量将会发生错误:
int a = 10;
System.out.println(a); //输出10;
int b;
System.out.println(b); //编译器将会报错
不同的数据类型,赋值将会不一样,如:
int a = 10; //只能赋值整数
double b = 1.2; //可以赋值实数
char c = '好'; //可以赋值一个中文汉字、字母、符号等
boolean c = true; //只能赋值 false 或者 true
以上规则将在下一节介绍
1.4 常量
在Java中,利用关键字final指示常量,如:
final int a = 10;
被final修饰的类型,变量初始化之后,将不能再被修改,如:
final int A = 10; // A 是常量
A = 8; //编译器将会报错
int b = 20; // b 是变量
b = 30 //可重新赋值
System.out.println(b); //输出30
常量的命名通常是大写.如:
final double PI = 3.1415926;
二, Java基本数据类型
2.1 基本数据类型(四类八种)
概念: 类型则是对变量的种类进行了划分, 不同的类型的变量具有不同的特性。
布尔型:
类型 | 默认值 | 取值范围 |
boolean(1字节) | false | true、false |
字符型
类型 | 默认值 |
char(2字节) | 空 |
浮点型:
类型 | 默认值 | 取值范围 |
float(4字节) | 0.0f | 小数点有效位数为6-7位 |
double (8字节) | 0.0d | 小数点有效位数为15位 |
整形:
类型 | 默认值 | 取值范围 |
byte(1字节) | (byte)0 | -128~127 |
short(2字节) | (short)0 | -32768~32767 |
int(4字节) | 0 | 约 ±20亿 |
long(8字节) | 0L | 数值长度约为20位 |
备注:
1 ) Java的数据类型大小是固定的,与C语言不同,没有无符号形式的int等类型。
2 ) 赋值时,需要加相应的后缀,不然可能会引起类型转化错误,如图:
注:
float 的后缀为f,
double 后缀为d,不写后缀默认为d。
long后缀为l (小写的 L)不写默认为int型。
3 ) 基本常识:
- 1 位 = 1 bit
- 1 Byte(B)= 8 bit;
- 1 Kilo Byte(KB) = 1024B;
- 1 Mega Byte(MB) = 1024 KB;
- 1 Giga Byte (GB)= 1024 MB;
- 1 Tera Byte(TB)= 1024 GB;
1、位
位是计算机存储的最小单位,简记为b,也称为比特(bit)计算机中用二进制中的0和1来表示数据,一个0或1就代表一位。位数通常指计算机中一次能处理的数据大小;
2、比特
比特(bit)是由英文BIT音译而来,比特同时也是二进制数字中的位,是信息量的度量单位,为信息量的最小单位;
3、字节
字节,英文Byte,是计算机用于计量存储容量的一种计量单位,通常情况下一字节等于八位,字节同时也在一些计算机编程语言中表示数据类型和语言字符,在现代计算机中,一个字节等于八位;
4、字
字是表示计算机自然数据单位的术语,在某个特定计算机中,字是其用来一次性处理事务的一个固定长度的位(bit)组,在现代计算机中,一个字等于两个字节。
2.2 强制类型转化
概念: 不同类型之间的转化
语法:
int a = 10;
long b = a; //相当于long b=(long)a,Long取值范围比int大,可以省略"(long)"
long c = 10;
int d = (int)c; //int取值范围比long小,因此"(int)"不能少
int e = 128;
byte f = (byte)e //"大转小"需注意变量的取值范围,超出范围将会出现意想不到的情况,此处超出byte取值范围,实际值为f=-128
int aa = 'a' //a字符的ASCII码值是97,因此aa=97
char bb = 97 //相当于char bb=(char)97 ,因此bb='a'
以上这些可以在学习中不断积累总结
附上数值类型之间的合法转化图:
2.3 char类型的特殊字符
转义序列 | |
\b | 退格 |
\t | 制表 |
\n | 换行 |
\r | 回车 |
2.4 浮点型的精度缺陷*
浮点数值不适合精确计算,例如以下代码:
System.out.print(2.0-1.1); //输出0.8999999999999999
Java 的 double 类型的内存布局遵守 IEEE 754 标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势 必会存在一定的精度误差。
算法题经验总结:我们在写算法题时,遇到除法有两种方法,一是变除法为乘法再进行值判断,二是分别对分子分母求最大公因数,而后进行约分化为最简分式。
2.5 包装类*
每一个基本数据类型都有其对应的包装类,可以理解为这些类中,存放了有关于基本数据类型的常用方法(C语言叫函数);包装类一般是基本数据类型将首字母大写,如:
long->Long double->Double
特别的,其中有两个需要特别记忆:
int->Integer char->Character
算法题中,常用包装类的方法和常量:
int a = Integer.parseInt("12345"); //"12345"为字符串类型,通过此方法将字符串转化为整形,注意字符串中不能含有非数值字符
int b = Integer.MAX_VALUE; //b=2147483647 是int所能表示的最大值
int c = Integer.MIN_VALUE; //c=-2147483648 是int所能表示的最小值
char low = Character.toLowerCase('A'); //low=a;
char upper = Character.toUpperCase('a'); //upper=A
2.6 十六进制与二进制表示*
int a = 0xa; //0x开头表示十六进制a,即十进制的10
int b = 0b11; //0b表示二进制11,即十进制的3
2.7 大数类*
当我们的需要存放的数值非常大, 或者需要非常精确的浮点数时, 我们的基本数据类型就不够用也不适用了, 这时我们就需要用到大数类,这一类是Java中十分实用的库函数
BigInteger类(可以存放50亿字符串长度的数):
No | 方法 | 类型 | 描述 |
1 | public BigInteger( String val) | 构造方法 | 将一个字符串变为BigInteger类型的数据 |
2 | public BigInteger add( BigInteger val) | 成员方法 | 加法 |
3 | public BigInteger subtract( BigInteger val) | 成员方法 | 减法 |
4 | public BigInteger multiply( BigInteger val) | 成员方法 | 乘法 |
5 | public BigInteger divide( BigInteger val) | 成员方法 | 除法 |
6 | public BigInteger max( BigInteger val) | 成员方法 | 返回两个数字中的最大值 |
7 | public BigInteger min( BigInteger val) | 成员方法 | 返回两个数字中的最小值 |
8 | BigInteger compareTo(BigInteger other) | 成员方法 | 相等返回0,这个大于other则返回正数,否则返回负数 |
9 | BigInteger mod(BigInteger other) | 成员方法 | 求模运算 |
基本常量:
A=BigInteger.ONE(1) B=BigInteger.TEN (10) C=BigInteger.ZERO
示例:
BigInteger bigint = new BigInteger("3");
BigInteger biglong = new BigInteger("6");
BigInteger ans = new BigInteger("0");
//加法
ans = bigint.add(biglong); //bigint + biglong
System.out.println(ans); //输出 9
//减法
ans = bigint.subtract(biglong); //bigint - biglong
System.out.println(ans); //输出 -3
ans = biglong.subtract(bigint); //biglong - bigint
System.out.println(ans); //输出 3
//乘法
ans = bigint.multiply(biglong); //bigint * biglong
System.out.println(ans); //输出 18
//除法
ans = biglong.divide(bigint); //biglong / bigint
System.out.println(ans); //输出 2
BigDecimal类:
No | 方法 | 类型 | 描述 |
1 | public BigDecimal( double val) | 构造方法 | 将double转化为BigDecimal |
2 | public BigDecimal( int val) | 构造方法 | 将int转化为BigDecimal |
3 | public BigDecimal( String val) | 构造方法 | 将字符串变为BigInteger类型的数据 |
4 | public BigDecimal add( BigDecimal val) | 成员方法 | 加法 |
5 | public BigDecimal subtract( BigDecimal val) | 成员方法 | 减法 |
6 | public BigDecimal multiply( BigDecimal val) | 成员方法 | 乘法 |
7 | public BigDecimal divide( BigDecimal val) | 成员方法 | 除法 |
8 | public BigDecimal max( BigDecimal val) | 成员方法 | 返回两个数字中的最大值 |
9 | public BigDecimal min( BigDecimal val) | 成员方法 | 返回两个数字中的最小值 |
10 | BigDecimal compareTo(BigDecimal other) | 成员方法 | 相等返回0,这个大于other则返回正数,否则返回负数 |
示例:
System.out.println(2.0-1.1); //不使用大数类,运算发生精度缺失,输出 0.8999999999999999
BigDecimal n1 = new BigDecimal("2.0");
BigDecimal n2 = new BigDecimal("1.1");
System.out.println(n1.subtract(n2)); //使用大数类,精确运算并输出 0.9
运行结果:
divide(BigDecimal 除数,int 精确小数位,RoundingMode舍入模式)
舍入模式:
ROUND_HALF_UP : 向“最接近的”数字舍入(四舍五入)
关于其他舍入模式,在这里不做介绍。
不带参数的divide示例:
n1 = new BigDecimal("1.0");
n2 = new BigDecimal("3.0");
System.out.println(n1.divide(n2)); //1/3 是个无限循环小数,无法精确表示,编译器将会报错,必须采用具体的精确模式
运行结果:
带参数的divide示例:
n1 = new BigDecimal("1.0");
n2 = new BigDecimal("3.0");
System.out.println(n1.divide(n2,3,BigDecimal.ROUND_HALF_UP));//四舍五入,精确到小数点后 3 位
运行结果:
三, 运算符
3.1 算术运算符
基本运算符: + - * / %
规则比较简单:
int a = 5;
int b = 3;
int c = a + b;
System.out.println(c); //5 + 3 输出结果为 8
c = a - b;
System.out.println(c); //5 - 3 输出结果为 2
c = a * b;
System.out.println(c); //5 * 3 输出结果为 15
c = a / b;
System.out.println(c); //5 / 3 向下取整,舍去余数,输出结果为 1, 除法需要注意除数不能为 0
double d= 5 / 3.0;
System.out.println(d); //5 / 3.0 输出结果为 1.6666666666666667 结果为浮点型(要求除数与被除数至少有一个是浮点数,否则运算过程也为向下取整,舍去余数)
c = a % b;
System.out.println(c); //5 % 3 输出结果为 2, %为模运算,求余数
备注:
“/”:双目是整型,则结果是取整型;其中一个为浮点型,结果为浮点型。
“%”:取余运算,要求两个操作数必须是整形
以上运算还可以有其他格式, 如:
int a = 5;
int b = 3;
a -= b; //等价于 a = a - b
System.out.println(a); //5 - 3 输出结果为 2
更进一步的写法:
int a = 5;
int b = 3;
int c = 10;
c *= a + b; //先算等式右边的 a+b, 等价与c = c * (a+b)
System.out.println(c); //输出 80
3.2 关系运算符
关系运算符: ==(全等于)、!=(不等于)、<(小于)、>(大于)、>=(大于等于)、<=(小于等于)
关系运算符的表达式返回值都是 boolean 类型, 如:
int a = 10;
int b = 20;
System.out.println(a == b); //输出 false, 因为 a 不等于 b
System.out.println(a != b); //输出 true, 因为 a 不等于 b
System.out.println(a < b); //输出 ture, 因为 a 小于 b
System.out.println(a > b); //输出 false, 因为 a 小于 b
System.out.println(a <= b); //输出 true, 因为 a 小于等于 b
System.out.println(a >= b); //输出 false, 因为 a 小于 b
3.3 逻辑运算符
逻辑运算符: && || !
1) 逻辑与 &&
规则: 两个操作数都为 true, 结果为 true, 否则结果为 false.
int a = 10;
int b = 20;
int c = 30;
System.out.println(a < b && b < c); //a < b 为true, b < c 为true, 所以输出true
2) 逻辑或 ||
规则: 两个操作数都为 false, 结果为 false, 否则结果为 true
int a = 10;
int b = 20;
int c = 30;
System.out.println(a < b || b < c ); //a < b 为true, 将不运行(重点) b < c, 直接输出true,
3) 逻辑非 !
规则: 操作数为 true, 结果为 false; 操作数为 false, 结果为 true(这是个单目运算符, 只有一个操作数)
int a = 10;
int b = 20;
System.out.println(!a < b); //a < b 为true, 加上 ! 运算, 结果为false
备注 (短路求值) :
对于 && , 如果左侧表达式值为 false, 则表达式的整体的值一定是 false, 无需计算右侧表达式。
对于 ||, 如果左侧表达式值为 true, 则表达式的整体的值一定是 true, 无需计算右侧表达式。如以上第二个例子。
3.4 自增与自减
自增自减运算符:++、--
int a = 3;
int b = 3;
a++; //++a 也可以
b--; //--b 也可以
System.out.println(a); //相当于a = a + 1, 输出4
System.out.println(b); //相当于b = b - 1,输出2
++a 与 a++ 的区别:
++a是先自增+1,后参与运算,a++是先参与运算,后自增+1
如:
int a = 3;
int b = 5;
int c = (a++) + b; //先执行c = a + b, 而后执行a = a + 1
System.out.println(c); //输出结果为 8
System.out.println(a); //输出结果为 4
c = (++b) + b; //先执行b = b + 1, 而后执行c = b + b
System.out.println(c); //输出结果为 12
System.out.println(b); //输出结果为 6
3.5 三目运算符*
三目运算符: Boolean表达式 ? true的结果值 : false结果的值
举个例子:
int a = 3;
int b = 5;
int c = a < b ? 10 : 20; //如果 a < b 为true,则给 c 赋值10, 否则赋值20
System.out.println(c); //因为a < b, 因此输出10
嵌套式三目运算符:
int a = 3;
int b = 8;
int c = 5;
int d = a < b ? b < c ? 10 : 20 : 30; //这个等价于 d = a < b ? (b < c ? 10 : 20) : 30;
System.out.println(d); //输出20
/*解释:
因为 a < b, 所以执行 ":" 的左边结果,即:(b < c ? 10 : 20)
又因为b < c 不成立,所以执行 ":" 右边的结果,即 20, 所以 d = 20
*/
3.6 运算符的优先级
优先级即先运算, 如乘除法运算优先与加减法运算, && 运算优先与 || 运算等等, 加了括号的优先级是最高的, 即最先运算,
附图:
具体的规则我们不必记忆. 在可能存在歧义的代码中加上括号即可
3.7 位运算*
位运算是偏底层原理的部分, 涉及二进制的运算原理, 因此需要对二进制有一定的了解。本节注重介绍位运算在代码中的使用以及部分算法题的应用。
1) 右移 (>>)
2) 无符号右移(>>>)
3) 左移(<<)
以上三者可以当做乘除法运算, 如:
int a = 1;
a = a << 2; //左移2位,末尾补0,相当于乘以4, 如:00001 -> 00100 (此处不严谨,不是32位举例)
System.out.println(a); //输出 4
a = 1;
a = a >> 1; //右移1位,符号位不动,最前面的非符号位补0,相当于除以2, 如:00001 -> 00000 (此处不严谨,不是32位举例)
System.out.println(a); //输出 0
a = -1;
a = a >>> 1; //无符号右移1位,即符号位也要移动,符号位前面补0
System.out.println(a); //输出 2147483647 (11111111111111111111111111111111 -> 011111111111111111111111111111111)
4) 按位与 ( & ): 二进制的每一位进行&运算
0 & 0 = 0 0 & 1 = 0 1 & 0 = 0 1 & 1 =1
即同为1时结果才为1,否则结果为0
用法一: 判断奇偶数
奇数的二进制, 末尾必定是1, 根据这个性质可以如下使用:
int a = 3;
if ((a & 1) == 1) {
System.out.println("是奇数");
} else {
System.out.println("是偶数");
}
/*解释:(此处不严谨,不是32位举例)
00011
& 00001
------------------
00001
*/
用法二: 计算一个二进制数中1的个数
看例子领悟:
int a = 11;
int ans = 0;
while (a != 0) {
ans++;
a &= a - 1;
}
System.out.println(ans); //输出 3
/*解析:(以八位二进制举例)
11 的二进制是 00001011
10 的二进制是 00001010
& 运算之后: 00001010 是 10
10 的二进制是 00001010
9 的二进制是 00001001
& 运算之后: 00001000 是 8
8 的二进制是 00001000
7 的二进制是 00000111
& 运算之后: 00000000 是 0 一共进行三次运算,所以11的二进制里有 3 个 1
*/
推荐相关LeetCode题:
位1的个数:力扣https://leetcode-cn.com/problems/number-of-1-bits/
5) 按位异或(^) :二进制的每一位进行异或
0 ^ 0 = 0 0 ^ 1 = 1 1 ^ 0 = 1 1 ^ 1 = 0
即不同为1,相同为0
异或的4条性质:
1、交换律
2、结合律 (a^ b)^ == a^ (b^c)
3、对于任何数x,都有 x^ x=0,x^0=x
4、自反性: a^ b^ b =a^0=a;
用法一: 不带中间参数的两数交换
例如:
int a = 5;
int b = 10;
a ^= b; //a = a ^ b
b ^= a; //b = a ^ b ^ b 等于 b = a
a ^= b; //a = a ^ b ^ a 等于 a = b
System.out.println(a); //输出10
System.out.println(b); //输出5
当然, 加法也可以实现类似的两数交换, 如:
int a = 5;
int b = 10;
a += b; //a = a + b
b = a - b; //b = a + b - b 即 b = a
a = a - b; //a = a + b - a 即 a = b
System.out.println(a); //输出10
System.out.println(b); //输出5
但一般来说, 位运算的速度比加减法的运算速度要快
用法二: 找重复出现的数
原理:
1 ^ 2 ^ 3 ^ 2 ^ 1
= 1 ^ 1 ^ 2 ^ 2 ^ 3
= 0 ^ 0 ^ 3
= 3
推荐相关LeetCode题:
丢失的数字: 力扣https://leetcode-cn.com/problems/missing-number/
找不同:
力扣https://leetcode-cn.com/problems/find-the-difference/
6) 取反运算符 (~)
定义:参加运算的一个数据,按二进制进行“取反”运算。
运算规则:
~1=0
~0=1
总结:对一个二进制数按位取反,即将0变1,1变0。
7) 按位或 ( | )
0 | 0 = 0 0 | 1 = 1 1 | 0 = 1 1 | 1 = 1
即只要有1出现结果就是1,否则为0
以上两者尚未更新完毕, 如果本篇文章对你有所帮助, 希望大家点个赞, 给个小小的鼓励