JAVA程序执行过程
- 编写
Hello.java
类,
1 | public class Hello { // 定义类 |
- 通过编译生成
Hello.class
文件,(字节码文件)
1 | javac Hello.java |
- 调用
JVM(java 虚拟机)
运行生成结果
1 | java Hello # 实际在运行Hello.class,但是不写后缀 |
JAVA类编写注意事项
- 一个源文件中最多只能有一个
public 类
,其他类的个数不限。 - 如果一个文件中包含
public 类
,则文件名必须和该类同名。
JAVA转义字符
- JAVA中常用的转义字符:
换行符 | 含义 |
---|---|
\n |
换行符 |
\t |
制表符,实现对齐 |
\r |
一个回车 |
JAVA注释
- 单行注释
1 | // 这是单行注释 |
- 多行注释
多行注释不允许嵌套多行注释
1 | /* |
- 文档注释
里面是java doc标签
1 | /** |
JAVA变量
变量是程序的基本组成单位,有三要素(类型 + 名称 + 值),变量表示内存中的一个存储区域。
1 | public class Variable { |
变量类型
int
整型,占4字节double
双精度浮点类型,占8字节char
字符型,占2字节String
字符串类型,
JAVA数据类型 ⭐
java 中定义数据必须指定明确的数据类型,可以看出java 是强类型语言
基本数据类型
- 数值型
- 整数类型,存放整数
byte[1], short[2], int[4], long[8]
- 浮点(小数)类型
float[4], double[8]
- 整数类型,存放整数
- 字符型
char[2]
,存放单个字符 - 布尔型
boolean[1]
整数类型
类型不同带来的是占用存储空间不同,进而带来的是数值范围不同。1个字节等于8位。
1 | public class IntDetail { |
浮点数类型
- 浮点数 = 符号位 + 指数位 + 尾数位
- 尾数部分可能丢失,造成精度损失(小数都是近似值)
陷阱:
2.7
和 8.1 / 3
不相等,8.1 / 3
是接近2.7
的小数,而不是2.7
。所以需要判断时,应该是以两个数的差值的绝对值,在某个精度范围内进行判断。
字符类型
- 必须用单引号
''
- 允许使用转义字符
\
- 允许进行运算
'a' - 'a'
- 字符型存储到计算机中,需要将对应的码值(整数)找出来进行存储。
- 字符和整数的对应关系是通过字符编码表决定的,是规定好的。
基本数据类型的转换
自动类型转换
- 精度小的类型自动转换为精度大的数据类型。
char < int < long < float < double
byte < short < int < long < float < double
注意:
- 有多种类型的数据类型进行混合运算时,系统首先将所有类型转为容量大的类型,然后再进行计算。
- 把容量大的数据类型赋值给容量小的数据类型时,会报错,反之则会进行自动类型转换。
(byte, short)
和char
之间不会自动转换。
强制类型转换
将容量大的类型转换为容量小的数据类型。使用时需要加上强制转换符()
,但可能造成精度降低或溢出。
1 | public class ForceConvert { |
基本数据类型和String类型的转换
- 基本类型转String类型:
基本类型值 + ""
- String类型转基本类型:通过基本数据类型的包装类调用
parseXXX
进行转换。
1 | public class StringToBasic { |
注意事项:
- 在将String类型转换为基本数据类型时,需要确保String类型能够转换为有效的数据。如果格式不正确,则会抛出异常,程序就会终止。
引用数据类型
- 类
class
,例如String
- 接口
interface
- 数组
[]
JAVA API文档
JDK > Packages > Interfaces + class + Exceptions > function
JAVA 算数运算符
运算符是一种特殊的符号,用于表示数据的运算,赋值和比较。
算数运算符
运算符 | 运算 |
---|---|
+ | 正号 |
- | 负号 |
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取模(取余) |
++ | 自增 |
— | 自减 |
+ | 字符串相加 |
加号
- 当左右两边都是数值类型,则做加法。
- 当左右两边有一方是字符串类型,则做拼接。
- 运算顺序,从左到右,右括号除外。
赋值运算符
基本赋值运算符:=
复合运算符:+=
,-=
,*=
,/=
,%=
。
关系运算符
关系运算符的结果都是boolean
类型
运算符 | 运算 |
---|---|
== | 相等于 |
!= | 不等于 |
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
instanceof | 检查是否是类的对象 |
逻辑运算符
用于连接多个条件(多个关系表达式),最终的结果也是一个boolean
值
a | b | a&b | a&&b | a\ | b | a\ | \ | b | !a | a^b(异或) |
---|---|---|---|---|---|---|---|---|---|---|
T | T | T | T | T | T | F | F | |||
T | F | F | F | T | T | F | T | |||
F | T | F | F | T | T | T | T | |||
F | F | F | F | F | F | T | F |
&&和&的区别
&&
当第一个条件为false
时,不再判断第二个条件。效率高。&
当第一个条件为false
时,仍需判断第二个条件。效率低。- 同理
||
和|
的区别也是如此
位运算符
运算符 | 运算 | |
---|---|---|
& | 按位与 | |
\ | 按位或 | |
~ | 按位取反 | |
^ | 按位异或 | |
>> | 算数右移,地位溢出,符号位不变,并用符号位补溢出的高位 | |
<< | 算数左移,符号位不变,低位补 | |
>>> | 逻辑右移 |
三元运算符
基本语法:条件表达式 ? 表达式1 : 表达式2
- 如果条件表达式结果为
true
,运算后的结果是表达式1; - 如果条件表达式结果为
false
,运算后的结果是表达式2;
标识符
命名规则:(必须遵守)
- 由26个英文字母大小写,0-9,_或$组成
- 数字不可以开头,
- 不可以使用关键字或保留字,但能包含关键字或保留字
- 严格区分大小写,长度无限制。
- 不能含有空格。
命名规范
- 包名:多个单词组成时所有字母都是小写。
- 类名、接口名:多单词组成时,所有单词的首字母大写。
- 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始后的所有单词首字母大写。
- 常量名:所有字母都大写。多单词时,每个单词用下划线连接。
键盘输入语句
导入java.util.Scanner
包,创建Scanner
对象,调用方法进行输入。
1 | import java.util.Scanner; |
进制
- 二进制:以
0b
或0B
开头 - 十进制:
- 八进制:以数字
0
开头 - 十六进制:以
0x
或0X
开头表示。
进制的转换
其他进制转十进制
- 二进制转十进制
从最低位(右边)开始,将每个位上的数提取出来,乘以2的(位数-1)次方,然后求和。
- 八进制转十进制
从最低位(右边)开始,将每个位上的数提取出来,乘以8的(位数-1)次方,然后求和。
- 十六进制转十进制
从最低位(右边)开始,将每个位上的数提取出来,乘以16的(位数-1)次方,然后求和。
十进制转其他进制
- 十进制转二进制
将该数不断除以2,指导商为0为止,然后将每步得到的余数倒过来。就是对应的二进制。
- 十进制转八进制
将该数不断除以8,指导商为0为止,然后将每步得到的余数倒过来。就是对应的八进制。
- 十进制转十六进制
将该数不断除以16,指导商为0为止,然后将每步得到的余数倒过来。就是对应的十六进制。
其他进制相互转换
- 二进制转八进制
从低位开始,将二进制数每三位一组,转成对应的八进制数即可。
- 二进制转十六进制
从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。
- 八进制转二进制
将八进制数的每一位转成对应的一个3位的二进制数即可。
- 十六进制转二进制
将十六进制数的每一位转成对应的一个4位的二进制数即可。
控制结构
顺序控制
程序从上到下逐行执行,中间没有任何判断和跳转。
分支控制
if...else if...if...
switch...case...default...
循环控制
for(循环变量初始化; 循环条件; 循环变量迭代) { 循环体 }
while(循环条件) { 循环体; 循环变量迭代}
do{ 循环体; 循环变量迭代} while(循环条件)
跳转控制
break
:结束最近的一层循环,推出该层循环continue
:结束本次循环,继续下一层循环return
:表示跳出所在方法
数组、排序、查找
数组
数组可以存放多个
同一类型
数据,数组也是一种数据类型,是引用类型。
数组下标是从0开始编号的。
数组的定义
动态初始化:
数组类型 数组名[] = new 数据类型[大小]
动态初始化,先声明,在创建。
- 静态初始化,
数据类型 数组名[] = {元素值, 元素值, ...}
1 | public class ArrayDef { |
数组的注意事项
- 数组内的元素必须是相同类型,
- 数组中的元素类型可以是任何数据类型,包括基本数据类型或引用数据类型,但不能混。
- 数组创建后,没有赋值,有默认值。
- 数组下标是从0开始的。
- 数组下标必须在指定范围内使用。
- 数组属于引用类型,数组型数据是对象(object)。
数组的赋值机制
- 基本数据类型赋值,这个值就是具体的数据,而且相互不影响。
- 数组在默认情况下,是阴影传递,赋的值是地址。
1 | public class ArrayDef { |
数组拷贝
1 | public class ArrayDef { |
排序
冒泡排序
每次冒泡都将最大的数找出,并移动到后面。
- 需要进行
arr.length - 1
轮排序。 - 第
i
轮排序需要确定第i
大数的位置。 - 每轮比较依次减少
i
次比较。
1 | public class BubbleSort { |
查找
- 顺序查找:用目标值依次和数组中的元素进行比较,若相等,则查找到,若遍历结束仍没有找到,则不存在。
- 二分查找,需要保证原数组是有序的。
二维数组
- 动态初始化:
类型 数组名[][] = new 类型[大小][大小]
- 动态初始化:先声明,在分配空间
- 动态初始化:列数不确定
- 静态初始化
1 | public class ArrayDef { |
类与对象
- 类:就是数据类型,例如Cat
- 对象:就是一个具体的实例,
对象[属性, 行为]
1 | package object; |
属性
属性
也叫成员变量
,也叫field(字段)
- 属性是类的一个组成部分,一般是数据类型,也可以是引用类型。
属性的定义方法:
访问修饰符 属性类型 属性名
访问修饰符包括:public
,private
, protected
,默认为public
成员方法
某个类中的函数就是该类的成员方法或者叫成员函数。
成员方法的定义:
访问修饰符 返回类型 方法名(形参列表) { 函数体 ; return 返回值;}
- 形参列表:代表成员方法的输入。
- 返回类型:表示成员方法的输出,若为
void
,则没有返回值 return
不是必须的
传参机制
- 值传递;方法运行后不会影响实参的值。
1 | class Test{ |
- 引用数据传递:接收数组,传递的是地址。
方法的递归调用
- 直接递归:方法自己本身直接调用自己。
- 简介递归
方法重载
JAVA允许在同一个类中的成员方法中,有多个重名函数存在,但是要求形参列表不一样!
重载的优点
- 减轻了起名的麻烦
- 减轻了记名的麻烦
1 | public class OverLoad01 { |
注意事项
- 方法名必须一样
- 形参列表必须不同,形参类型不同 或者 个数不同 或者 顺序不同。
- 参数名没有要求
- 返回类型无要求,返回类型不是构成方法重载的条件。
可变参数
JAVA允许将同一个类中多个同名同功能但参数个数不同的方法,封装成同一个方法。
for(参数类型... 参数名)
,此时参数名可以当做数组使用。
1 | public class VarParameter01 { |
注意事项
- 可变参数的实参可以直接是数组
- 可变参数的实参可以是0个或多个
- 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
- 一个形参列表只能出现一个可变参数
作用域
包括局部变量或者全局变量
- 局部变量:定义在某一个成员方法中的变量 或定义在某一个代码块中 。作用域仅在该成员方法中 或 该代码块中。
- 全局变量:直接定义在类中的变量,属性就是全局变量,在该类中的任何成员方法中都可以直接使用。作用域在整个类中。
- 全局变量可以不用赋值,有默认值,局部变量必须赋值后才可以使用,不会有默认值。
注意事项
- 属性和局部变量可以重名,使用时遵守
就近原则
- 在同一个作用域内,两个局部变量不能重名
- 属性声明周期比较长,局部变量声明周期相对比较短
作用域范围
- 属性:可以被本类所有成员方法使用,也可以通过对象调用被其他类使用。
- 局部变量:只能在本成员方法中使用。
修饰符
- 属性:可以添加修饰符
- 局部变量:不可以添加修饰符
构造方法/构造器
基本语法:[修饰符] 方法名(形参列表) { 方法体; }
作用:在创建对象时,实现对对象的初始化。
- 构造器的修饰符可以是默认的也可以是其他的。
- 构造器没有返回值
- 方法名和类名必须保持一致
- 构造器的调用是由系统完成的
1 | public class Constructor { |
注意事项
- 一个类可以构造多个构造器,即构造器的重载
- 若没有自定义构造器,则系统会自动给类生成一个默认无参构造器,但是若定义了一个新的构造器,则不会再自动生成一个默认无参构造器。
对象创建流程
- 加载类信息,只会加载一次
- 在堆中分配空间(地址)
- 完成对象初始化,
- 默认初始化
- 显式初始化
- 构造器初始化
- 在对象堆中的地址,返回给创建的对象
this关键字
java
虚拟机给每个对象分配this
,代表当前对象。
作用:在成员方法中,this
主要用在当形参和属性名同名时,使用this.属性名
代替属性名,来区分同名问题。
1 | public class Constructor { |
本质:哪个对象调用,this
就代表哪个对象
注意事项
this
可以访问本类的属性、方法、构造器this
用于区分当前类的属性和局部变量- 访问成员方法时语法:
this.方法名(参数列表)
- 访问构造器语法:
this(参数列表)
;注意只能在构造器中使用 this
不能再类定义的外部使用,只能再类定义的方法中使用
Intellij IDEA
快捷键
功能描述 | 快捷键 |
---|---|
删除当前行 | ctrl + y |
复制当前行 | ctrl + d |
代码格式化 | ctrl + alt + L |
补全代码 | 补全代码:alt + / |
单行注释 | ctrl + / |
多行注释 | ctrl + shift + / |
显示错误 | alt + Enter |
快速运行代码 | ctrl + shift + F10 |
生成构造器、get函数、set函数 | alt + insert |
查看类的继承关系 | ctrl + h |
定位到定义的方法 | ctrl + b |
自动分配变量名 | 在后面加.var |
… | … |
模板
查看模板:file -> settings -> editor -> Live templates -> Java
,可以自定义自己的模板
功能描述 | 快捷键 |
---|---|
主函数 | main + enter |
输出语句 | sout + enter |
for循环语句 | fori + enter |
… | … |
面向对象编程(中)
包
作用
- 可以区分相同名字的类
- 当类很多时,可以很好的管理类
- 控制访问范围
基本语法:package.com.constructor
package
关键字,表示打包com.constructor
表示包名
原理: 创建不同的文件夹来保存类文件。
命名规则
- 只能包含数字、字母、下划线、小圆点,但不能以数字开头,不能是数字或保留字
命名规范
- 一般是小写字母 + 小圆点,一般是
com.公司名.项目名.业务模块名
常用的包
java.lang.*
默认引入,不需要再引入。例如Mathl类
java.util.*
系统提供的工具包,工具类,使用Scanner
java.net.*
网路包,网络开发java.awt.*
Java界面开发,GUI
导入包
基本语法:import 包
,引入一个包的目的是使用该包下面的类。
package
的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一个package
import
放在package
和类之间,可以有多条且顺序没有要求
1 | package com.pkg; |
访问修饰符
java提供四种访问修饰控制符,用于控制方法和属性(成员变量)的访问权限。
- 公开级别:
public
修饰,对外公开 - 受保护级别:
protected
修饰,对子类和同一个包中的类公开 - 默认级别:没有修饰符,向同一个包的类公开,对子类不能访问
- 私有级别:
private
修饰,只有类本身可以访问,不对外公开
注意事项
- 修饰符可以用来修饰类中的属性,成员方法以及类
- 只有默认的和
public
才可以修饰类
三大特征 ⭐
封装
定义: 把抽象出来数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作。
优点
- 隐藏实现细节,直接调用即可
- 可以对数据进行验证,保证安全合理
步骤
- 将属性私有化
- 提供一个
public 的 set
方法,对属性判断并赋值 - 提供一个
public 的 get
方法,用于获得属性值
当使用构造器对属性赋值时,构造器函数体的编写方法需要进行改变
1 | package com.xzt.encapsulation; |
继承
定义: 当两个类中有很多属性和方法是相同的,则可以使用继承来减少代码复用。
基本语法:
class 子类名 extends 父类名 {}
- 子类会自动拥有父类定义的属性和方法
- 父类又叫超类或者基类
- 子类又叫派生类
优点: 代码的复用性、扩展性、维护性都得到很大提升
注意事项:
- 子类继承了所有的属性和方法,但是私有属性不能在子类中直接访问,要通过公共的方法去访问。
- 子类必须调用父类的构造器,完成父类的初始化。 在子类的构造函数中会默认调用
super()
函数 - 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会调用父类的无参构造器,如果父类中没有提供无参构造器,则必须在子类的构造器中用
super()
去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。 - 如果希望指定去调用父类的某个构造器,则显示的调用一下,
super(参数列表)
super()
在使用时,需要放在构造器的第一行(super()
只能在构造器中使用)super()
和this()
都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器- java所有类时
Object类
的子类,Object类
是所有类的基类 - 父类构造器的调用不限于直接父类。将一直往上追溯直到
Object类
(顶级父类) - 子类最多只能继承一个父类(指直接继承),即java中是单继承机制
- 不能滥用继承,子类和父类之间必须满足
is-a
的逻辑关系(子类是父类中的一类)
super关键字: super()
代表父类的引用,用于访问父类的属性,方法,构造器。
- 访问父类的属性/方法,但不能访问
private
私有属性/方法,super.属性名
- 访问父类的构造器,
super(参数列表)
只能放在构造器的第一行
优点
- 调用父类构造器,分工明确,父类属性由父类初始化,子类的属性由子类初始化
- 当子类中有和父类中成员(属性和方法)重名时,为了访问父类的成员,必须通过
super
关键字。 - 若多个上级类都有同名,则
super
访问遵循就近原则
super
和this
的比较
No. | 区别点 | this | super |
---|---|---|---|
1 | 访问属性 | 访问本类中的属性,若本类中没有此属性,则从父类中继续查找 | 访问父类中的属性 |
2 | 调查方法 | 访问本类中的方法,若本类中没有此方法,则从父类中继续查找 | 访问父类中的方法 |
3 | 调用构造器 | 调用本类的构造器,必须放在构造器首行 | 调用父类的构造器,必须放在子类构造器的首行 |
4 | 特殊 | 表示当前对象 | 子类中访问父类对象 |
方法重写/覆盖
方法重写就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么就说子类的这个方法覆盖了父类的方法。
注意事项
- 子类的方法的参数、方法名称要和父类方法的参数、名称完全一样
- 子类的方法的返回类型要和父类方法的返回类型一样,或者是父类返回类型的子类。例如:父类返回类型为
Object
,子类方法的返回类型可以是String
。 - 子类方法不能缩小父类方法的访问权限:
public > protected > 默认 > private
多态
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承的基础之上的。
作用: 提高代码的复用性
- 方法的多态:方法的
重载 和 重写
就体现多态 - 对象的多态:【核心】
- 一个对象的编译类型和运行类型可以不一致。例如:
Animal animal = new Dog()
;可以让一个父类的引用指向子类的对象。animal
的编译类型是Animal
,运行类型是Dog
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型是可以变化的。
- 编译类型看定义时
=
左边,运行类型看=
右边。
- 一个对象的编译类型和运行类型可以不一致。例如:
注意事项
- 两个类存在继承关系
- 多态是向上转型
- 本质:父类的引用指向子类对象
- 语法:
父类类型 引用名 = new 子类类型()
- 特点:编译类型看左边,运行类型看右边
- 多态的向下转型
- 语法:
子类类型 引用名 = (子类类型) 父类引用
; - 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 可以调用子类类型中所有的成员日
- 语法:
1 | Animal animal = new Dog(); // 向上转型 |
属性重写:
- 属性没有重写之说,属性的值看编译类型。
instanceof
比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型。
1 | public class Test{ |
java动态绑定机制 ⭐
- Java重要特性:
动态绑定机制
- 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
1 | package com.xzt.poly._dynamic; |
多态的应用
- 多态数组:数组的定义类型为父类型,里面保存的实际元素类型为子类型
1 | public class Tes{ |
- 多态参数:方法定义的参数类型为父类,实参类型允许是子类类型。
Object 类详解
equal
方法
==
既可以判断基本类型,又可以判断引用类型==
如果判断基本类型,判断的是值是否相等,==
如果判断引用类型,判断的是地址是否相等,即判断的是否是同一个对象equal
是Object
类中的方法,只能判断引用类型- 默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。
1 | // String类中重写的equals方法 |
hashCode
方法
- 提高具有哈希表结构的容器的效率
- 两个引用,如果指向的是同一个对象,则哈希值肯定是一样
- 两个引用,如果指向的是不同对象,则哈希值不一样
- 哈希值主要是根据地址号来的,不能完全将哈希值等价于地址
1 | public class Test{ |
toString
方法
默认返回:全类名 + @ + 哈希值的十六进制
1 | // Object 类中的toString方法 |
- 重写
toString
方法,在类中使用快捷键alt + insert
然后选中toString
即可 - 当直接输出一个对象时,
toString
方法会被默认调用
finalize
方法
- 当对象被回收时,系统会自动调用该对象的
finalize
方法。子类可以重写该方法,做一些释放资源的操作 - 什么时候被回收:当某个对象没有任何引用时,则
jvm
就认为该对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize
方法 - 垃圾回收机制的调用,是由系统来决定(即有自己的
GC算法
),也可以通过System.gc()
主动触发垃圾回收机制。
断点调试
在断点调试过程中,试运行状态,是以对象的运行类型来执行的。
- 断点调试是指在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。进行分析从而会找到这个Bug
快捷键
快捷键 | 功能 |
---|---|
F7 |
跳入方法内 |
F8 |
跳过,逐行执行代码 |
shift + F8 |
跳出方法 |
F9 |
resume,执行到下一个断点 |