开始时间: April 10, 2024
结束时间: April 16, 2024
阶段: Done
基础部分
类与对象的关系
- 类是抽象的,概念的,代表一类事物
- 对象是具体的,实际的,代表一个具体事物(实例)
- 类是对象的模板,对象是类的一个个体,对应一个实例
对象在内存中存在形式
class Cat{
String name;
int age;
String color;
}
// new 的过程:加载类的信息
// 属性信息
// 方法信息
Cat cat = new Cat();
cat.name = "Root";
cat.age = 18;
cat.color = "white";
类和对象的内存分配机制
- 栈: 一般存放基本数据类型(局部变量)
- 堆: 存放对象(Cat cat , 数组等)
- 方法区:常量池(常量,比如字符串), 类加载信息
Java 创建对象的流程简单分析
Person p = new Person();
p.name = “jack”;
p.age = 10
- 先加载 Person 类信息(属性和方法信息, 只会加载一次)
- 在堆中分配空间, 进行默认初始化(看规则)
- 把地址赋给 p , p 就指向对象
- 进行指定初始化, 比如
p.name ="jack",p.age = 10
方法的调用机制
1、当程序执行到方法时,就会开辟一个独立的空间(栈空间)
2、当方法执行完毕,或者执行到return语句时,就会返回结果值(void无返回值)
3、回到调用方法的地方
4、继续执行方法后面的代码
5、当 main 方法(栈)执行完毕,整个程序退出
Person peo = new Person();
int res = peo.getSum(10,20);
System.out.println("getSum Method return = " + res);
public int getSum(int num1, int num2){
int res = num1 + num2;
return res;
}
成员方法传参机制
- 基本数据类型的传参机制【值拷贝】
- 引用数据类型的传参机制【地址拷贝】
方法重载【overload】
- Java中允许同一个类中,多个同名方法的存在,但要求形参列表不一致
- 注意事项和使用细节
- 方法名:必须相同
- 形参列表:必须不同(形参类型或个数或顺序,至少有一样不同,参数名无要求)
- 返回类型:无要求
可变参数
- Java 允许将同一个类中多个同名、同功能、参数个数不同的方法,封装成一个方法。通过可变参数实现。
public class Method{
public static void main(String[] args){
tool t = new tool();
System.out.println(t.sum(1,2,3));
}
}
class tool{
/**
* 访问修饰符 返回类型 方法名(数据类型... 形参名) {}
*/
public int sum(int ... nums){
int res = 0;
for(int i = 0; i < nums.length; i++){
res += nums[i];
}
return res;
}
}
- 注意事项和使用细节
- 可变参数的实参可以为0个或任意多个
- 可变参数的实参可以为数组
- 可变参数的本质就是数组
- 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
- 一个形参列表中只能出现一个可变参数
构造方法/构造器【constructor】
- 主要作用是完成对新对象的初始化
- 方法名和类名相同
- 没有返回值
- 在创建对象时,系统会自动的调用该类的构造器完成对象的初始化
对象创建的流程
class Person{
int age = 90;
String name;
Person(String n, int a){ //构造器
name = n;
age = a;
}
}
Person p = new Person("FOUR_A",18);
流程分析:
- 加载Person类信息(Person.class),只会加载一次
- 在堆中分配空间(地址)
- 完成对象初始化
- 默认初始化:
age = 0 name = null
- 显式初始化:
age = 90,name = null
- 构造器的初始化:
age = 18, name = FOUR_A
- 默认初始化:
- 对象在堆中的地址返回给p(p是对象名,也可以理解成是对象的引用)
this关键字
- Java虚拟机会给每个对象分配this,代表当前对象
public class This{
public static void main(String[] args){
Dog dog = new Dog("FOUR_A",18);
dog.info();
}
}
class Dog{
public String name;
public int age;
// 构造器
public Dog(String name, int age){
this.name = name;
this.age = age;
}
public void info(){
System.out.println("name = " + this.name + "age = " + this.age);
}
}
this 的注意事项和使用细节
- this 关键字可以用来访问本类的属性、方法、构造器
- this 用于区分当前类的属性和局部变量
- 访问成员方法的语法:this.方法名(参数列表);
- 访问构造器语法:this(参数列表); 注意只能在构造器中使用(即只能在构造器中访问另外一个构造器, 必须放在第一
条语句) - this 不能在类定义的外部使用,只能在类定义的方法中使用
中级部分
IDE快捷键
- 删除当前行, 默认是 ctrl + Y 自己配置 ctrl + d
- 复制当前行, 自己配置 ctrl + alt + 向下光标
- 补全代码alt + /
- 添加注释和取消注释 ctrl + / 【第一次是添加注释,第二次是取消注释】
- 导入该行需要的类 先配置 auto import , 然后使用 alt+enter 即可
- 快速格式化代码 ctrl + alt + L
- 快速运行程序 自己定义 alt + R
- 生成构造器等 alt + insert【提高开发效率】
- 查看一个类的层级关系 ctrl + H[学习继承后,非常有用]
- 将光标放在一个方法上,输入 ctrl + B , 可以定位到方法 [学继承后,非常有用]
- 自动的分配变量名 , 通过 在后面假 .var[老师最喜欢的]
- 模板快捷键
包
**包的本质:**创建不同的文件夹/自录来保存类文件
包的作用:
- 区分相同名字的类
- 当类很多时,可以很好的管理类
- 控制访问范围
包的命名:com.公司名.项目名.业务模块
访问修饰符
访问修饰符 | 本类 | 同包 | 子类 | 不同包 |
---|---|---|---|---|
public | ✔️ | ✔️ | ✔️ | ✔️ |
protect | ✔️ | ✔️ | ✔️ | ❌ |
default | ✔️ | ✔️ | ❌ | ❌ |
private | ✔️ | ❌ | ❌ | ❌ |
面向对象编程三大特征
封装【encapsulation】
-
把抽象出的数据【属性】和对数据的操作【方法】封装在一 起,数据被保护在内部,程序的其它部分只有通过被授权的操作【方法】,才能对数据进行操作。
-
封装的实现步骤
-
将属性进行私有化
private
【不能直接修改属性】 -
提供一个公共的set方法,用于对属性判断并赋值
// Xxx表示某个属性 public void setXxx(类型参数名){ //加入数据验证的业务逻辑 属性=参数名: }
-
提供一个公共的(public)get方法,用于获取属性的值
public dataType getXxx(){ //权限判断,再返回Xxx某个属性 return XX; }
-
继承
-
当两个类的属性和方法有很多是相同的,可以用继承提高代码的复用性
-
继承的基本语法
class childClass extends parentClass{}
-
子类就会自动拥有父类定义的属性和方法
-
父类又叫超类,基类.
-
子类又叫派生类。
-
继承的细节问题
- 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
- 子类必须调用父类的构造器, 完成父类的初始化
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译
- 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
- super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
- super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
- java 所有类都是 Object 类的子类, Object 是所有类的基类
- 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
- 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制
-
继承的内存布局
public class ExtendsTheory{ public static void main(String[] args){ Son son = new Son(); } } class GrandPa{ String name = "grandpa"; String hobby = "buybuybuy"; } class Father extends GrandPa{ String name = "father"; int age = 38; } class Son extends Father{ String name = "son"; }
super 关键字
-
super 代表父类的引用,用于访问父类的属性、方法、构造器
-
super 和 this 的比较
区别点 | this | super |
---|---|---|
访问属性 | 访问本类中的属性,如果本类没有此属性则从父类中继续查找 | 从父类开始查找属性 |
调用方法 | 访问本类中的方法,如果本类没有此方法则从父类继续查找 | 从父类开始查找方法 |
调用构造器 | 调用本类构造器,必须放在构造器的首行 | 调用父类构造器,必须放在构造器的首行 |
特殊 | 表示当前对象 | 子类中访问父类对象 |
方法重写
- 方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法
- 注意事项和使用细节
- 子类的方法的形参列表,方法名称,要和父类方法的形参列表,方法名称完全一样。
- 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
- 子类方法不能缩小父类方法的访问权限
- 对方法的重写和重载做一个比较
名称 | 发生范围 | 方法名 | 形参列表 | 返回类型 | 修饰符 |
---|---|---|---|---|---|
重载【overload】 | 本类 | 必须一样 | 类型、个数、顺序 至少 有一个不同 | 无要求 | 无要求 |
重写【override】 | 父子类 | 必须一样 | 必须一样 | 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类 | 子类方法不能缩小父类方法的访问权限 |
多态
-
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的
-
对象的多态
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型是可以变化的
- 编译类型看定义时=号的左边,运行类型看=号的右边
//animal : 编译类型, Dog : 运行类型 Animal animal = new Dog(); //animal 的运行类型变成了 Cat animal = new Cat();
-
多态注意事项和细节
- 多态的前提是:两个对象(类)存在继承关系
- 多态的向上转型
Animal animal = new Cat(); // Cat->Animal
- 可以调用父类【Animal】中的所有成员(需遵守访问权限)
- 不能调用子类【Cat】中特有成员
- 最终运行效果看子类的具体实现
- 多态向下转型
Cat cat =(Cat)animal; // Animal->Cat
- 只能强转父类【animal】的引用,不能强转父类的对象【Cat()】
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,可以调用子类类型中所有的成员
Java 的动态绑定机制
- 当调用对象方法的时候,该方法会和该对象【运行类型】的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,那里使用
Object 类
==
和equals
的对比==
: 一个比较运算符- 既可以判断基本类型,又可以判断引用类型
- 如果判断基本类型,判断的是值是否相等
- 如果判断引用类型,判断的是地址是否相等
equals
: Object类中的方法,只能判断引用类型- 默认判断的是地址是否相等
- 子类中会重写该方法,用于判断内容是否相等