类与对象
类是抽象的,概念的,代表一类事物,比如人类,猫类,……是一种数据类型
对象是具体的,实际的,代表一个具体事物,是实例
类是对象的模板,对象是类的一个个体,对应一个实例
对象存在形式
属性 / 成员变量
成员变量 = 属性 = field(字段)
属性是类的一个组成部分,一般是基本数据类型,也可以是引用类型(对象,数组)
方法 / 成员方法
除了属性外,还有一些行为,就是方法
方法的定义
访问修饰符 返回数据类型 方法名(形参列表 …){ // 方法体
语句;
return 返回值;
}
形参列表:表示成员方法输入
返回数据类型:**表示成员方法输出,**void 表示没有返回值
方法名:表示为了实现某一功能代码块
return 语句不是必须的
方法的使用
方法写好后,如果不去调用,不会输出
先创建对象,然后调用方法即可
Person p1 = new Person();(创建对象)
p1.speak();(调用speak方法(无返回值)))
p1.cal01(5);(调用cal01方法(传入参数5))
方法的好处
提高代码的复用性
可以将实现的细节封装起来,然后供其他用户来调用即可
方法调用机制
底层机制
当程序执行到方法时,就会开辟一个独立的空间(栈空间)
当方法执行完毕,或者执行到 return 语句时,就会返回
返回到调用方法的地方
返回后,继续执行方法后面的代码
当 main 方法(栈)执行完毕,整个程序退出
传参机制
基本数据类型,传递的是值(值拷贝),形参的任何改变不影响实参
引用类型传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参
注意事项和使用细节
访问修饰符不写则默认访问
返回数据类型
一个方法最多有一个返回值(返回多个值 →返回数组)
返回类型可以为任意类型,包含基本类型或引用类型
如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值;且返回值类型必须和 return 值类型一致或兼容
如果方法是 void,则方法体中可以没有 return 语句,或者只写 return
方法名
遵循驼峰命名法,最好见名知义,表达出该功能的意思即可
形参列表
一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开
参数类型可以为任意类型,包含基本类型或引用类型
调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数
方法定义时的参数称为形式参数,简称形参;方法调用时传入的参数称为实际参数,简称实参;实参和形参的类型要一致或兼容,个数,顺序必须一致
方法体
里面写完成功能具体的语句,可以为输入,输出,变量,运算,分支,循环,方法调用
方法不能嵌套定义
方法调用细节
同一个类中的方法调用:直接调用即可
跨类中的方法A类调用B类方法:需要通过对象名调用(对象名.方法名(参数))
跨类方法调用和方法的访问修饰符有关
创建对象
先声明再创建
Cat cat;(声明对象 cat)
cat = new Cat();(创建)
直接创建
Cat cat = new Cat();
访问属性
对象名**.属性名(cat.**name;)
注意事项和细节说明
属性的定义语法同变量(访问修饰符 属性类型 属性名;)
访问修饰符:控制属性的访问范围:public,proctected,默认,private
属性的定义类型可以为任意类型,包含基本类型或引用类型
属性如果不赋值,有默认值,规则和数组一致
方法重载
Java 中允许同一个类中,多个同名方法的存在,但要求形参列表不一致
重载的好处
减轻了起名的麻烦
减轻了记名的麻烦
注意事项和使用细节
方法名:必须相同
形参列表:必须不同(形参类型,个数,顺序,至少有一样不同,参数名无要求)
返回类型:无要求
类和对象的内存分配机制
内存结构分析
栈:一般存在基本数据类型(局部变量)
堆:存在对象(Cat,cat,数组等)
方法区:常量池(常量,比如字符串),类加载信息
创建对象的流程简单分析
先加载 Person 类信息(属性和方法信息,只会加载一次)
在堆中分配空间,进行默认初始化
把地址赋给p,p 就指向对象
进行指定初始化,比如 p.name= “ Jack ”
在栈里面修改只会修改它的指向(指向某个地址),在堆里面修改才会把 “内容” 修改
继承
定义:当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可
继承的好处
提高代码复用性
提高代码的扩展性和维护性
继承的基本语法
class 子类 extends 父类{
}
子类就会自动拥有父类定义的属性和方法
父类又叫超类,基类
子类又叫派生类
注意事项和细节
子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
子类必须调用父类的构造器,完成父类的初始化
当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中使用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不会通过
如果希望指定去调用父类的某个构造器,则需要显示调用
super 在使用时,需要放在 构造器第一行
super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
父类构造器的调用不限于直接父类,将一直往上追溯到 Object 类
子类最多只能继承一个父类(单继承),
不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
继承的本质分析
当子类对象创建好后,建立查找的关系
首先看子类是否有该属性
如果子类有该属性,并且可以访问,则返回信息
如果子类没有这个属性,就看父类有没有这个属性(如果父类有这个属性,并且可以访问,就返回信息)
如果父类没有就按照(3)的规则,继续找上级父类,直到Object
继承设计的基本思想
父类的构造器完成父类属性初始化
子类的构造器完成子类属性初始化