Java语法基础
1 Java简介
1.1 编程简介
编程是通过操作计算机来实现需求。
1.2 Java简介
诞生于1995年5月23日,Sun公司在Sun World会议上正式发布
Java可分为4个平台:
-
Java Card:支持一些Java小程序(Applets)运行在一些小的内存设备上。
-
Java ME:支持Java运行在移动端平台,对Java API有一些精简,并添加了对移动端的支持。
-
Java SE:支持面向桌面版的平台,提供了完整的Java核心API。
-
Java EE:支持多层架构的企业级应用平台,除了提供Java SE的API之外,还对其进行了大量的扩展,并提供了相关的部署支持。
1.3 开发环境
- JDK:Java Development Kit
- Java开发环境
- 是Java开发的核心,包含JRE、Java工具和Java基础类库
- JRE:Java Runtime Environment
- Java运行环境
- 提供Java程序运行必备的环境,包含了JVM
- JVM:Java Virtual Machine
- Java虚拟机,是实现跨平台的重要部分
- .Java文件编译后生成.class(字节码)文件,再加载到虚拟机中运行
2 进制
2.1 什么是进制
进制就是进位的制度。
2.2 进制的表示形式
- 二进制:以
0b
开头 - 八进制:以
0
开头 - 十六进制:以
0x
开头
2.3 进制转换
-
十进制与其他进制之间的相互转换
-
十进制转其他进制
辗转相除法:用这个数字除进制,再用商除进制,一直到商为0结束。将每一步得到的余数倒着连接起来,最后得到的结果,就是转换成指定进制后的结果。
-
其他进制转十进制
用每一位的数字,乘进制的位数-1次方,最后将每一个结果相加,就是转换成的十进制的表示形式。
-
-
二进制、八进制、十六进制之间的相互转换
-
一个八进制位可以等价替换成三个二进制位
从后往前三位一取
-
一个十六进制位可以等价替换成四个二进制位
从后往前四位一取
-
0123 => 0b 001 010 011
0b 010 100 100 011 111 001 => 0244371
0b 0001 0100 1000 1111 1001 => 0x148F9
-
数据单位转换
bit(位) -> Byte -> KB -> MB -> GB -> TB -> PB -> EB -> ZB -> YB -> BB -> NB -> DB -> CB -> XB
2.4 原码、反码、补码
-
负数的表示
最高位为符号位;0为正,1为负
-
补码的计算
原码:二进制本身
反码:负数的反码;除符号位外,其他按位取反
补码:负数的补码就是反码+1
正数的反码、补码均和原码相同
计算机中都是补码 来进行计算、存储的
补码的存在,就是为了解决正负数字在进行存储和运算时候会出现的符号问题。
EXP: ↓
-8【原】 = 1000 1000
-8【反】 = 1111 0111
-8【补】 = 1111 1000
10 - 8 = 10 + -8
0000 1010
1111 1000
1 0000 0010 => 结果也是一个补码 => 再取补码 0000 0010 = 2
溢出1;舍去
8 - 10 = -2
8【补】 = 0000 1000
-10【原】 = 1000 1010
1111 0101 => 1111 0110
0000 1000
1111 1110
1000 0001
1000 0010 = > -2
负数转补码 前面的符号位不变,往后的取反直到最后一个1保持不变,后面也保持不变
-20 = 1001 0100 = 1110 0100
3 数据类型
在Java中,数据类型分为两种: 基本数据类型 和 引用数据类型 。
基本数据类型分为:
- 整型:就是整数类型
- 字节型:byte,占1个字节,[-27, 27-1]
- 短整型:short,占2个字节,[-215, 215-1]
- 整型:int,占4个字节,[-231, 231-1]
- 长整型:long,占8个字节,[-263, 263-1]
- 浮点型:就是小数类型
- 单精度浮点型:float,占4个字节
- 双精度浮点型:double,占8个字节
- 字符型:用来描述一个字符(字母、数字、符号、汉字…)
- char,占2个字节
- 布尔型:用来描述非真即假,非假即真的数据
- boolean,占1个字节
任何一个整数,自身数据的类型默认为int类型
如需为long类型赋值在值后面加 L
【为何加 L ?(和虚拟机相关) 程序运行过程中,瞬时空间(局部变量表 - > slot 槽)TA可以存储(一个槽最大存32位)byte、shot、int、float、char、boolean……reference 不包含double 和 long——如要存,则分配两个槽,并且是捆绑的两个槽 所以需要加 L 来告诉虚拟机】
任何一个小数,自身的数据类型默认为 double 类型;如需为float,则加F
※ 为何folat和int都是4字节,但float的取值范围更大?
-
float/double无法做精确运算;称为近似值运算——存储结构和整数不一样,
-
float ——32bit : 1bit符号位 、8bits指数位 、23bits尾数位
4 标识符
标识符是有序的字符序列,用来表示内存中的某个数据,用于区分各个数据;类似于数学中的代数。
1、只能由字母、数字、下划线和$符号组成
2、不能以数字开头
3、不能与系统关键字重名
关键字:满足以上两点要求的字符序列;但被系统所占用,被赋予特殊的含义
保留字:同满足两点要求的字符序列,同被系统占用,暂无含义,未来可能有:)
5 变量&常量
5.1 变量常量的概念
如果某一个标识符表示的数据,在程序运行的过程中是可以发生改变的,这样的数据称为变量。
如果某一个标识符表示的数据,在程序运行的过程中是不能发生改变的,这样的数据称为常量。
src 存放java源文件
bin 保存.class文件
5.2 变量常量的定义方式
变量的定义
// 语法:数据类型 标识符;
int age;
age = 10; // 将10给变量age进行赋值
age = 20; // 将20给变量age进行赋值
// 语法:数据类型 标识符 = 初始值;
int height = 172; // 在定义一个变量的同时,给他赋一个初始值
// 语法:数据类型 标识符1, 标识符2, ...;
int a, b, c, d, e; // 可以同时定义多个相同类型的变量
int x, y = 20, z; // 可以同时定义多个相同类型的变量,并且对其中的某些变量进行初始化赋值
常量的定义
// 常量,需要使用关键字 final 修饰
final int birthday = 2000; // 定义一个常量,一旦赋值完成,值不可以修改
// 常量,也可以先声明,后赋值
final int day;
day = 30;
5.3 各种数据类型的变量定义
不同数据类型的变量,在定义的时候,直接修改为指定的数据类型即可。但是有些数据类型需要特殊说明:
1、关于long型:整型字面量默认推导的类型是int,如果需要写一个long型的字面量,需要在最后添加一个l。
2、关于浮点型:浮点型字面量默认推导的类型是double,如果需要一个float型的字面量,需要在最后添加一个f,或者大写的F。其实double类型,也可以在最后添加一个d来表示。
3、关于字符型:字符型的字面量,需要使用单引号括起来,并且单引号中只能有一个字符,不允许多,也不允许少。
/*
* 每一种数据类型的变量的定义和赋值
*/
// 整型
byte a = 10;
short b = 20;
int c = 30;
long d = 40;
// 浮点型
float e = 3.14f;
double f = 3.14;
// 字符型
char g = 'a';
// 布尔型
boolean h = true;
boolean i = false;
6 注释
注释,其实就是对某一段程序的解释、备注。注释的内容是为了提示程序员的,注释部分的内容不会被编译运行。
在Java中,注释分为三种:
- 单行注释:顾名思义,就是注释一行的内容,用两个
//
来表示。 - 多行注释:注释多行的内容。以
/*
作为开头,以*/
作为结尾。 - 文档注释:常用于类、接口、方法前面。以
/**
作为开头,以*/
作为结尾。
7 数据类型转换
7.1 什么是数据类型转换
一个变量声明完成后,已经在内存上开辟好了空间,此时这个空间大小是不允许改变的。也就是说
一个变量的类型是不允许改变的。
数据类型转换,其实就是定义一个新的指定类型的变量,将原变量的值赋给这个新变量。赋值完成后,新的变量和原来的变量值基本相同,并且类型也发生了改变,因此,这个过程就被称为数据类型转换。——精度可能会有区别
在数据类型转换中,分为两种转型:自动类型转换 和 强制类型转换
7.2 自动类型转换
就是直接的赋值操作,不需要进行任何额外的操作。常见于取值范围小的数据类型转型为取值范围大的数据类型。例如:byte转型为int。
byte、short、char类型的变量,在进行计算的时候,结果会自动的转型为int类型
7.3 强制类型转换
在进行赋值的时候,需要额外的操作来辅助完成。常见于取值范围大的数据类型向取值范围小的数据类型转型。
注意事项:
强制类型转换,可能会出现值溢出的问题。
在强制类型转换的时候,非常有可能出现的情况是两个类型的字节数不一样。如果出现这样的问题,取最后的指定的字节数的数据为新的变量赋值。
//自动类型转换
byte num1 = 10;
int num2 = num1;
//这个过程中,num1给新变量num2进行赋值
System.out.println(num2);
//强制类型转换
short num3 = (short) num2;
System.out.println(num3);
//值溢出
int a = 200;
byte b = (byte) a;
System.out.println(b);
/*
* 200 = 128 + 64 +8
*
* 0000 0000 0000 0000
* 0000 0000 1100 1000
* 取后8位
* 1100 1000 这存储的是一个补码
* 1011 0111 -> 1011 1000 = -56
*
*/
自动类型转换,由于不需要任何的额外操作,因此被称为 -- 隐式转换
强制类型转换,由于需要强制转换的操作,因此被称为 -- 显式转换
8 字符类型
8.1 字符型是如何存储的?
任意的数据在计算机底层存储都是二进制数字,字符型也不例外。每一个字符在计算机底层存储的时候,都是以一个数字来存储的。
每一个字符与数字的对应关系,需要在一个类似于字典的文件中存储,这样的存储了每一个字符与数字的对应关系的文件,被称为是 – 字符集。
常见的字符集:ASCII、GB2312。
世界上每一个国家都有自己的字符集,来存储自己国家的文字。为了将每一个国家的字符集统一起来,发明了unicode字符集。
unicode被称为万国码,为了统一每一个国家的字符集,统一规定给每一个字符都分配两个字节的空间。这样会有一个问题:如果一个文本中所有的字符都可以用一个字节来表示,那么这个文本的体积翻倍了。
因此,肯·汤普森 在unicode的基础上,发明出了 utf-8 的字符集。这个字符集也叫作万国码。但是这个字符集会针对每一个字符动态的分配空间大小。
8.2 字符类型与整型的相互转换
在Java中,字符类型可以和整型直接相互转换。
int x = 'a';
System.out.println(x);
char y = 97;
System.out.println(y);
8.3 转义字符
转义字符,就是一个\
,常用于字符或者字符串中。可以将某些具有特殊含义的字符变成普通字符,不再具备特殊的含义。
反斜线是一个转义字符,只会对后面的一个字符生效,使其转义。如果在一个字符串中,有多个特殊的字符,那么,每一个特殊字符的前面都需要添加一个转义字符。
char c = '\'';
System.out.println(c); // '
转义字符还有另外一个作用:转义字符可以配合某些普通的字符使用,使其具有特殊的含义。
\t : tab
\n : 换行
\r : 回车
1.10、常用运算符
1.10.1、算术运算符
+ - * / %
以上几个运算的注意事项:
1、求模运算%:求余数, 5 % 3 = 2
2、关于/:整型与整型的计算结果,还是整型。最终除如果得到一个浮点型的结果,那么这个浮点型的数字会自动的转成整型数字,浮点型转整型,舍去小数点后面所有的内容,直接保留整数部分。
++ --
自增、自减运算符,对一个变量进行自增1、自减1。
注意事项:自增、自减运算是很多初学者很容易出错的地方。
自增、自减运算符,可以放在变量的前面,也可以放在变量的后面。
放变量前:先对这个变量进行自增、自减操作,然后再使用这个变量的值。
放变量后:先使用这个变量的值,然后再对这个变量进行自增、自减操作。
也就是说:
++a 先对a进行自增,再使用a的值
a++ 先使用a的值后,再自增
int a = 10;
System.out.println(a++); // 10, a = 11
System.out.println(--a); // 10, a = 10
System.out.println(++a); // 11, a = 11
System.out.println(a--); // 11, a = 10
System.out.println(a); // 10
// 拓展(了解):
// 在内存中进行各种计算的时候,其实是将计算的结果先存到了一个临时的空间中,然后再使用这个空间中的值给指定的变量赋值
a = a++;
System.out.println(a); // 10
1.10.2、赋值运算符
=
是一个赋值运算符,将等号右边的值给左边的变量进行赋值。
+= -= *= /= %=
将一个变量,在现有值的基础上,对一个数字进行运算
a += 3; // a = a + 3;
a -= 3; // a = a - 3;
a *= 3; // a = a * 3;
a /= 3; // a = a / 3;
a %= 3; // a = a % 3;
注意事项:
1、组合运算符,在给左侧变量进行赋值的时候,是进行了一次强制类型转换。
2、赋值运算,也有运算结果。赋值运算的结果,是赋值完成后的变量的值。
char c = 'a';
System.out.println(c += 2); // 结果是c,并不是99
byte n = 127;
n++; // n += 1 n = n + 1
System.out.println(n); // 结果是-128
int a = 10;
System.out.println(a = 100); // 结果是赋值完成后的变量值100
1.10.3、关系运算符
对两个数据进行大小比较的运算
> < >= <= == !=
关系运算的结果一定是 boolean 类型
1.10.4、逻辑运算符
对两个boolean类型的变量进行的运算
& | ! ^
&:与,两真即为真,有任意一个为假,结果就是假。
|:或,两假即为假,有任意一个为真,结果就是真。
!:非,非真即假,非假即真。
^:异或,两个相同为假,两个不同为真。
&&:短路与, ||:短路或。
短路操作:如果在进行逻辑运算的时候,前半部分的内容可以决定最终的结果,则后半部分不参与运算。
以后在使用逻辑运算的时候,如果没有特殊的需求,尽量使用短路操作。
int x = 10, y = 20;
boolean flag = x++ > --y && x-- < ++y;
System.out.println(flag); // false
System.out.println(x); // 11
System.out.println(y); // 19
1.10.5、位运算符
类似于逻辑运算,将两个整型数字的补码的每一位进行类似逻辑运算的操作。1相当于true,0相当于false。
& | ^ ~
注意事项:
~按位取反,是将一个数字的补码的每一位进行取反,包括符号位。
x = 10; // 0000 1010
y = -20; // 1110 1100
/*
* 0000 1010
* 1110 1100
* 0000 1000
*/
System.out.println(x & y); // 8
/*
* 0000 1010
* 1110 1100
* 1110 1110 => 1001 0010
*/
System.out.println(x | y); // -18
/*
* 0000 1010
* 1110 1100
* 1110 0110 => 1001 1010
*/
System.out.println(x ^ y); // -26
/*
* 0000 1010
* 1111 0101 => 1000 1011
*/
System.out.println(~x); // -11
<< >> >>>
位移运算符,也叫作移位运算符。
将一个数字的补码的每一位向左或者向右移动指定的位数。
>> : 有序号右移,左侧补符号位。
>>>: 无符号右移,左侧补0。
1、左移运算符,每向左移动一位,相当于乘一个2
正数、负数都适用 当然要防止溢出问题 :)
2、右移运算符,每向右移动一位,相当于除一个2
若是浮点型数字,最后的结果是向下取整。
1、位异或:定理:一个数字和另外一个数字异或两次,肯定得到自己。
2、面试题:如何高效率的计算 2 * 8 解: 2 << 3
1.10.6、三目运算符
语法:
boolean变量或者boolean结果的表达式 ?值1 :值2
规则:
如果问号前面的boolean是true,整体的结果是值1;
如果问号前面的boolean是false,整体的结果是值2;
int a = 10, b = 20;
/*
先判断a和b的大小关系,
如果a > b成立,取a的值给max赋值,
如果a > b不成立,取b的值给max赋值
*/
int max = a > b ? a : b;
1.10.7、运算符的优先级
1、运算符的简单分类:
运算符根据操作数的不同,可以分为:一元运算符、二元运算符、三元运算符。
一元运算符:只能操作一个操作数,++ -- ! ~ + - (此时的+和-代表的是正负)
二元运算符:只能操作两个操作数,
三元运算符:只能操作三个操作数,三目运算符。
2、运算符的优先级
1. 一元运算符 > 二元运算符 > 三元运算符
2. 算术运算:乘除模 > 加减
3. 逻辑运算:与 > 或
4. 赋值运算符的优先级是最低的
5. 小括号的优先级是最高的
自己。
2、面试题:如何高效率的计算 2 * 8 解: 2 << 3
##### 1.10.6、三目运算符
语法:
boolean变量或者boolean结果的表达式 ?值1 :值2
规则:
如果问号前面的boolean是true,整体的结果是值1;
如果问号前面的boolean是false,整体的结果是值2;
```java
int a = 10, b = 20;
/*
先判断a和b的大小关系,
如果a > b成立,取a的值给max赋值,
如果a > b不成立,取b的值给max赋值
*/
int max = a > b ? a : b;
1.10.7、运算符的优先级
1、运算符的简单分类:
运算符根据操作数的不同,可以分为:一元运算符、二元运算符、三元运算符。
一元运算符:只能操作一个操作数,++ -- ! ~ + - (此时的+和-代表的是正负)
二元运算符:只能操作两个操作数,
三元运算符:只能操作三个操作数,三目运算符。
2、运算符的优先级
1. 一元运算符 > 二元运算符 > 三元运算符
2. 算术运算:乘除模 > 加减
3. 逻辑运算:与 > 或
4. 赋值运算符的优先级是最低的
5. 小括号的优先级是最高的