类与对象
- 访问修饰符:public,protected,默认,private
- 属性properties如果不赋值,有默认值,同数组默认值
如何创建对象
-
先声明再创建
Cat cat; cat = new Cat();
-
直接创建
Cat cat = new Cat();
内存分配机制!
堆、栈、方法区
递归
重要规则
- 执行一个方法是,会创建一个新的独立栈空间
- 方法的局部变量相互独立,不互相影响
- 方法使用引用变量类型时,会共享该引用类型数据
重载
- 必须同名
- 形参列表必须不一致(类型、个数、顺序至少有一个不同)
- 返回类型无要求
可变参数
将同一类中多个同名同功能但参数个数不同的方法封装为一个方法
- 访问修饰符 返回类型 方法名(数据类型… 形参名)
- 实参可以是0或者多个
- 实参可以是数组
- 可变参数本质是数组
- 可以和普通类型参数一起放在形参列表,但是只能放在最后
- 一个形参列表中只能出现一个可变参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5PAK5K65-1679030654950)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20221107103843851.png)]
作用域
-
全局变量:属性,作用域为整个类体
-
局部变量除属性之外的其他变量,作用域为定义它的代码块
-
属性和局部变量可以重名,使用时遵循就近原则
-
同一个作用域中,局部变量不能重名
-
属性伴随对象的创建和销毁,局部变量伴随定义它的代码块的创建和销毁
-
作用域范围不同
- 局部变量:本类中对应的方法使用
- 属性:本类或其他类使用
-
修饰符不同
- 属性可以加修饰符
- 局部变量不能加修饰符
构造器constructor
-
完成对新对象的初始化,不是创建对象,创建是new干的事情
-
语法
-
[修饰符] 方法名(形参列表){
方法体}
-
-
修饰符可以默认,也可以 public protected private
-
没有返回值
-
方法名必须和类名相同
-
参数列表和成员方法一样的规则
-
构造器的调用由系统完成
-
在创建对象时,系统自动调用该类的构造器完成对对象的初始化
-
一个类可以定义多个不同的构造器,即构造器重载
-
如果程序员没有定义构造方法,系统自动生成一个默认无参的构造方法
-
一旦定义了自己的构造器,默认的构造器会被覆盖,不能再使用默认无参构造器,除非自己显式定义一下
创建对象流程分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fjOcPRY9-1679030654951)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20221107111305086.png)]
-
方法区加载Person类信息,只会加载一次
-
堆中分配空间(地址)存放对象
-
对象初始化:先进行默认初始化,属性的默认初始值,int为0,string为null;再显式初始化,age = 90;最后构造器初始化,实参传给n,把null换成小倩,小倩在常量池,把20赋值给age
-
把对象在堆区地址返回给栈区的p,p的本质是对象的引用(对象名),存储的是堆区的地址,对象应该是栈区开辟的空间
-
person p2 = p1,意思是把堆区的地址赋值给p2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cSuvjoF4-1679030654952)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20221107111202183.png)]
JAVA _this
-
java虚拟机会给每个对象分配this,代表当前对象。
-
this.name是当前对象属性name,哪个对象调用就代表哪个对象
-
this是一个引用,是堆区的一种属性,指向自己
-
细节
- this可以用来访问本类的属性、方法、构造器
- this用于区分局部变量与属性
- 访问构造器语法:this(参数列表); 注意只能在构造器中使用,在一个构造器中访问另一个构造器,且必须放在第一句
- this不能再类定义的外部使用,只能再类定义的方法中使用
访问修饰符modifier
-
public:对外公开
-
protected:子类和同一个包的类公开
-
默认:向同一个包的类公开
-
private:只有类本身可以访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gZBJHVPH-1679030654952)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20221107161116137.png)]
- 只有默认和public才能修饰类
封装encapsulation
实现步骤
- 属性私有化
- 提供公共的set方法,对属性判断并赋值
- 提供公共的get方法,用于获取属性的值
- 可以把set放在构造器中,限制设置的值
继承extends
解决代码复用
细节
- 子类继承了所有的属性,但私有属性不能在子类直接访问,要通过公共方法去访问
- 子类必须调用父类的构造器完成父类的初始化
- 创建子类对象时,不管使用子类哪个构造器,默认情况下总会去调用父类的无参构造器,若父类没有提供无参构造器,则必须在子类构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作
- 希望 去调用父类的某个构造器,则显式的调用一下
- super使用时需要放在构造器第一行
- super(),this()都只能放在构造器第一行,因此两个方法不能共存在同一个构造器。
- object是所有类的基类
- 单继承机制,子类最多只能继承一个父类(直接继承)
- 不能滥用继承
- 内存:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOpoPKm2-1679030654952)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20221107174951414.png)]
-
加载类信息:object、grandpa、father、son
-
堆中分配内存空间:
- name:爷爷(存储在常量池)、hobby:旅游(存储在常量池)
- name:爸爸(存储在常量池)、年龄:39
- name:儿子(存储在常量池)
-
堆区中的空间地址分配给main栈中的son
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-64n5QwiA-1679030654952)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20221107174026414.png)]
当用son访问时,输出的应该是哪个名字?按照查找关系来返回信息
- 首先看子类是否有该属性:如果有且可以访问,则返回信息
- 如果子类没有该属性,则向上返回看父类是否有该属性且可以访问,则返回该信息
- 按照2规则继续向上查找,直到object,如果没有然后报错
super
代表父类的引用,用于访问父类的属性、方法、构造器
- 可以访问父类的属性,不能访问父类的私有属性
- 可以访问父类的方法,但不能访问父类的私有方法
- 访问父类的构造器,只能放在构造器的第一句!
好处
- 分工明确,父类属性由父类初始化,子类属性由子类初始化
- 子类有父类成员重名时,为了访问父类的成员,必须通过super,如果没有重名,使用super、this、直接访问是一样的,如下:
- 子类调用父类的方法时(属性同理)
- cal(); 找cal方法顺序是先找本类,有则调用,没有则找父类,有则调用,无则继续寻找父类的父类;若找到了但是不能访问,则报错cannot access,若一直没有找到则提示方法不存在
- this.cal(); 逻辑同cal();
- super.cal(); 没有查找本类的过程,直接查找父类
- super不限于直接父类,如果多个上级类都有同名成员则遵循就近访问原则
- this和super的区别:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WvE2zKxD-1679030654953)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20221109162523951.png)]
重写 override
子类有一个方法和父类的一个方法的名称、返回类型、参数相同,即子类的这个方法覆盖了父类a的方法。
注意事项:
- 子类的方法名称、参数必须与父类相同
- 子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类
- 子类方法不难缩小父类方法的访问限权
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6re8fg1r-1679030654953)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20221109213526865.png)]
多态
方法或对象有多种形态,重写和重载体现了多态。
对象的多态
编译类型和运行类型
- 一个对象的编译类型和运行类型可以不一致
Animal animal = new Dog(); //编译类型Animal,运行类型Dog
animal = new Cat(); //运行类型变成Cat,编译类型仍是Animal
- 编译类型在定义对象时就确定了不能改变
- 运行类型是可以变化的
- 编译类型看 ’=‘左边,运行类型看’=‘右边
- 编译类型决定能调用哪个类的方法,如果调用子类的特有方法过不去编译,只能调用重写的方法(向上转型)
- 向下转型强制转换以后,编译类型改变为子类了,就可以调用子类的特有方法了
细节
-
前提:两个对象具有继承关系
-
向上转型:父类的引用指向了子类的对象 Animal animal = new Dog();
-
语法:父类对象 对象名 = new 子类对象()
-
编译阶段能调用哪些成员是由编译类型决定:可以调用父类的成员(遵守访问权限),不能调用子类特有成员(因为不能通过编译),可以调用重写的方法(通过编译以后,按照运行类型调用)
-
向下转型:子类类型 引用名 = (子类类型) 父类引用;
- Cat cat = (Cat) animal;
- 此时cat的编译类型为Cat
-
只能强转父类的引用,不能强转父类的对象
-
父类引用必须指向的是当前目标类型的对象:animal原先的对象是猫,所以只能强转为猫
-
可以调用子类类型中的所有成员
-
属性没有转型之说,属性的值看编译类型
-
instanceOf:用于判断对象的运行类型是否为某某类型
动态绑定机制 Dynamic Binding
-
调用对象方法时,该方法会和对象的运行类型/内存内存绑定
-
调用对象属性时,没有动态绑定机制,哪里声明,哪里使用(找当前方法所在类的属性)
多态的应用
多态数组
参数多态
object类详解
equals方法
==:是一个比较运算符,不是一个方法,既可以判断基本类型(),也能判断引用类型(地址是否相等,即是否是同一个对象)。
equals:object类的一个方法,只能判断引用类型。默认判断地址是否相等。
hashcode
返回该对象的哈希码值。为了哈希表的性能。
- 提高具有哈希结构容器的效率。
- 两个引用,如果指向同一个对象,那么哈希值是一样的,
- 两个引用如果指向不同对象,则哈希值是不一样的。
- 哈希值主要根据地址计算,但不能等价于地址。
toString
返回该对象的字符串表示。默认返回:全类名(包名+类名)+ @ + 哈希的十六进制
finalize
垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类可以重写来做一些释放资源的操作。
系统自己决定调用时机,也可以用system.gc()主动触发垃圾回收机制。