Java 基础¶
简介¶
基本介绍¶
- Java 语言难度适中、实用性强。
- Java 是世界上最流行的编程语言。
- Java 是一门开放语言。
Hello, World¶
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello World! Go Go Go! 你好,世界!");
}
}
public class HelloWorld 类——class。HelloWorld 是类名,public class——告诉 Java 类名要与代码文件名一致。大括号内是类的内容。
public static void main(String[] args) —— main 方法的定义,告诉 Java 这事程序入口,也就是程序开始执行的地方。大括号内是方法的内容,又称方法体。main 方法最为特殊的一点是,它是 Java 程序的入口。
System.out.println 是 Java 提供的内置功能,可以将内容输出。小括号里的内容是参数。没有参数的情况下,System.out.println() 会输出一行空行。
注意:
- class 后面的名字是类名。
- 类名必须与源文件的文件名相同,文件名后缀必须是是小写的 java。
- main 方法是 Java 程序执行的入口。
数据类型¶
int¶
int 用来表示一个整数,取值范围在 -2^31 ~ 2^31-1。计算出来是 -2147483648 ~ 2147483647。
标示符¶
- 由大小写英文字符、数字和下划线组成的,区分大小写的,不以数字开头的文字。
- 可以用作 Java 中的各种东西的名字,比如类名,方法名等。
- 标示符是区分大小写的。
关键字是 Java 语法的保留字,不能用来做名字。
Java 代码三级跳——表达式、语句和代码块
- 表达式:Java 中最基本的一个运算。比如一个加法运算表达式。
- 语句:类似于平时说话时的一句话,由表达式组成,以
;结束。 - 代码块:一对大括号括起来的就是一个代码块。
Java 是区分大小写的:
- 关键字和标示符都是区分大小写的
- 类名必须与文件名一致,包括大小写要求
- 使用变量时,名字必须和声明变量时的标示符大小写一致
- 方法名也区分大小写。main 和 Main 是两个名字
- 类型也区分大小写。int 是数据类型,Int 则不是
- System.out.println 可以被 Java 认识,SYSTEM.Out.Println 就不可以
认识进制¶
十六进制:
每一位可以是 0~F 这16个值,到16进位。一百用十六进制表示就是64,十就是 A。
bit 和 byte:
- 一个二进制的位叫做一个 bit。网络带宽中的单位,都是 bit。
- 八个二进制的位,组成一个 byte。硬盘等存储的单位,都是 byte。
- byte 是计算机中基本的衡量存储的单位,计算机在对外使用时不会用 bit 作为划分存储的单位。
数字的基本类型¶
整数类型¶
- byte 占用 1 个 byte,值域是 -128~127
- short 占用 2 个byte,值域是 -32768~32767
- int 占用 4 个 byte,值域是 -2147483648 ~ 2147483647。Java 中整数缺省的是 int 类型
- long 占用 8 个 byte,值域是 -9223372036854774808~9223372036854774807
浮点(小数)类型¶
- float 占用 4 个 byte,有精度,值域复杂 ±340282346638528859811704183484516925440
- double 精度是 float 的两倍,占用 8 个 byte。Java 中浮点数缺省是 double 类型。
符号位¶
布尔和字符数据类型¶
- boolean 占用 1 个 byte,值域是 true,false。
- char 占用 2 个 byte,值域是所有字符。
引用数据类型¶
- Java 中的数据类型分为基本数据类型和引用数据类型
引用数据类型和基本数据类型¶
相同点¶
- 都可以用来创建变量,可以赋值和使用其值
- 本身都是一个地址
不同点¶
- 基本数据类型的值,就是地址对应的值。引用数据类型的值还是一个地址,需要通过“二级跳”找到实例。
- 引用数据类型是 Java 的一种内部类型,是对所有自定义类型和数组引用的统称,并非特指某种类型。
Java 有一个大大的布告板,放着所有实例¶
Merchandise m1 = new Merchandise();
- 使用 new 操作符可以创建某个类的一个实例。在 Java 程序运行的时候,所有这些创建出来的实例都被 Java 放在内存里一个叫做堆(heap)的、类似公告板的地方。
- 创建一个实例,就是根据类的定义,点出需要的“纸”,鼎铛一个本子,挂在布告板上。实例本身,可以认为是一个本子。
- 引用里存放的,相当于某个本子所在的布告板的地址。
引用的缺省值——null¶
引用也有缺省值——null:
- null 是引用类型的缺省值。
- null 代表空,不存在。可以读作空。
- 引用类型的数组创建出来,初始值都是空。
- null 也是 Java 中的关键字。
null 带来的问题:
- NullPointerException(NPE)
- 如果不确定,使用前要先判断引用是不是空
- 访问 null 的任何属性都会报错
运算符¶
- 运算符对一个或者多个值进行运算,并得出一个运算结果。
- 运算符的运算结果类型有的是固定的,有时候会根据被计算的值变化。比如两个 int 相加,结果的类型就是 int。两个 byte 相加,返回值的类型就是 int。
- 混淆点:除赋值运算外,运算符本身不会更改变量的值。
取模运算符 %¶
- 用来计算余数
- 负数也可以被取模
- 负数也可以取模
- 小数也可以取模
比较运算符¶
>>=<<=!===
布尔运算符¶
!叫做非运算符,not 运算符。&叫做且运算符,and 运算符。有一个 false 结果就是 false。&&叫做且且运算符,andand 运算符。运算结果和&一样。|叫做或运算符,or 运算符。有一个是 true 结果就是 true。||叫做或或运算符,oror 运算符。运算结果和|一样。
建议用 && 和 || ,避免报错。
运算符优先级¶
()!*,/,%+,->,>=,<,<===!=&,&&,|,||=
字面值的八进制和十六进制¶
-
以 0 开头的整数为八进制
05 就是十进制的 5
011 就是十进制的 9
-
以 0x 开头的整数的十六进制
0xF 就是十进制的 15
0x11就是十进制的 17
按位运算符¶
- 按位并(AND):
& - 按位或(OR):
| - 按位异或(XOR):
^ - 按位取反:
~
用处:掩码(MASK)
位移运算符¶
>>:符号位不动,其余位右移,符号位右边正数补0,负数补1,又称带符号右移。>>>:符号位一起右移,左边补0,又称无符号右移。<<:左移,右边补0.左移没有带符号位一说,因为符号位在最左侧。
用处:高效除以 2
注意:
-
按位运算符不会改变原本的变量的值。
-
位移运算符不会改变原本的变量的值。
计算并赋值运算符¶
作用是为了让代码更简洁。
+=-+/=*=%=&=^=|=<<=>>=>>>=
数据类型自动转换¶
自动类型转换:
- 不会出现问题的类型转换,编程语言可以做自动类型转换,比如低精度的数字向高精度的数字转换
- 自动类型转换可以发生在算术运算,也可以发生在赋值。
数值精度顺序:double > float > long > int > short > byte
char 可以转换为 int:
- char 可以转换为 int
- 虽然同样是两个 byte,但是因为 char 是无符号数,值域超出了 short 可以表示的范围,所以不可以自动转为 short。
强制数据类型转换¶
强制类型转换:
- 可能出现问题的类型转换,需要使用强制类型转换,比如高精度数值向低精度数值转换
- 强制类型转换也是操作符
- 语法是用小括号括起来的目标类型放在被转换的值前面
- 强制转换会造成数据精度丢失
数值溢出:
- 数值计算一旦溢出,结果将失去其原有意义。比如,两个正数会加出负数。
- 要对能够处理的值有大概的估计。
字符集和编码¶
字符集:
- 字符集就是字符的集合。一般会包含一种语言的字符。比如 GBK,是包含所有常用汉字的字符集。ASCII 是包含英文字符的字符集。
- 字符就是 Java 中的 char,char 是 character 的简写。
编码:
- char 代表一个字符,char 的本质也是数字。将数字映射到字符,就叫编码。
- 将一个字符集映射到数字,就是给这个字符集编码。编码是有标准的,所有的计算机系统按照同一个编码标准执行。
- 有时候编码和字符集会混用。
常用的字符集:
- ASCII 码
- Unicode 包含世界上所有常用字符,编码也有几种,包括 UTF-8,UTF-16 等。
- Unicode,GBK 等所有常用的字符集,都会兼容 ASCII。
Java 中的字符集:
- Java 中有的是 UTF-16 编码的 Unicode。
- UTF-16 用 16 个 bit,即两个 byte,这也是 char 占用两个 byte 的原因。当把 char 转成数字的时候,需要用 int。
ASCII 码和转义符¶
如何输出特殊字符:
- ASCII 码 + char,通过 ASCII 表可以找到需要的字符对应的数字。将这个数字转换为 char,然后输出这个 char。
- 转义符。转义符用来给字符赋值,也可以用作字符串里面,作为字符串中的一个字符。
转义符语法和常用的转义符:
\n:换行号\":双引号\t:制表符\uXXXX:unicode 编码 对应的字符
字符串的“加法”¶
将变量穿插在字符串中输出:
- 字符串可以和任何类型进行加法运算,则会将这个值的字符拼接到字符串上。
- 字符串也可以使用 += 操作符来拼接
- 字符串的加法运算符符合加法运算符本身的优先级
字符串不是 Java 中的基本数据类型:
- 字符串的类型的名字叫做 String
- 虽然 String 不是 Java 中的基础类型,但是也可以使用类似的语法 String stc = "abc" 来创建。开始的时候将其当成基础类型,更容易理解。
- String 不是 Java 中的保留字。
String 的加法不会改变原 String 变量的值,改变其值要用赋值语句。
自增和自减操作符¶
- 自增自减操作符是可以直接改变变量值的操作符
- 前加加和前减减
- 后加加和后减减
- 其实是一个 +1 操作和一个赋值操作的缩写
语句¶
if-else 语句¶
- if-else 语法,只有一个语句块被执行
- if 和 else 都是 Java 中的关键字
- 把 if-else 看作一个表达式,程序整体还是顺序执行的
if (boolean 值){
语句块
}else{
else 语句块
}
if-else 的嵌套¶
- if-else 就是一个语句,可以是另一个语句的一部分,也可以是 if-else 的一部分,即嵌套
if-else 的简化¶
- 如果 if 或者 else 的语句块只有一个语句,可以省略大括号
if(boolean 值)
if 语句块
else
else 语句块
if(boolean 值){
if 语句块
}else if(){
if 语句块
}else{
else 语句块
}
for 语句¶
- 让程序在满足某条件时,重复执行某个代码块。for 是 Java 中的关键字
- 初始语句在 for 循环开始前执行一次,以后不再执行;循环体条件表达式在每次循环体执行前会执行,如果为 true,则执行循环体,否则循环结束;循环体后语句会在每次循环执行后被执行。
for(初始语句;循环体条件表达式;循环体后语句) {
for 循环体
}
break 语句¶
- break 语句可以结束任何循环
- 不考虑负数的情况,使用 break 改善程序
continue 语句¶
- 跳过不符合条件的循环
- continue 语句可以结束当次循环的执行,开始下一次循环体的执行
代码块¶
- 大括号括起来的就是代码块
- 代码块也叫体,比如 for 循环体,main 方法体
- 代码块可以嵌套
变量的作用域¶
- 代码块里创建和使用变量
- 代码块里创建变量
- 不能在外层代码块里使用内层代码块的变量。是否可以使用变量,也称作变量在某个代码块的可见性。也就是说,外层代码块创建的变量对内层代码块可见。内层代码块中创建的变量对外层代码块不可见。
- 内层命名空间不可以重复定义外层代码块的变量,但是可以使用外层代码块的变量
- 代码块无论嵌套多少层,都遵循上述变量可见性
作用域和命名空间¶
- 同一个命名空间中的变量不可以重名
- 为了避免变量名冲突,所以必须有命名空间
while 语句¶
- 条件表达式的结果是一个 boolean 值,如果为 true,则执行循环体,如果为 false,则循环结束。
- while 循环体是一个代码块。所以 while 循环也是可以嵌套别的语句的,包括 while 语句,for 语句,if-else 语句等。
while(条件表达式){
while循环体
}
do-while 语句¶
- do-while 语句等循环体至少执行一次
do{
while循环体
}while(条件表达式);
死循环¶
- 无法结束的循环
- 死循环是因为没有设置好结束条件,循环的结束条件很重要,要充分考虑各种边界情况。
switch 语句¶
- 能够根据两个值相比较,进入某个代码块最适合这个情况
switch(用于比较的 int 值){
case 目标值1,对应一个 if else(xxx):
匹配后可以执行的语句
case 目标值2,不可以与别的 case 语句重复:
匹配后可以执行的语句
default(对应最后的 else,可选);
default 语句
- switch 里的 case 子句中也可以有任意合法的语句,比如 if-else,for 循环等。
- switch 里不同的 case 不能声明相同的变量。
- switch 语句中用于比较的值,必须是 int 类型。
- switch 语句适用于有固定多个目标值匹配。然后执行不同逻辑的情况
- 必须使用 break 语句显示的结束一个 case 语句,否则 switch 语句会从第一个 match 的 case 语句开始执行直到遇到 break 语句或者 switch 语句结束。
- default 子句是可选的,如果所有的 case 语句都没有匹配上,才会执行 default 中的代码。
Java 中的注释¶
单行注释¶
- 以
//为开始,到这一行结束都是注释内容 - 注释可以是任何内容
- 可以在一行的开始注释,也可以在程序内容后面添加注释
- 注释不会对程序有任何影响
多行注释¶
/* */
生成指定范围内的随机数¶
Math.random()生成随机数,随机数在 0 到 1 之间,类型是 double。
从标准输出读取字符串和整数¶
Scanner in = new Scanner(System.in)连接标准输入。in 也是变量,只是不是基本类型。in.nextLine()可以从命令行读取一行字符串in.nextInt()可以从命令行读取一个正整数- 点操作符也是 Java 中的操作符,和
System.out.println()以及Math.random()中的点是一样的操作符。是对点前面的“变量”进行点后面的“操作”。这里所谓的操作,就是指方法,也就是我们一直写的 main 方法的那个方法。这些操作都是使用一个个的方法。使用方法我们叫做调用方法(invoke a method)/方法是 Java 中的重中之重。 import java.util.Scanner;是告诉程序,Scanner 这个类型在哪里。- 创建 Scanner 类型的“变量”,它就是我们提过的工具,可以帮我们从标准收入读取数据
nextLine()和nextInt()两个方法可以从命令行读取一行字符串或者一行字符串代表的整数。
数组¶
- 数组是相同类型的变量的集合,所有元素的类型都一样
- 可以指定数组包含的元素个数,最多为 int 的最大值个
- 元素有固定的顺序
- 每个元素都有一个固定的编号, 称之为索引,从 0 开始递增,类型为 int
- 可以像操作变量一样读写数组中的任何一个元素
数组类型¶
数组是一种特殊的类:
- 数组的类名就是类型带上中括号
- 同一类型的数组,每个数组对象的大小可以不一样。也就是每个数组对象占用的内存可以不一样,这点和类的对象不同。
- 可以用引用指向类型相同大小不同的数组,因为它们属于同一种类型。
引用的数组:
- 可以把类名当成自定义类型,定义引用的数组,甚至多维数组。
创建和使用一个数组的语法¶
数组元素类型[]变量名 = new 数组元素类型[数组长度]
变量名[索引]可以使用这个变量,可以读取也可以给它赋值
数组的名与实¶
- 数组的“实”是一块地址连续的内存,就像是编号连续的一沓白纸。
- 数组的名,就是这个块连续内存的第一个内存的地址
- 受伤的变量和基本变量一样,本身是个地址。但是与基本变量不一样的是,这个地址的值,是数组的“名”,也就是数组的第一个地址。
数组=数组变量+数组的实体¶
数组变量[索引]就是在数组原有地址的基础上,加上索引,获得想要的元素- 所以索引是从 0 开始的,因为数组变量的地址就是数组第一个元素的地址
数组的长度¶
- 数组变量
.length可以获得数组的长度 - 数组创建之后,长度不可以改变
数组索引过界和初始值¶
- 访问数组过界出错的例子,数组出界的错误叫做 IndexOutOfBoundException。
- 如果没有把握数组是否会出界,可以把索引和数组长度做比较。注意索引是从 0 开始的,不是从 1 开始的。
- 数组里每个元素都有初始值,初始值和类型有关。对于数字类型,初始值是 0,对于 boolean 类型,初始值是 false。
让变量指向性的数组¶
- 数组变量可以指向新的数组实体。这时候,数组变量的值就是新的数组实体的地址了。这种数组变量的赋值操作,叫做让变量指向新的数组。
- 如果没有别的数组变量指向原来的数组实体,也就是说,如果没有数组变量“记得”原来数组的地址,原来的数组实体就再也不可访问了,也就好像“消失”了。
- 对于非基本类型的变量,计算机都要通过这种“两级跳”的方式来访问。基本类型变量,一跳就可以。
多维数组¶
创建一个二维数组,二维数组是一维数组的自然延伸
double[][] 变量名 = new double[][]
类¶
Java 是就是使用类来描述世界,用类的实例(对象)让世界运转起来。
如何创建类的实例/对象(Instance/Object)¶
- 从数据类型的角度看,类就是自己创建了一种新的数据类型。类也叫做“自定义类型”。一个 Java 程序中不允许类同名。
点操作符¶
通过点操作符操作对象的属性:
- 点操作符是用来访问/操作前面实体的属性的,类似于“的”
- merchandise.name 可以读作 merchandise 的 name
类、对象和引用的关系¶
类和对象的关系¶
- 类是对象的模板,对象是类的一个实例
- 一个 Java 程序中类名相同的类只能有一个,也就是类型不会重名
- 一个类可以有很多对象
- 一个对象只能根据一个类来创建
引用和类以及对象的关系¶
- 引用必须是、只能是一个类的引用
- 引用只能指向其所属的类型的类的对象
- 相同类型的引用之间可以赋值
- 只能通过指向一个对象的引用,来操作一个对象,比如访问某个成员变量
像自定义类型一样使用类¶
类就是一种自定义类型:
- 在类定义中可以使用类,创建类的引用
- 在类定义中,甚至可以使用类自己的类创建引用
- 引用类型的缺省值是 null。一个类定义中如果有引用,创建出来的实例,其缺省值是 null
类的管理¶
- 为了避免类在一起混乱,可以把类放在文件夹里。这时就需要使用 package 语句告诉 Java 这个类在哪个 package 里。package 语句要和源文件的目录完全对应,大小写要一致。
- package 读作包。一般来说,类都会在包里,而不会直接放在根目录
- 不同的包里可以用相同名字的类
- 一个类只能有一个 package 语句,如果有 package 语句,则必须是类的第一行有效代码
用 import 使用类¶
- 当使用另一个包里的类的时候,需要带上包名
- 每次使用都带包名很繁琐,可以在使用的类的上面使用 import 语句,一次性解决问题
- import 语句可以有多个
- 如果需要 import 一个包中的很多类,可以使用 * 通配符
属性访问修饰符:public¶
- 被 public 修饰的属性,可以被任意包中的类访问
- 没有访问修饰符的属性,称作缺省的访问修饰符,可以被本包内的其他类和自己的对象
- 访问修饰符是一种限制或者允许属性访问的修饰符
类的全限定名¶
- 包名 + 类名 = 类的全限定名。也可以简称为类的全名
- 同一个 Java 程序中全限定名不可重复
Debug¶
设置断点,debug 调试模式运行程序。
断点(breakpoint):可以让程序在调试模式停在某一行。
程序调试标准动作:
- 查看变量的值,展开实例看内部成员变量的值
- 程序继续执行之 Step Over:执行一行
- 程序继续执行之 Step Out:继续执行直到遇到下一个断点或者程序结束(执行到方法结束然后返回到调用方法的地方)
- 指向任意代码之 Evaluate Expression:在对话框输入代码,直接执行看结果值
- 条件断点:给断点设置条件,只有满足条件时,程序才会在该断点停住
- Resume Program:执行到程序结束
方法¶
方法英文名叫做 method,又称作 function。
方法的调用:
- 通过引用的点操作符,可以调用对象的方法
- 方法调用要有括号,即使没有参数
- 不能用类来调用方法
方法可以使用的数据:对象的成员变量(member variable)
方法体内部定义的变量叫做局部变量。
参数和返回值的传递¶
- 方法里使用的参数相当于一个局部变量。只是在方法调用之前,会用实参给参数的形参赋值。
- 发生在代码块里的,就让它留在代码块里。方法执行完毕,参数和方法的局部变量的数据就会被删除回收。
- 调用一个有返回值的方法时,就好像访问一个成员变量。
- 参数本身可以是一个表达式,只要表达式的值类型可以和参数类型匹配。
- 对于引用类型,参数同样是一个表达式。
- 方法里的代码不能改变实参的值。
- 给返回值赋值,并不会影响用来充当返回值的变量。
名词解释¶
- 缺省值,default 值,默认值三个词是一个意思。代表某种数值类型的默认值。
参考资料
- 课程平台:极客时间,课程链接:https://time.geekbang.org/course/intro/100027801