导图社区 面向对象未完成
这是一篇关于面向对象未完成的思维导图,包括:Java类及类的成员、面对对象的三大特征、其他关键字三部分内容。
编辑于2022-10-22 11:36:40 陕西面向对象思维导图
Java类及类的成员
类的成员
属性
直接定义在类的一对{}内
也叫成员变量、field、域、字段
“对象.属性”
加载到堆空间中(非static)
可以被四种权限修饰符所修饰
根据其类型都有不同的默认初始化值
整形(byte、shor、int、long):0
浮点型:(float、double):0.0
字符型:(char):0或('\u0000')
布尔型:(boolean):false
引用数据类型(类、接口、数组):null
方法
也叫成员方法、 函数、method
“对象.方法”
方法的声明: 权限修饰符 返回值类型 方法名 (形参列表){ 方法体 }
方法的调用
在同一个类中
在main方法中 要进行类的实例化 然后在通过对象.方法 或 对象.属性 的方式来调用当前类中的属性或方法(因为main是静态方法 因为生命周期的原因 静态方法只能调用静态方法和静态变量)
在非main方法中 可以直接调用当前类中的属性或方法
在不同类中
不管是不是main方法 都要进行类的实例化 然后在通过对象.方法 或 对象.属性 的方式来调用其他类中的属性或方法
递归方法:方法A中又调用了方法A
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
方法中,不可以定义方法。
可以被四种权限修饰符所修饰
返回值类型: 有返回值 vs 没有返回值
return
作用:① 结束方法 ② 针对与有返回值类型的方法,使用“return 数据”方法返回
return关键字后面不可以声明执行语句。会编译不通过。
如果方法有返回值方法中,必须返回指定类型的变量或常量:“return 数据”
如果方法没有返回值,则方法声明时,使用void来表示。 不使用return。如果使用的话,如果使用的话, 只能使用“return;”表示结束此方法的意思。
可以被static、final、abstract 来修饰
重载
定义:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可
判断是否是重载: 跟方法的修饰符、返回值类型、形参变量名、方法体 都没有关系!!
可变个数形参的方法
格式:数据类型 ... 变量名
与本类中方法名相同形参类型也相同的数组不构成重载 可以构成方法的重写
可变个数形参在方法的声明中 必须声明在末尾
方法的形参的传递机制:值传递
如果参数是基本数据类型,此时实参赋值给形参的是 实参真实储存的数据值。 如果参数是引用数据类型,此时实参赋值给形参的是 实参真实储存的地址值。
方法的重写(override / overweitr)
1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(static的方法是不能被重写的)。
约定俗成: 子类中的叫重写的方法; 父类中的叫被重写的方法 ① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同 ② 子类重写的方法的权限修饰符不小于父类被重写的权限修饰符 >特殊情况: 子类不能重写父类中声明为private的权限方法
③ 返回值类型: * >父类被重写的方法的返回值类型是void,则子类中重写的方法的返回值类型也是void * >父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型是A类或A类的子类 * (如果返回值类型是Object型 则子类重写的方法的返回值类型可以是Object 也可以是String(Object的子类)) * >父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是:double) * ④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
2.应用: 重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法
3. 重写的规定: 方法的声明: 权限修饰符 返回值类型 方法名 (形参列表) throws(异常的类型) { 方法体(一定是不同的 不然没必要重写) }
构造器
构造器的作用: * 1.创建对象(可以在任何方法体中进行) * 2.初始化对象的信息
如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性(非static的)
通过“对象.属性”或“对象.方法”调用对象的结构
对象是一个引用型变量
引用类型的变量,只可能存储两类值:null 或 地址值(含变量类型,且不是同类型 不能赋值)
匿名对象的使用
mall.show(new Phone());//将此匿名对象的地址传给了PhoneMall中的形参public void show(Phone phone) {
如果说没有显示的定义类的构造器 系统会默认提供一个空参的构造器 构造器的权限修饰符与它所在的类相同 一旦我们显示的定义了类的构造器之后, 系统就不再提供默认的空参构造器
构造器可以被四种权限修饰符所修饰
格式: 权限修饰符 类名(形参列表){ (构造器内部可以调用属性、方法....) }
一个类中定义的多个构造器,形参列表不同,彼此构成重载
代码块
内部类
类
面对对象的三大特征
封装性
体现:我们将类的属性私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
getXxx()的格式:有返回值类型 无形参 * public 返回值类型 getXxx( ){ * return xxx; * }
setXxx()的格式:无返回值类型 有形参 * public void setXxx(xxx类型 xxx ){ * * }
封装性的体现,需要四种权限修饰符来配合 4种权限(从小到大排列): private、缺省、protected、public
* private 只能在类内部使用 * 缺省 可以在同一个包中使用 * protected 可以在不同包的子类使用 * public 可以在同一个工程中 随便使用
4种权限可以用来修饰 类 及类的内部结构:属性、方法、构造器、内部类 共5种。 (类、属性、方法、构造器、内部类)
对于class的权限修饰只可以用public 和 缺省(default)。
总结封装性: Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小
继承性
关键字 extends: 延展、扩展
继承性的好处
①减少了代码的冗余,提高了代码的复用性 ②便于功能的扩展(本来要在每个类中添加 但现在只需要在父类中添加就行) ③为之后的多态性的使用,提供了前提
继承性的格式:class A extends B{}
A: 子类、派生类、subclass B: 父类、超类、基类、superclass
继承性的体现
一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的结构 属性和方法 * 特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。 * 只是因为封装性的影响,使得子类不能直接调用父类的结构而已。
子类不能重写父类中private的方法
子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。 * 子类和父类的关系,不同于子集和集合的关系。(因为子类可以在父类的基础上进行延展、扩展 所以功能更加强大一点)
继承性的规定
1.一个类可以被多个子类继承。 2.Java中类的单继承性 : 一个类只能有一个直接父类 可以有多个间接父类 3.子父类是一个相对的概念。(多层继承的关系) 4.子类直接继承的父类,称为:直接父类; 间接继承的父类称为:间接父类 5.子类继承父类以后,就获取了直接父类以及间接父类中声明的属性和方法
如果我们没有显式的声明一个类的父类的话,则此类继承于java.lang.Object类
继承于一个类 就要在子类的每个构造器中调用父类的构造器
可以默认调用
(子类构造器中首行未声明this(形参列表)和super(形参列表) 首行会有一个未显示的 super() 来调用父类中的空参构造器) ①(默认调用父类中的空参构造器,-- 若父类中声明了有参构造器没有声明空参构造器 此时会报错)
报错的解决方法:(此时可以去父类中声明一个空参构造器 也可在子类构造器中使用
也可以显式调用
在子类构造器中使用“super(形参列表)”的方式 显式调用父类的有参构造器)
继承于一个抽象类
继承于一个抽象类 必须要实现它所有的抽象方法 不然此类还得是一个抽象类 需要abstract修饰
多态性·1
多态性:可以理解为一个事物的多种形态
何为多态性:( 父类的类型 对象名 = new 一个子类的类型) * 对象的多态性:父类的引用指向子类的对象(对象是多态的 只要是父类的子类 都可以写在这个位置) * 子类的对象赋给父类的引用
多态的使用:虚拟方法调用有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。 * (多态也可调用父类中特有的方法 但不能调用子类中特有的方法 因为编译时是看左边的)
一般都是: 父类的类型 对象名 = new 一个子类的类型 * 对象的多态性只适用于方法 不适用于属性 * * 总结: 编译,看左边 ; 运行,看右边 (看的是类的实例化那条语句)
对于实例变量(属性)则不存在这样的现象,即使子类里定义了与父类完全相同的 实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量。 编译运行都看左边 --- 多态并不体现在属性上
子父类中不要定义同名的属性 因为多态并不体现在属性上
多态性的使用前提: ① 类的继承关系 ② 方法的重写
向下转型:多态可以称之为向上转型 多态所对应的则是向下转型
为什么要使用向下转型: > 有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于对象类型 声明为父类类型, > 导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。
如何才能调用子类特有的属性和方法? 向下转型:使用强制类型转换符: ( ) Man m1 = (Man)p2; //***强转符中的类一定要是强转符后的引用指向的对象的类或他的父类才行 m1.earnMoney();//这时的引用就可以调用子类中特有的方法了
使用时的注意点: 使用强转时,可能出现ClassCastException的异常。 Woman w1 = (Woman)p2; w1.name = "hh"; w1.goShopping(); 为了避免出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
instanceof 放入关键字中说
其他关键字
this(当前对象 或 当前正在创建的对象)
this可以用来修饰属性、方法、构造器
类的方法中
我们可以使用"this.属性" 或 "this.方法"的方式,调用当前对象的属性或方法
通常情况下,我们都选择省略"this." 特殊情况下,如果方法的形参和类的属性同名时 我们必须显式的使用"this.变量"的方式,表明此变量时属性,而非形参。
在类的构造器中
我们可以使用"this.属性" 或 "this.方法"的方式,调用当前正在创建的对象的属性或方法。
通常情况下,我们都选择省略"this." 特殊情况下,如果构造器的形参和类的属性同名时我们必须显式的使用"this.变量"的方式,表明此变量时属性,而非形参。
子主题
this可以用来调用属性、方法、构造器
this调用构造器
"this(形参列表)"的使用必须放在构造器体内的首行
我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器(不能调用自己 死循环)(也不能调用成一个闭环 a - b - c - a 也是死循环)
且使用"this(形参列表)"方式,调用本类中指定的其他构造器 "this(形参列表)"中的形参的类型 必须得是自身构造器的形参有的类型才可以 "super(形参列表)"也是
多个不同的构造器内部 可以使用"this(形参列表)"方式 调用同一个构造器 (可以多调一 不能一调多)
package:包
使用package声明类或接口所属的包,声明在源文件的首行
同一个包下不能命名同名的接口、类。 不同的包下,可以命名同名的接口、类。
import:导入
声明在包的声明和类的声明之间
可以使用“ xxx.* ” 的方式,表示可以导入xxx包下的所有结构
如果使用的类或接口是本包下的(不包含本包下的子包),则可以省略import结构 (子包就是在此包名下在.一层目录 就是此包的子包)
如果在源文件中,使用了不同包下的同名类,则必须至少有一个类需要用全类名的方式显示
.super:父类的
super可以用来调用:属性、方法、构造器
super的使用
我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
特殊情况: 当子类和父类中定义了同名的属性时,我们想要在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,表明调用的是父类中声明的属性。
特殊情况: 当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
super调用构造器
"super(形参列表)"的使用,必须声明在子类构造器的首行!
我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定构造器
我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现 但是必须有一个 不是"this(形参列表)"就是"super(形参列表)"(因为他们两个都得声明在首行 冲突了)
在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器:super()
如果子类构造器中既未显式调用父类或本类的构造器,且父类中声明了有参构造器又没有声明无参的构造器,则编译出错
相当于在子类的一个构造器中 既没有"this(形参列表)"或"super(形参列表)" 则构造器内部为: * public A() { //在一个类中调用父类的构造器 则代表这个类获得了父类中的所有结构 * super(); //就算不写 或是写了删掉 它还是存在的 * }
instanceof
a instanceof A 判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
对象a是以A类的父类声明的 实际new的是A类的对象 使用instanceof的时候要想到这一点
使用情景: 为了避免出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。 如果返回false,不进行向下转型。
如果a instanceof A 返回true, a instanceof B 也返回true。 其中B是A的父类因为a是子类A的实例则肯定也是父类B的实例 子类中有父类中的所有结构(属性、方法)
instanceof的总结
如果一个对象名a instanceof A 返回true , 那么对象名a instanceof (A的直接、间接父类)都返回true。 因为子类中肯定包括直接、间接父类的所有结构 如果a是A类的实例 那么在堆空间中肯定加载过A的所有父类的结构
static:静态的
static可以用来修饰:属性、方法、代码块、内部类 (不能修饰构造器)
修饰属性: 静态属性(类变量) vs 非静态属性(实例变量)
实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象的非静态属性使,不会导致其他对象中同样的属性值的修改
静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
① 静态变量随着类的加载而加载。 可以通过“类.静态变量”来进行调用 在通过“类.静态变量”来进行调用时 在此之前类就会被加载 (可以在类的实例化之前进行调用) 在通过“类.静态变量”来进行调用时 要对其赋值 或 用一个新的变量来接收 不然会报错( 和非静态变量(属性)一样 ) ② 静态变量的加载要早于对象的创建。 ③ 由于类只加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
静态属性举例:System.out;Math.PI
能否通过类、对象来调用类变量、实例变量(通过“类.静态变量”……的方式)
类变量 实例变量 类 yes no 对象 yes yes
.使用static来修饰方法:静态方法
随着类的加载而加载,可以通过“类.静态方法”来进行调用(可以在类的实例化之前进行调用)
能否通过类、对象来调用静态方法、非静态方法(通过“类.静态方法”……的方式)
静态方法 非静态方法 类 yes no 对象 yes yes
静态方法中,只能调用静态的方法或属性(因为他们的生命周期是一样的) 非静态方法中,可以调用静态的方法或属性、也可以调用非静态的方法或属性(因为静态方法的生命周期是大于非静态方法的)
static注意点:(从生命周期的方法去理解)
在静态方法内,不能使用this关键字、super关键字 *
>在静态方法内,不能使用this关键字、super关键字 ①静态方法是随着类的加载而加载的 this是代表当前对象或当前正在创建的对象 类刚加载时 没有进行类的实例化 就没有对象 所以不能使用this ②super调用的是父类中的结构 父类中的结构要靠子类的构造器创建对象时或取 所以更不能使用super了 >在静态方法内,不能调用非静态结构(属性、方法) (同一个类中)非静态结构前一般省略this. >在非静态方法内,可以调用静态结构(属性、方法) (同一个类中)静态结构前一般省略类.
开发中,如何确定一个属性是否要声明为static的?
> 属性是可以被多个对象所共享的,不会随着对象的不同而不同的 > 类中的常量(final) 也常声明为static
开发中,如何确定一个方法是否要声明为static的?
> 操作静态属性的方法,通常设置为static的(例如静态属性的 get() 、set() 方法)
> 工具类中的方法,习惯上声明为static的。比如Math、Arrays、Collections
(把这些方法声明为静态是因为 调用这些常用的方法就不用再去声明一个对象再来调用方法了)
子主题
子主题
子主题
子主题
Java Ben
子类对象实例化的全过程
java.lang.Object类
equals()方法
toString()方法
Java中的JUnit单元测试
包装类的使用
单例设计模式
局部变量
将声明在方法内、方法形参、代码块内、构造器形参、构造器内的变量。
加载到栈空间
不可以使用权限修饰符
局部变量:没有默认初始化值 特别地:形参在调用时,我们赋值即可