1. 基础语法
2. 面向对象
3. 常用API、常用类型
4. 集合
5. 多线程(线程状态、线程安全、线程池、线程间通信)
6. IO
7. 其它(Swing开发、异常正则表达式、TCP、Socket、HTTP、爬虫)
一、基础语法
- 数据类型
1. 基本类型(8种:byte-8bit整数、short-16bit整数、int-32bit整数、long-64bit整数、float-32bit浮点、double-64bit浮点、boolean、char-16bit字符)
2. 引用类型(存储对象的地址值、也就是我们常说的指针。Java中string是引用类型)
提问:string str1= ""; string str2= null;区别就是str1指向的对象内容为空,str2就是没有指向任何对象。 - 变量的初始化
- 任何变量在使用之前都必须先初始化(赋值)
- 局部变量:需要程序员手动初始化
- 非局部变量(实例变量也就是实例变量、类变量也就是static):编译器会自动给未初始化的变量设置一个初始值
-
运算符
-
>>
与>>>
截屏2021-01-27 下午3.44.36.png
- boolean 在判断语句中,必须是boolean类型才行。Java中(
&&
||
)的bool判断具有短路
功能,Java中(&
|
)的bool没有短路
功能。
-
-
类型转换
- 小转大,自动转(隐式转换); 大转小,必须强转(也就是必须添加强转的类型)。
- 数组创建
- int [] arr1; int【】 arr2 = {}; int arr3[ ] = {};
- Java中 字符串数组不等于字符串 。
-
数组索引如何实现。比如int aray[n] 如何快速查找到。(随机访问、速度快、O(1))
array的地址0x1110,那么array[n] = 0x1110 + n*4 即可找到目前对象地址。4是取决于什么元素,int是4字节,long是8字节。
截屏2021-01-27 下午5.45.56.png
-
方法
-
可变参数 注意用
(int... numbers)
public static void main(String[] args) {
System.out.println(sum());
System.out.println(sumTest(new int[] {10,20,30}));
}
// 可变就是随便你定,外部参数为null也是可以的。允许外界直接传整数,然后numbers可以将整数初始化数组,什么都不传numbers的长度为0
// 也就是numbers会把外面传入的null转换为一个空数组,所以可以放心使用numbers
public static int sum(int... numbers) {
System.out.println(numbers.length);
return 2;
}
// 如果参数这么写,要求外界引用时候必须传数组,如果外面传入数组为null那么方法内部使用numbers就会报错。
public static int sumTest(int[] numbers) {
System.out.println(numbers.length);
return 2;
}
-
参数传递
- 基本类型作为参数是值传递,返回值返回的也是值。
- 引用类型作为参数是引用传递(地址传递),其返回也是地址传递。
-
方法签名(Method、Signature)
由两部分组成:方法名、参数类型。 -
方法重载(OverLoad)
Java的方法支持重载:方法名相同,方法签名不同。
也就是方法名相同,参数个数不同,参数类型不同 -
栈帧(stack frame)
栈帧随着方法的调用而创建,随着方法结束而销毁,存储了方法的局部变量信息。 -
递归调用
如果递归调用没有终止,将会一直消耗栈空间
最终导致栈内存溢出(Stack Overflow)
所以必须要有一个明确的结束递归的条件
也叫做边界条件、递归基。
截屏2021-01-27 下午7.59.21.png
-
Java一些特性
- Java一个类只有一个main,多个类可以有多个main,编译执行时候编译的哪个类则执行哪个类的main方法。
- 注释。单行、多行、文档注释(/**+enter)
- IDEA中如何关联 JDK源码。
Java SE 就是Java语言基础
二、面向对象
- 对象与数组的内存分析
- 内存区域划分
- 构造方法
- 包
- 继承
- 重写_super
- 构造方法细节
- Annotation
- 访问控制
- 封装_toString
- static
- 静态导入
- 初始化
- 单例模式
- final_常量
- 内部类
- 静态嵌套类
- 局部类
- 抽象类
- 接口01_基本使用
- 接口02_细节
- 接口03_对比抽象类
- 接口04_默认方法
- 接口05_静态方法
- 多态
- 使用接口的好处
- 匿名类01_基本使用
- 匿名类02_用途
- 匿名类03_排序
- Lambda01_基本使用
- Lambda02_使用注意
- 方法引用
1. 对象与数组的内存分析
- 对象内存new 出来的对象是在堆空间,方法内部的变量dog、person这个在栈的方法里。

-
数组内存:
如下图,dogs指向Dog[7]的首地址,Dog[7]中存放的是7个地址,然后每个地址再指向一个实例dog对象。
截屏2021-01-28 下午5.00.38.png
2. Java程序的内存划分
Java虚拟机在执行Java程序时会将内存划分为若干个不同的数据区域。
PC寄存器:存储Java虚拟机正在执行的字节码指令的地址。
Java 虚拟机栈: 存储栈帧。
堆:存储GC(垃圾回收)所管理的各种对象。也就是平时new出来的对象。
方法区:存储每一个类的结构信息.(结构信息:字段和方法信息、构造方法和普通方法的字节码等)
本地方法栈:支持native方法的调用。(比如用C语言编写的)
3. 构造方法 Constructor
只有在构造方法里,才可以使用this\super调用别的构造方法

this
this 本质是一个隐藏的、位置最靠前的方法参数。
只要面向对象的编程语言,其实this、self的本质都是一样的。

4. 包(package)
Java中包就是其他编程语言中的命名空间,包的本质是文件夹。
将不同的类进行组织管理、访问控制
解决命名冲突
为解决包名的唯一性,一般包名都是以公司域名的倒写开头,比如com.baidu.
全小写
类的第一句代码必须使用package声明自己属于哪个包。如:package com.baidu.model;
导入包 import xxx
5. 继承(Inheritance)
Java中对象都是继承自基类Object。
Student 继承自 Person ,那么Person中存在的成员变量被Student继承。person、student对象分别在堆中开辟内存,每个对象中都存在基类person的age,同时student也会存在自己成员变量age。
总结一下:子类对象包含父类所有成员属性,父类私有变量也是存在,只是编译时候对访问权限进行的控制,但是不影响在子类对象内存在(可以通过set 、get进行设置、读取)

6. 方法的重写(Override)
重点: 子类的方法签名
与父类一样。
子类
重写的方法权限
必须 大于
父类
的方法权限
子类
重写的方法返回值类型
必须 小于
父类
的方法返回值
类型
子类 <= 父类
7.构造方法细节
super
访问父类中定义的成员变量
访问父类汇总定义的方法(包括构造方法)
子类的构造方法必须先调用父类的构造方法
,再执行后面的代码。(不同语言有不同语言的特性,Java语言中子类的构造是先默认调用了父类的构造)
编译器会自动调用父类无参的构造方法(若此时父类没有无参的构造方法,编译器将报错)
8. 注解(Annotation)
@Override :告诉编译器这是一个重写后的方法 。方法签名
要一致才行。
@SuppressWarnings(”警告类别“):让编译器不生成警告信息
9. 访问控制(Access Control)
Java中存在4个基本访问权限,从高到低如下所示
1. public:在任何地方都是可见的
2. protected:尽在自己的包中,自己的子类中可见
3. 无修饰符(什么都不写):仅在自己的包中可见。
4. private:仅在自己的类中可见
上述4中访问权限都可以修饰类的成员(成员变量、方法、嵌套类等)
只有public 、无修饰符可以修饰顶级类(Top-level Class)
上述4个访问权限不可以修饰局部类(Local Class)、局部变量
一个Java源文件中可以定义多个顶级类,public顶级类的名字必须和文件名一样
10. 封装_toString
成员变量 private
化,提供public
的getter、setter。
建议提供一个无参的构造函数。
我们可以重写对象的toString方法
public class Person {
private int age;
private String name;
public init getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
封装、继承、多态。三大特性。。。
11. static_final
static
常用来修饰类的成员:成员变量、方法、嵌套类。
我们需要知道创建多少个对象时候,构造函数统计static数据++就行。
static修饰成员变量:
程序运行过程中只占用一份固定的内存(存储在方法区、全世界只有一份内存)
可以通过实例、类访问
没有static修饰成员变量:
在每个实例内部都有一份内存
只能通过实例访问,不可以通过类访问。
static修饰方法:
1. 被static修饰的方法叫做:类方法、静态方法。
2. 内部不允许使用this。(this本质是实例对象在用方法时候把自身对象传入方法内部,所以static修饰的方法不能用this)
3. 可以直接访问类变量、类方法
4. 不可以直接访问实例变量、实例方法(由于类方法中没有this,所以不可以调用实例变量,实例方法)
没用static修饰方法称之为实例方法:
1. 实例方法只能通过实例访问,不可以通过类访问
2. 内部可以使用this
3. 可以直接访问实例变量、实例方法
4. 可以直接访问类变量、类方法
不能有同名的实例变量和类变量。不能有相同签名的实例方法和类方法
12. 静态导入
静态导入后,可以省略类名来访问静态成员(成员变量、方法、嵌套类)

13. 初始化

14. 单例模式(Singleton Pattern)
1. 构造方法私有化。(禁止外面调用构造方法)
2. 公告的静态的方法,返回唯一的那个实例
3. 私有的静态的实例变量
/***
* 饿汉式单例模式,上来就先创建一个单例对象
*/
public class Person {
// 私有的静态的实例变量
private static Person instance = new Person();
// 构造方法私有化
private Person() {
}
// 公共的静态的方法,返回唯一的那个实例
public static Person getInstance() {
return instance;
}
}
/***
* 懒汉式单利模式,需要的时候调用生成
*/
public class Person {
// 私有的静态的实例变量
private static Person instance = null;
// 构造方法私有化
private Person() {
}
// 存在线程不安全的问题。多个线程同时调用的时候,多条线程同时创建多个instance,但是后期是唯一的,但仍然在开始创建时不安全。
public static Person getInstance() {
if (instance == null) {
instance = new Person();
}
return instance;
}
}
饿汉式单例没有线程安全问题
,懒汉式单例存在线程安全问题。
线程安全问题,一旦加了锁,效率都会降低。所以我们可以直接用饿汉式单例
。
15. final_常量
1. 被final修饰的类:`不能被继承`
2. 被final修饰的方法:不能被重写
3. 被final修饰的变量:只能进行1次赋值
Java 中说的常量。命名规范常量全是大写字母
public static final double PI = 3.141592653;
通过指的 static final这种修饰的
如果将基本类型或字符串定义为常量,并且在编译时就能确定值
编译器会使用常量值替代各处的常量名(类似于C预言的宏替换)
成为编译时常量
16. 嵌套类(Nested Class)
嵌套类:定义在另一个类中的类。
静态嵌套类(static修饰的)
非静态嵌套类(内部类)
内部类:是先创建外层的对象,然后再创建内部类对象person.new。内存表示如下如:

内部类:没有被`static`修饰的嵌套类,非静态嵌套类。
跟实例变量、实例方法一样,内部类与外部类的实例相关联。
必须先创建外部类实例,然后再用外部类实例创建内部类实例
内部类不能定义除编译时常量意外的任何`static`成员
内部类可以直接访问外部类中的所有成员(即使被声明为`private`)
外部类可以直接访问内部类实例的成员变量、方法(即使被声明为`private`)
17. 静态嵌套类(Nested Class)
- 静态嵌套类:被
static
修饰的嵌套类
2.静态嵌套类在行为上就是一个顶级类,只是定义的代码写在了另一个类中。 - 对比一般的顶级类,静态嵌套类多了一些特殊权限
- 可以直接访问外部类中的成员(即使被声明为
private
)
什么情况使用嵌套类?
如果类A只用在类C内部,可以考虑将类A嵌套到类C中
封装性更好
程序包更加简化
增强可读性、维护性
如果类A需要经常访问类C的非公共成员,可以考虑将类A嵌套到类C中
另外也可以根据需要将类A隐藏起来,不对外暴露
如果需要经常访问非公共的实例成员,设计成内部类(非静态嵌套类),否则设计及成静态嵌套类
如果必须先有C实例,才能创建A实例,那么可以将A涉及为C的内部类。
18.局部类(Local Class)
局部类:定义在代码块中的类(可以定义在方法中、for循环中、if语句中等)
局部类不能定义除编译时常量以外的任何static
成员
局部类只能访问 final
或者 有效 final
的局部变量
局部类可以直接访问外部类中的所有成员。(即使被声明为private
)
局部类只有定义在实例先关的代码块中,才能直接访问外部类中的实例成员(实例变量、实例方法)
19.抽象类(Local Class)
抽象方法(Abstract Method)
抽象方法:被 `abstract`修饰的方法
只有方法声明,没有方法实现(参数列表后面没有大括号,而是分号)
不能是 `private`权限(因为定义抽象方法的目的让子类去实现)
只能是实例方法,不能是类方法。
只能定义在抽象类、接口中
抽象类
抽象类:被 `abstract`修饰的类(此类就是作为父类被继承用的)
可以定义抽象方法
不能实例化,但可以自定义构造方法(等着被子类去调用😬)
子类必须实现抽象父类中的所有抽象方法(除非子类也是一个抽象类)
可以像非抽象类一样定义成员变量、常量、嵌套类型、初始化块、非抽象方法等
为什么使用抽象类
抽取子类的公共实现到抽象父类中,要求子类必须要单独实现的定义成抽象方法。
抽象方法是要求子类强制实现的方法。只是堆积抽象公共方法
20.接口01_基本使用
Java中的接口:
一系列方法声明的集合
用例定义规范、标准
接口定义:抽象方法、常量、嵌套类型。
这个接口就是规定 方法(规范),其它依赖这个接口的类实现里面的方法即可。
接口就是:有做哪些能力
21.接口02_细节
接口、抽象类都不能实例化。
接口可以在任何使用类型的地方使用。
一个类可以通过`implements`关键字实现一个或多个接口
实现接口的类必须实现接口中定义的所有抽象方法,除非它是个抽象类
如果一个类实现的多个接口中有相同的抽象方法,只需要实现此方法一次。
`extends`和`implements`可以一起使用,`implements`必须写在`extends`的后面
当父类、接口中的方法签名一样时,那么返回值类型也必须一样
一个接口可以通过`extends`关键字继承一个或者多个接口
22.接口03_对比抽象类
抽象类:
1.继承 A extends B , A 拥有B 的方法。
接口:
实现:A implements B , A会B中的行为。
何时选择抽象类?
- 在紧密先关的类之间共享代码
- 在要除
public
之外的访问权限 - 需要定义实例变量、非
final
的静态变量
何时选择接口?
- 不相关的类实现相同的方法。
- 只是定义行为,不关心具体是谁实现的行为
- 想实现类型的多重继承
23.接口04_默认方法
接口升级问题:
如果接口需要升级,比如增加新的抽象方法。
会导致大幅的代码改动,以前实现接口的类都需要改动。
若想在不改动以前实现类的前提下进行接口升级。从Java8开始,有2种方法
- 默认方法
- 静态方法
1. 默认方法的使用
当一个类实现的接口中有默认方法是,这个类可以
啥也不干,沿用接口的默认实现
重新定义默认方法,覆盖默认方法的实现
重新声明默认方法,将默认方法声明为抽象方法(此类必须是抽象类)
当一个接口继承的父接口中有默认方法时,这个接口可以
啥也不干,沿用接口的默认实现
重新定义默认方法,覆盖默认方法的实现
重新声明默认方法,将默认方法声明为抽象方法
如果父类定义的抽象方法与接口的默认方法相同时,要求子类实现此抽象方法
可以通过super
关键字调用接口的默认方法。调用代码接口名.super.方法
24.接口05_静态方法
定义:
接口中定义的静态方法只能通过接口名调用,不能被继承。
类是单继承,接口是多继承所以静态方法不能被继承下去。
25.多态(Polymorphism)
什么是多态?
具有多种形态
统一操作作用于不同的对象,产生不同的执行结果
JVM会根据引用变量指向的具体对象来调用对应的方法
这个行为叫做:虚方法调用
类似于C++中的虚函数调用
多态提现:
父类(接口)类型指向子类对象
调用子类重写的方法
静态方法中,如果基类类型那么调用的时候还是基类的静态方法。可以看一下dog2的方法。

如果没有static
的则是子类方法了
成员变量的访问细节

instanceof
可以通过instanceof
判断某个类型是否属于某个类型
26.使用接口的好处
面向接口编程
业务层==》dao层(数据库)这是最常见的需求
但是我们需要面向接口,也就是 业务层是通过调用 接口 来实现查询 dao层数据。可以做到类的解耦。
可以看下面图:接口是LoginDao,实现接口LoginDaoH、LoginDaoM的类,如果需要变更那我们只需要更改这些类即可。

27.匿名类01_基本使用
匿名类:当接口、抽象类的实现类,在真个项目中只用过一次,可以考虑使用匿名类。
使用接口,必须要有对应的类实现这个方法。我们使用这个类,就可以把这个方法实现。但是假如这个类,只使用过一次,这时候类使用匿名类。

28.匿名类02_用途
首先演示一下,代码传递。
写一个工具类:统计某一段代码的执行时间。
工具类通常写在一个包内。
package timeTest;
public class Times {
//搞一个带接口的 代码块
public interface Block {
void execute();
}
//外部传入代码块,传入的代码块中需要实现接口方法。然后这里测试执行方法实现需要的时间
public static void test(Block block) {
long begin = System.currentTimeMillis();
block.execute();
long end = System.currentTimeMillis();
double duration = (end - begin) / 1000;
System.out.println("耗时" + duration + "s");
}
}
具体使用
import timeTest.Times;
import timeTest.Times.Block;
public class mainTime {
public static void main(String[] args) {
// 匿名类执行,传入block块,实现block块里面的接口即可。
Times.test(new Block() {
@Override
public void execute() {
int age = 100000;
String string = "";
for (int i = 0; i < age ; i++) {
string += i;
}
}
});
}
}
当然我们可以通过 类 实现某个类中,某段代码耗时问题。但是这样存在的问题是不灵活,我们每次都需要写一个类测试,不如我们直接填入需要测试的代码。
回调
其实跟代码传递类似,只是决定哪个时刻调用哪个接口方法而已。
过滤器
1.先把过滤器内部功能实现.内部需要实现传入的路径获取所有文件数据。然后对这些文件数据单独筛选是否需要返回,再单独对文件进行筛选返回的时候,需要外部对这个文件名进行选择确认,筛选出对应数据。
public class Files {
public interface Filter {
boolean accept(String filename);
}
public static String[] getAllFilenames(String dir, Filter filter) {
// 1. 现获取dir下所有文件名
String[] allFilenames = {};
// 2. 进行过滤
for (String filename: allFilenames) {
if (filter.accept(filename)) {
// 将这个文件名包装起来
}
}
// 3. 返回所有装起来的文件名
}
}
- 外部如何调用,再实现一下。
import timeTest.Files;
import timeTest.Files.Filter;
public class mainFilter {
public static void main(String[] args) {
Files.getAllFilenames("F",new Filter(){
@Override
public boolean accept(String filename) {
return filename.contains("过滤内容条件");
}
});
}
}
29.匿名类03_排序
Array.sort默认是升序排列
会把小的放左边,大的放右边。
30.Lambda Expression
函数式接口:只包含一个抽象方法的接口。
前面添加@FunctionalInterface表示函数是接口,规范。
// 标准形式
(参数列表) -> {
return xxxxx;
}
//简写形式
(参数A、参数B) -> xx
31.Lambda 的使用注意
只能访问final或者有效 final的局部变量
没用引入新的作用域
32.方法引用
种类::方法
对于lambda的一种简化.如果Lambda中的内容仅仅是调用某个方法,可以使用方法调用来简化。
-
引用类方法
Testable t1 = (v1, v2) -> Math.max(v1,v2);
或者Testable t1 = (v1, v2) -> Math::max;
-
引用特定对象的实例方法
截屏2021-02-25 上午11.46.46.png
-
运用特定类型的任意对象的实例方法
-
引用构造方法
-
引用数组的构造方法
-
引用当前类中定义的实例方法
-
引用父类中定义的实例方法
三、常用类型
- 枚举
- 包装类01_基本使用
- 包装类02_细节
- Math_Random_UUID
- 数字格式化_BigDecimal
- String01
- String02_intern
- String03_常用方法
- StringBuilder
- Date_Calendar
1.枚举 ENUM
枚举目的是保证变量的取值为固定的那几种。
如果一个变量的取值只可能是固定的几个值,那么可以考虑枚举类型。
枚举由一组预定义的常量构成
public enum Season {
SPRING, SUMMER, FALL, WINTER
}
Season s = Season.WINTER;
枚举的本质就是类
枚举的构造方法权限必须是无修饰符 或者 private
Java枚举会主动调用构造方法初始化每一个常量,你不能主动调用构造方法。初始化常量时候自己主动调用。
2.包装类01_基本使用
基本类型的缺陷
对比引用类型,基本类型存在的一些缺陷
- 无法表示不存在的值(也就是不存在null值)
- 不能利用面向对象的方式去操作基本类型(比如直接用基本类型调用方法)
- 当方法参数是引用类型时,基本类型无法传递。
解决办法,将基本类型包装成引用类型
public class IntObject {
public int value;
public IntObject(int value) {
this.value = value;
}
}
包装类(Wrapper Class)
Java中已经内置了基本类型的包装类(都在java.lang包中)

基本类型与包装类的关系,这点要搞明白。
自动装箱:基本类型转为引用类型。
自动拆箱:引用类型转为基本类型。
转的时候,注意缓存中数据大小[-128, 127]范围的Integer对象
包装类的判等 引用类型中 == 比较的是内存地址。

这个就是127内整数,有缓存是同一个对象。new的话就是新的对象,所以不是同一对象。

使用注意
基本数据数组 与 包装类数组之间不能自动装箱、拆箱的。
需要遍历,然后加入数组内部。
3.包装类02_细节
Math

4. Math_Random_UUID
Random产生随意数
UUID
通用唯一标识符
分布式系统上面用的
5. 数字格式化_BigDecimal


高精度计算
float、double存储的小数只是存的近似值,并非精准值。因此不适合用来进行高精度计算
小数转二进制常识问题,乘以2,乘以2这样进行推算出二进制数

使用BitDecimal进行高精度计算,使用字符串进行计算就是准确的了。
原理:大数乘法。底层是将字符串单独存储,然后按位进行乘、加等
6. String01
底层用char[ ] 存储字符数据,但是从Java 9 开始,底层使用byte[ ] 存储字符数据。
思考一下,为什么之前用 char,后面改为byte。
小小知识点
Java中,{ }表示的数组,但是JavaScript中表示的一个对象,iOS中表示一个字典也就是对象。
Block是什么?
Block是C语言的一个语法特性,同时也是C语言的运行时特性,它很像C中的函数指针,因为你可以像使用函数指针一样的去使用block对象;它也很像C++中的函数对象,因为除了要执行的代码,block还可以携带和block绑定的状态信息。
因此,block是一个对象,这个对象里包含了要执行的代码片段以及一些状态信息。
网友评论