Java核心
1. Java程序设计概述
略
2. Java程序设计环境
编译和运行
javac hello.java
// javac程序是一个java编译器
// 编译创建的java文件,如果有错误,则会编译不通过
// 会生成class文件
java hello
// java程序用于启动java虚拟机
// 运行生成的class文件,注意此时不再需要带扩展名
当然也可以使用集成开发环境来进行编译和运行
3. Java的基本程序设计结构
程序的一般形式
public class Hello{
public static void main(String[] args){
System.out.println("Hello");
}
}
// public称为访问修饰符,控制其他程序对该代码块的访问级别
// class表示程序中的全部内容都包含在类中
// 类名以大写开始,多个单词首字母大写
// 在类的源文件中必须包含一个main方法,也可以将用户自定义的方法添加到类中,然后在main方法中调用
// 一个代码块(由{}进行标记)包含多个语句(使用;来进行标记)
// 打印时调用了System.out对象的println方法,此处点号表示调用方法
// 格式如同object.method(parameters)
注释
// 单行注释
/* 多行注释 */
/** 多行注释,可以自动生成文档 */
数据类型
- 整型,表示没有小数部分的数值,允许是负数
类型 | 存储需求 | 取值范围 | 有效位数
- | - | -
int | 4 | - 2147483648 ~ 2147483647 (20亿级) | 9 ~ 10位
short | 2 | -32768 ~ 32767 (万级) | 4 ~ 5位
long | 8 | 很大 | 18 ~ 19位
byte | 1 | -128 ~127 (百级) | 2 ~ 3位
对于int,定义4个字节为32位,就有2的32次方种选择(包括正负)
主要是两个区间 - 2147483648 ~ - 1 和 0 ~ 2147483647
0一般是包含在正数这个区间
对于short,定义2个字节为16位,就有2的16次方种选择(包括正负)
主要是两个区间 -32768 ~ -1 和 0 ~ 32767
后面的依次类推即可
long类型需要在后侧添加L符号
- 浮点类型,表示有小数部分的数值
| 类型 | 存储需求 | 取值范围 | 有效位数 |
|---|---|---|---|
| float | 4 | 6~7位 | |
| double | 8 | 15位 |
float类型有一个后缀F
if (x == Double.NaN)
// 件始终无法成立,因为所有非数值的值都认为是不相同的
if (Double.isNaN(x))
// 使用函数的形式来进行检查
- char类型,需要使用单引号括起来
可以表示一些字母以及特殊符号
其同样可以表示为16进制的值,范围从\u0000到\Uffff,也就是常说的unicode值
| 转义序列 | 名称 | Unicode值 |
|---|---|---|
| \b | 退格 | \u0008 |
| \t | 制表 | \u0009 |
| \n | 换行 | \u000a |
| \r | 回车 | \u000d |
| " | 双引号 | \u0022 |
| \' | 单引号 | \u0027 |
| \ | 反斜杠 | \u005c\' |
\'A\'是一个编码值为65所对应的字符常量
“A”是包含一个字符A的字符串
尽量不要使用char类型,而是使用字符串来进行代替
- boolean类型有两个值,false和true,用来判定逻辑条件
需要注意到,整型值和布尔值之间不能互换
变量
每个变量都具有一个type,并且需要进行显式初始化
double selectedItem; // 变量声明
selectedItem = 100; // 变量初始化
常量
即不可更改的量
使用final关键字来指示常量
final double SelectedItem = 100;
// 表示此变量赋值为100且不可更改,即为常量
// 常量名一般全部为大写
类常量
此常量可以在一个类的多个方法中使用
public class Constants{
public static final double SelectedItem1 = 100:
// 可以在多个类中使用,因为其被声明为public
public static void main(String[] args){
final double SelectedItem2 = 100:
// 只能在main这个类中使用
}
}
运算符
对于除法/,参与的两个都是整数,则为整数除法,否则就是小数除法
整数除以0将产生异常,浮点数除以0将会得到无穷大或者NaN
数学函数
double x = 4
double y = Math.sqrt(x) // 进行求平方根的运算
double z = Math.pow(x,3) // 求三次方
其他的数学函数及常量
Math.sin
Math.cos
Math.tan
Math.atan
Math.exp
Math.log
Math.log10
Math.PI
Math.E
数值转换
可能导致精度损失的转换(注意是可能,与数值本身大小有关)
int(4字节) --> float(4字节)
// 字节相同,但是编码方式不同,所以有效位数不同
// 因为int为9到10位,而float为6~7位,所以int在达到8位时,在转换为float时即会发生精度损失
long(8字节) --> float(4字节)
// 因为long可以达到19为,而float为6~7位,所以转换时极有可能出现精度损失
long(8字节) --> double(8字节)
// 同理,double最高只能到15位,所以转换时也可能出现精度损失
其他类型的高字节向低字节的转换都有可能出现精度损失
二元计算中的自动类型提升(转换为同一类型再进行计算)
- 如果,有一个为double,另一个也会变为double再进行计算
- 否则,有一个为float,另一个转换为float再进行计算
- 否则,有一个为long,另一个转换为long再进行计算
- 如果以上都不是,两个都转换为int进行计算
强制类型转换
double x = 9.997;
int nx = (int) x; // 值为9,其为直接进行截断
int nx = (int) Math.round(x); // 值为10,使用了四舍五入
如果试图将一个数值从一个类型转换为另一种类型,而又超出了目标类型的表示范围,结果会截断成一个完全不同的值
结合赋值
x += 4; // 结合赋值
int x = 5;
x += 3.5;
// 与(int)(x+3.5)相同,x先被转换为float进行计算,然后再使用int进行转换
// 可以看出,结合运算符并不允许原类型被改变
自增和自减
int a = 2 * ++m // 运算之前即自增
int b = 2 * n++ // 运算之后即自增
布尔运算
3 == 7;
3 !- 7;
3 < 7;
3 > 7;
(3 < 7) && (3 > 7);
(3 < 7) || (3 > 7);
// 交并计算中,最好对条件加上括号同时注意可能发生的短路
位运算符
- & 位与:意味着0会将原值替换为0(替换特定位为0),1会直接取原值(取特定位)
3&5
// 0000 0011 & 0000 0101 = 0000 0001,因此 3&5 的值得1
0000 0011 & 0000 0000
// 0000 0000
// 对0000 0011进行清零
0000 0011 & 0000 1111
// 0000 0011
// 取0000 0011的低四位
if ((a & 1) == 0)
// 此处的a为二进制数,直接判断其最后一位即可判断奇偶
- | 位或:意味着0直接取原值(取特定位),1会将原值替换为1(替换特定位为1)
1010 1110 | 0000 1111
// 1010 1111
// 因为0在或运算中不改变原值,使用1可以将某些位直接替换为1
// 常用来对一个数据的某些位设置为1
- ^ 异或:相同为0,相异为1,意味着0直接取原值(取特定位),1会将原值进行反转(替换特定位为反值)
1010 1110 ^ 0000 1111
// 1010 0001
// 反转特定位
a ^= b;
b ^= a;
a ^= b;
// ?????
- ~取反
a & ~1
// ~1的值为 1111 1111 1111 1110
// 使最低为为0
- << 左移运算符:将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)
若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2
a=1010 1110
a = a << 2
// a=1011 1000
- >> 右移运算符:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃
操作数每右移一位,相当于该数除以2
a= a >> 2
运算优先级
| 运算符 | 结合性 |
|---|---|
| [] . ()(方法调用) | 从左向右 |
| ! ~ ++ -- + (一元运算) - (一元运算) () (强制类型转换)new | 从右到左 |
- / % | 从左到右
-
- | 从左到右
<< >> >>> | 从左向右
< <= > >= | 从左向右
== != | 从左向右
& | 从左向右
^ | 从左向右
| | 从左向右
&& | 从左向右
|| | 从左向右
?: | 从右向左
= += -= *= /= %= &= |= ^= <<= >>= >>>= | 从右向左
- | 从左到右
字符串
Java中没有内置的字符串类型,而是直接提供了一个标准类,称之为String
String e = "";
String greeting = "Hello" \\ 产生了一个字符串对象
String s = greeting.substring(0,3); \\ 此时接收的结果就是Hel,类似于切片的形式
String a = "aa";
String b = "bb";
String ab = a + b;
// 此时字符串之间完成拼接就构成了字符串
// 当将一个字符串与另一个字符串的值进行拼接时,后者会被转化为字符串
// 一般来说,任何一个java对象都可以转换为字符串
int answer = 13;
System.out.println("the answer is" + answer);
// 可以利用这个特点直接进行输出
String all = String.join("\","1","2");
// 输出1\2
// 注意此时使用的是String类的静态join方法
字符串的修改
在java中,String类对象称为不可变字符串
String greeting = "Hello";
greeting = greeting.substring(0,3) + "p";
// Help
// 字符串为不可变对象,表示greeting这个字符串变量引用的字符串是不可更改的
// 如果想要更改,可以更换字符串变量greeting引用的字符串
// 但是要注意,此时存储池中就有两个字符串,分别是Hello和Help
s.equals(t)
// 表达式,返回布尔值,用于验证是否相等
s == t
// 这种方式比对的字符串的存储位置是否一致,但是可能存在内容一样,但位置不同的字符串
""为一个长度为0的字符串,其串长度为(0),内容(空)
str.length() == 0;
str.equals("");
// 返回布尔值
字符串的内容也可以为null,表示没有任何对象与该变量相关联
str == null;
// 返回布尔值
if (str != null && str.length() != 0)
// 应该首先检查null,因为null调用方法会进行报错
编码(补充)
0×20以下的字节状态称为”控制码”,不打印内容,而是控制状态或者格式
把所有的空格、标点符号、数字、大小写字母分别用连续的字节状态表示,一直编到了第127号此为,ANSI 的ASCII编码
GB2312 是对 ASCII 的中文扩展,用于简体汉字的扩充
后面GB2312扩展成了GBK,包含了更多的繁体字
增加了少数民族的语言,GBK又扩展成为GB18030
出于各国的交流之需,万国码UNICODE被发明
UNICODE直接规定必须用两个字节,也就是16位来统一表示所有的字符,对于 ascii 里的那些”半角”字符,UNICODE 保持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。由于”半角”英文符号只需要用到低8位,所以其高 8位永远是0,因此这种大气的方案在保存英文文本时会多浪费一倍的空间
UTF(UCS Transfer Format)标准也是一种编码格式,顾名思义,UTF8 就是每次8个位传输数据,而 UTF16 就是每次16个位
0000 – 007F // unicode
0xxxxxxx // utf-8单字节模板
0080 – 07FF
110xxxxx 10xxxxxx // utf-8双字节模板
0800 – FFFF
1110xxxx 10xxxxxx 10xxxxxx // utf-8三字节模板
// 不同的Unicode码对应的不同的utf-8字节模板
// 由于Unicode只能填充2字节,也就是16位,将其转换为2进制填充到x内即可
举例如下:
新建汉字"联通"
汉字 --> GBK16进制(2字节) --> 二进制(2字节)
联 --> C1 AA --> 1100 0001 1010 1010
通 --> CD A8 --> 1100 1101 1010 1000
// 发现联字与utf-8的双字节模板保持一致,可能会被系统误认为是utf-8(本身是GBK)从而乱码
需要注意的是,二进制编码是所有字符的底层基础,也是转换的枢纽,也是各种系统自动识别的基础
码点和代码单元
码点是指一个编码表中的某个字符(char)对应的代码值
Unicode的码点分为17个代码级别
第一个级别是基本的多语言级别,码点从U+0000——U+FFFF,每个字符用16位表示代码单元
其余的16个级别从U+10000——U+10FFFF,其中包括一些辅助字符(使用连续的代码单元进行表示,也就是一个码点可能对应多个代码单元)(辅助字符一般包含了两个代码单元)
char数据类型其实就是一个采用utf-16编码表示的unicode码点的代码单元
代码单元理解为实际存储的数据量,码点理解为实际包含的有效内容量
举例如下:
String hello = "hi