本文为Java面向对象 的基础提要,源于《疯狂Java讲义 th5》
所用JDK版本为:java 11.0.2
作者:房梁上的猫
邮箱:gyqc@outlook.coom
面向对象(上)
类 与对象
- 对象是类的实例化,类是对象的抽象。
类的结构
[修饰符] class 类名
{
成员变量,,,;
内部类,,,,,,;
初始化代码块,,,;
构造器,,,,, ;
方法,,,,,;
}
-
外部类的修饰符有:
访问控制符( public 、包访问控制符)、abstract、final。
-
类成员(static)不能访问非类成员。
-
类至少有一个构造器,如果不写出系统提供默认构造器。
-
成员变量
[修饰符] 类型 成员变量名 [= 默认值];
-
成员变量的修饰符:
访问控制符(public 、包访问控制符、protected、private)、static、final。
-
-
方法
[修饰符] 返回值类型 方法名 (形参类型 形参名) { 方法体; }
-
方法的修饰符:
访问控制符(public 、包访问控制符、protected、private)、static、final、abstract。
-
-
构造器
[修饰符] 构造器名(形参列表) { 构造器执行体 }
-
修饰符:
访问控制符(public、包访问控制符、protected、private)
-
对象的产生与定义
//定义一个引用类型 Person 类变量
Person p;
//创建该类的实例
p=new Person();
this引用
-
在构造器中引用,引用该构造器正在初始化的对象——必须放在构造器执行体的首句。
-
在方法中引用调用该方法的对象,访问该类的方法或实例变量。
-
static修饰的方法不能使用 this关键字
方法详解
方法与类之间的关系
- 方法只能在类里定义
- 执行方法必须使用类或对象作为调用者
方法的参数
- 传递机制:值传递
形参个数可变的方法
[修饰符] 返回值类型 方法名( type 参数1,type... 参数)
{
方法执行体
}
- 本质为一个数组参数
- 可变形参 与 使用数组 的区别
- 个数可变形参只能位于形参列表最后,最多只能包含一个个数可变形参。
递归方法
- 含义
- 必须有一个返回值是确定的
方法重载
- 特点:
- 方法名相同
- 形参列表不同
- 调用时依据传递的形参列表匹配
成员变量 和 局部变量
-
变量的分类
-
不同类别的变量的作用范围 (产生 和 销毁 时间)
-
初始化——局部变量处了形参外都必须显式初始化 ;其他类型变量都是隐式初始化。
-
作用范围不同的变量 同名 产生的效果 以及 相关调用。
-
变量在内存中的运行机制
-
变量的使用规则——依据需求选择合适的变量作用范围。
隐藏 和 封装
封装的含义 及 作用
- 含义:将对象的状态信息隐藏在对象的内部,不允许外部程序访问内部信息,而是通过该类提供的方法来实现对内部信息的操作和访问。
- 封装的目的
- 封装的实现
访问控制符
- 四个访问控制符的访问权限
- 如果源文件里包含一个public类,则该文件名必须与该类名相同,且一个源文件最多只能包含一个public类。
- 访问控制符使用的基本规则:
- 类里绝大部分成员采用private 修饰
- protected的使用(继承)
- public 使用
package、import、import static
-
包 的作用:
- 提供类的多层命名空间,用于解决类的命名冲突、类文件管理等问题。
-
位于包中每个类的完整命名都应该是包名和类名的组合。
-
位于包中的类,在文件系统中也必须有与包名层次相同的结构目录。
-
Java包机制需要做的两个保证:
- 源文件里使用package指定包名。
- class文件必须放在对应路径下。
-
package语句必须作为源文件的第一条非注释性语句,一个源文件只能指定一个包。
-
import 关键字,可以向某个Java文件中导入指定包层次下的某个 或全部类。
-
import 语句应该出现在package语句后、类定义之前。
-
import static 用于导入指定类的某个或全部静态成员变量、方法。
-
Java常用包——————
深入构造器
- 构造器的作用: 用于创建实例时执行初始化。
- 构造器重载:
- 形参列表不同
- this的使用。
类和继承
继承的特点
- 单继承
- extends 关键字
- 父类与子类的关系: 子类是对父类的扩展
- 子类只能获得 成员变量、方法、内部类
重写父类的方法
-
方法重写(方法覆盖):子类包含与父类同名的方法。规则:
-
方法名相同、形参列表相同。
-
子类方法返回值类型比父类方法返回值类型更小或相等;
子类方法声明抛出的异常类应比父类的更小或相等。
-
子类的方法访问权限应比父类方法的访问权限更大或相等。
-
覆盖方法和被覆盖的方法 要么都是类方法、要么都是实例方法。
-
-
子类覆盖了父类的方法后,子类对象将无法访问父类中被覆盖的方法,但可以在子类方法中调用父类中被覆盖的方法(使用super或父类类名类调用)。
super的限定
-
super用于限定对象调用它从父类继承得到的实例成员变量或方法。(不能出现在使用static修饰的方法中)
-
super在构造器中,,,。
-
子类定义了和父类同名的实例成员变量,则会发生隐藏父类实例变量的情形。(调用 同方法)
-
当程序创建一个子类对象时,系统会同时为它从父类继承得到的所有实例变量分配内存。
调用父类构造器
-
子类构造器里可以调用父类构造器里的初始化代码。(super)
-
super调用父类构造器代码 则必须出现在子类构造器执行体的第一行。(与this 不可能同时出现)
-
系统在调用子类构造器之前都会显示或隐式地调用父类构造器。
-
创建任何对象总是从该类继承树的最顶层构造器开始执行。
多态
-
引用变量的两种类型:编译时类型、运行时类型。
-
向上转型
-
当运行时调用该引用变量方法时,其方法总是表现子类方法的行为特征。
导致 相同类型变量调用同一方法时呈现不同的行为特征,这就是多态。
-
对象的实例成员变量不具有多态性。
-
引用变量编译阶段只能调用编译时类型所具有的方法,但运行时执行它运行类型所具有的方法。
-
通过引用变量来访问实例成员变量时,系统总是访问它编译时类型所定义的成员变量。
引用变量的强制类型转换
- 如果需要引用变量调用运行时的方法 则必须进行强制类型转换。
- 引用类型间的转换只能发生在具有继承关系的两个类型间进行。 (使用
instanceof
运算符来判断) - 如果把一个父类实例转换成子类类型,则这个对象必须实际上是子类实例才行。
// inctanceof 详解
引用类型变量 instanceof 类或接口 ; //用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。
//返回 Boolean 类型值。
继承与组合
继承
- 继承 会破坏封装,而组合不会
- 为了避免子类破环父类封装,父类设计原则:
- 尽量隐藏父类内部数据。
- 不要让子类随意访问修改父类的方法。
- 工具方法(private)
- 被外部自由调用的方法(public final)
- 留给子类重写的方法(protected)
- 尽量不要在父类构造器中调用将要被子类重写的方法。
组合
- 组合:把旧类对象作为新的成员变量组合进来。(通常private 修饰旧类对象)
- 继承关系中从子类抽象出共有父类的过程,类似于组合关系中从多个整体类里提取被组合类的过程。
初始化块
//初始化块的语法
[修饰符] {
//修饰符 只能时 static ,分实例初始化块 和 类初始化块
//初始化可执行性代码
...
}
初始化块的使用
-
一个类里可以有多个初始化块,初始化块的执行顺序,,,.
-
实例初始化块只在创建Java对象时隐式执行,而且在构造器之前执行; 类初始化块则在类初始化阶段自动执行。
-
查Java创建一个对象时,系统先为该对象的所有实例变量分配内存(前提是该类已经被加我过了),接着程序开始对这些实例变量执行初始化,其初始化顺序是:先执行实例初始化共或声明实例变量时指定的初始值(这两个地方指定初始值的执行顺序与它们在源代码中的排列顺序相同),再执行构造器里指定的初始值。
实例初始化 和构造器
-
可以把构造器中相同的固定代码提取到实例初始化块中 以实现代码复用。
-
实际上实例初始化块是一个假象,使用
javac
命令编译Java类后,该Java类中的实例初始化块会消失——实例初始化块中代码会被“还原”到每个构造器中,且位于构造器所有代码的前面。 -
同构造器一样 系统会追溯父类 实例初始化块。
类初始化块
- 类初始化块是类相关的,用于类初始化处理,通常用于类变量初始化处理。
- 同样遵循类成员不能访问实例成员的规则。
- 同实例初始化块一样 系统会追溯父类 类初始化块。
- 当JVM第一次主动使用某个类时,系统会在类准备阶段为该类的所有类变量分配内存;在初始化阶段则负责初始化这些类变量,初始化类变量就是执行类初始化块代码和声明类成员变量时指定的初始值,它们的执行顺序与源代码中的排列顺序相同。