Java的学习笔记
这里的内容完全照搬我在课堂上写的笔记和自己乱七八糟的思想。
课堂学习
项目结构
maven标准目录结构
my-project/
├── src/
│ ├── main/
│ │ ├── java/ # Java 源代码
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── MyClass.java
│ │ ├── resources/ # 资源文件
│ │ │ ├── config.properties
│ │ │ └── log4j2.xml
│ │ └── webapp/ # Web 应用文件(如果是Web项目)
│ └── test/
│ ├── java/ # 测试代码
│ │ └── com/
│ │ └── example/
│ │ └── MyClassTest.java
│ └── resources/ # 测试资源
├── target/ # 编译输出(自动生成)
├── pom.xml # Maven 配置文件
└── README.md
例子:
公司 (项目)
└── 技术部、市场部、财务部 (模块)
└── 技术部/前端组、后端组、测试组 (包)
└── 前端组/张三、李四 (类)
10.21重新写//之前写的太烂了,什么要点都没有,所以直接全烧了重新来一遍,也就当复习了
static关键字
内存静态,对立于对象
生命周期静态:与整个程序的进程一致
绑定静态:编译时确定调用关系,不依赖运行时的对象。
状态静态:表示为与具体的对象无关共享状态活行为。
何时使用?与类无关则使用,描述对象则不用
第四章
在这里我们将会着重讨论关于类的一切
4.1类的重要特征
封装继承以及多态。
4.1.1封装
4.1.2继承
类的复用有两种方式:组合与继承(原则是多用组合,少用继承)
类的声明格式:
修饰符 class class_name extends super_class{//代码体}
因此很简单的就能得出几个小总结:
- 公共操作在父类中
- 不使用受保护的字段
- 多使用多态方法或接口
- 继承打破了封装性,增强了耦合性
- 使用多态方法或者接口,比使用多种类型检测代码更易于维护和扩展
- 不要滥用反射
反射是编程语言提供的一种强打的能力,让程序在运行时检查修改自身的结构和行为【观察并修改自己】(其实我们还是不怎么玩这个东西)
组合为什么比继承的使用优先度更高呢?因为组合式更加复杂的黑盒式代码复用,不会破坏封装性
只有在子类的行为符合is-a关系时才适合使用继承
this关键字
this.属性名:表示当前对象的属性
this.方法名:表示调用当前对象的方法
super关键字
super.超类属性名:调用父类中的属性
super.超类方法名:调用父类的方法
super():调用父类的无参构造方法
super(参数):有参
一些注意的事项:
子类和父类的方法重名时,直接访问得到的是子类方法,使用super可以调用父类
this和super构造器只能选择一个
this()和super()都指的是对象,均不可以在static环境中使用
final
在 Java 中,声明类、变量和方法时,可使用关键字 final 来修饰。final 所修饰的数据具有“终态”的特征。为你的类加密,使得封装更加彻底
final修饰的类不能被继承,该类包含的方法也将被隐式地声明为final,但是变量不是。final修饰的方法不能被子类重写。被final修饰的方法为静态绑定,不会产生多态(动态绑定)。final修饰的变量(成员变量或局部变量)即成为常量,只能赋值一次。final修饰的成员变量通常在声明的同时赋值,如果没有赋值,那么只有一次机会而且只能在构造方法中显式赋值。final修饰的局部变量可以只声明不赋值,然后再进行一次性的赋值。- 被
static或private修饰的方法会被隐式的声明为final,因为动态绑定没有意义。
//到这里,继承的内容也就结束了
4.1.3多态
多态的定义:指父类定义的属性或方法被子类继承后,可以表现出不同的行为或数据类型。同一操作作用于不同对象,可以有不同的解释和结果。
多态的分类:
- 编译时多态(静态):主要指方法重载。
- 运行时多态(动态):主要指方法重写,通过动态绑定实现。
实现多态的三大必要条件:继承、重写、向上转型。
重写(Override)的规则:子类对父类的非静态、非private、非final、非构造方法进行重新编写,方法签名(名称和参数)必须相同。
在实际开发中,多态的作用可以归结为以下几点:
- 降低耦合:程序依赖于抽象(父类/接口),而非具体实现,使得各个模块可以独立变化。
- 增强扩展性:增加新功能时,只需添加新的子类,无需修改现有基于父类的代码。
- 提高代码复用性:通过父类提供通用方法,子类继承并差异化实现,避免了代码重复。
- 使代码更灵活、更易于维护:程序在运行时才决定调用哪个方法,这使得程序的行为可以动态变化,适应新的需求。
简单来说,多态让我们的代码从“谁在干活”的细节中解放出来,只关心“要干什么活”,这是构建大型、复杂软件系统的关键。
到这里,类的封装继承与多态就完工了,然后我们来总结一下“公式”(跳转到最后去看就行了)#
4.2抽象类与接口
所有的对象都是通过类来实例化的,如果说一个类没有足够具体,那它就是抽象类,反之则为具体。
接口时抽象方法的集合,是由全局常量和公共抽象方法所组成的,接口不是类,它被理解为一种特殊的类,用来建立类与类之间的协议
4.2.1抽象类
- 使用abstract声明
- 方法抽象,类也抽象
- 抽象类中可以有抽象方法也可以有具体方法,但是抽象方法只能在抽象类中
- 抽象类无法实例化,也就无法new创建对象
4.2.2接口
public关键字
公有承诺,接口一律使用public声明
| 修饰符 | 本类 | 同包 | 不同包子类 | 不同包其他类 | 工程用途 |
|---|---|---|---|---|---|
public | ✅ | ✅ | ✅ | ✅ | 对外API |
protected | ✅ | ✅ | ✅ | ❌ | 框架扩展点 |
默认 | ✅ | ✅ | ❌ | ❌ | 模块内部实现 |
private | ✅ | ❌ | ❌ | ❌ | 类内部细节 |
一个接口可以有多个直接父接口,接口只能继承接口,不能继承类
4.2.3抽象类于接口之间的联系与区别
- 接口和抽象类都不能实例化
- 接口抽象类都可以包含抽像方法
- 接口中的所有方法都是抽象的,抽象类可以实现部分方法
- 接口是可以继承的
- 接口中的基本数据类型为static而抽象类不是
4.3内部类
是常规类之下的类,相当于类的零件(产品和组件的关系)
- 内部类提供了更好的封装,不允许同一个包下的其他类访问
- 内部类是外部类的一个成员,但是在static修饰时,仍然只能访问外部类的静态成员
- 内部类与外部类不能重名,内部类仍然是一个独立的类,在编译之后内部类会被变异成独立的.class文件
- 在外部类中可以直接通过内部类的类名访问内部类。在外部类以外的其他类中则需要通过内部类的完整类名来访问内部类。
4.3.1成员内部类
成员内部类又分为非静态和静态两种(依照是是否被static修饰来区分)
非静态的又称为实例内部类,无static修饰。而静态则有static修饰。
根本区别就在于是否有必要实例化
4.3.2局部内部类
只在方法之内使用使用…(反正谁都不怎么用,还是别大费周章了)
4.3.3匿名内部类(最重要)
下面这个是ppt原文
new className(参数列表)|Abstractclass(参数列表)|InterfaceType(){
//代码块
}
我还是直接摆四个模板吧,不然真的容易头晕
先明确一点:有参数就写,没参数就不填,区别就是继承自不同类型的父类
1.赋值给一个变量:
父类类型 引用变量名 = new 父类名(参数列表){...}
2.直接作为参数传递:(最常用)
方法名(new 父类名/接口名() {
// 实现方法
});
3.作为返回值:
public 父类/接口类型 方法名() {
return new 父类名/接口名() {
// 方法实现
};
}
4.直接调用方法
new 父类名/接口名() {
// 方法实现
}.方法名(); // 立即调用
到这里你可以很清楚的感觉到匿名内部类最主要的目的就是简化代码
//但是你很快就会想到,它真的简化了代码么?
缺点:
- 代码长度:比Lambda长很多
- 可读性:比单独类差(逻辑混在主线代码中)最让人头疼的就是这一点
- 维护性:修改时要找到匿名类的位置
优点却很有限:
- 避免创建单独文件(但现代IDE管理文件很方便)
- 代码在一起(但可能让主方法变得臃肿)
所以匿名内部类更像是一个过渡,它是为了引出lambda表达式而出现的小插曲,只要能读懂它的含义就足够了
4.4 lambda表达式
核心就是参数指向方法,意思是对这些参数执行方法中的行为(我觉得这句已经总结的足够好了)
直接给个表哈:
| 知识点 | 一句话说明 |
|---|---|
| 本质 | 匿名方法,可作为参数传递 |
| 语法 | (参数) -> {方法体} |
| 用途 | 简化单方法接口的实现 |
| 条件 | 只能用于函数式接口 |
| 优势 | 代码简洁,支持函数式编程 |
这幻灯片的确有点不适合阅读,所以直接让爱哥帮我整理了
🎯 Lambda表达式省略规则(清晰版)
1. 参数类型省略
规则:参数类型可以推断时,可以省略
// 完整写法
(int a) -> System.out.println(a)
(int a, int b) -> a + b
// 省略写法(推荐)
(a) -> System.out.println(a)
(a, b) -> a + b
实际上就是参数列表指向方法体,这里相对而言还是十分简单的。
2. 单参数括号省略
规则:只有一个参数且类型可推断时,() 可省略
// 完整写法
(a) -> a * a
(String s) -> s.length()
// 省略写法(推荐)
a -> a * a
s -> s.length()
3. 方法体花括号省略
规则:方法体只有一条语句时,{} 可省略
// 完整写法
(a, b) -> { return a + b; }
() -> { System.out.println("Hello"); }
// 省略写法(推荐)
(a, b) -> a + b // 自动return
() -> System.out.println("Hello")
4. 多参数/多语句情况
规则:多个参数或语句时,符号不能省略
// 这些必须保留括号/花括号
(a, b) -> a + b // ✅ 多参数要()
(a, b) -> {
int sum = a + b; // ✅ 多语句要{}
return sum * 2;
}
📋 省略规则总结表
| 情况 | 可省略什么 | 示例 |
|---|---|---|
| 参数类型可推断 | 类型声明 | (int a) → (a) |
| 单参数 | 圆括号 () | (a) → a |
| 单条语句 | 花括号 {} | { return a; } → a |
| 单条语句+无参 | () + {} | () -> { x++; } → () -> x++ |
🚫 不能省略的情况
// 错误!多参数不能省略()
a, b -> a + b // ❌
// 错误!多语句不能省略{}
(a, b) -> int sum = a + b; return sum; // ❌
// 错误!有类型声明时单参数也要()
int a -> a * a // ❌
💡 实际开发建议
推荐写法:在可读性的前提下尽量省略
// 好的写法
names.stream()
.filter(name -> name.length() > 3) // 单参数省略()
.map(String::toUpperCase) // 方法引用
.forEach(System.out::println); // 方法引用
// 清晰且简洁!✨
这样整理后是不是清楚多了?Lambda的省略规则其实就这几点!
最后这两个就直接偷懒了,实在有肝不下去了
4.5 UML图 - 核心要点
UML本质:统一建模语言,软件的“蓝图”
两大类图:
🏛️ 结构图(静态,描述系统组成部分)
- 类图:核心!展示类、接口、关系(继承、实现、关联)
- 对象图:某一时刻对象的快照
- 组件图:软件模块构成(Jar包、DLL)
- 部署图:软件在硬件上的部署
🎬 行为图(动态,描述系统如何工作)
- 用例图:系统能帮用户做什么
- 顺序图:对象间调用的时间顺序
- 状态图:对象生命周期状态变化
- 活动图:业务流程步骤(类似流程图)
记忆技巧:
- 结构图回答“有什么”
- 行为图回答“怎么做”
4.6 引用 - 核心要点
引用本质:对象的“遥控器”或“地址标签”
关键理解:
Person p = new Person();
// p不是对象本身,而是指向对象的引用
引用特点:
- 多个引用可以指向同一个对象
- 引用传递的是地址,不是对象副本
==比较引用地址,equals()比较对象内容
内存关系:
引用p ───→ [Person对象]
(在堆内存中)
第五章泛型集合与枚举
泛型与集合还有枚举
5.1泛型
指定类型的控制器,一种编程机制,不是特定的某种类型
5.1.1泛型的基本概念
泛型是一种参数化类型的编程方式,常见的应用范围是类、接口、方法。
5.1.2如何使用
就像上边那老哥说的那样,使用范围是类、接口还有方法
泛型类
class 类名称<泛型标识,泛型标识,...>{
private 泛型标识 变量名;
....
}
泛型类就是在定义类时,在类名后面加上一个或多个类型参数,告诉使用者:“这个类需要你传入具体的类型参数才能使用”
然后这个时候你可能会提出一个问题:这不是连具体的类型都没有么?咋实例化啊?
1939

被折叠的 条评论
为什么被折叠?



