笔上得来终觉浅,绝知此事要躬行
🔥 个人主页:星云爱编程
🔥 所属专栏:javase
🌷追光的人,终会万丈光芒
🎉欢迎大家点赞👍评论📝收藏⭐文章
目录
一、封装
1.1基本介绍
1.2封装的好处
1.3封装的实现步骤(三步)
1 4封装实例:
二 、继承
2.1基本介绍
2.2继承基本语法
2.3继承的好处
2.4注意事项及使用细节
三、super关键字
3.1基本介绍
3.2基本语法
3.3使用super的好处及其使用细节
3.4super和this的比较
四、方法重写/覆盖(override)
4.1基本介绍
4.2方法重写案例:
4.3注意事项及细节
4.4方法重写与方法重载的比较
五、多态
5.1基本介绍
5.2多态的具体体现
5.3注意事项及使用细节
5.3.1多态的前提
5.3.2多态的向上转型
5.3.3多态的向下转型
5.3.4补充
5.4Java 重要特性: 动态绑定机制
5.5多态的应用
结语
面向对象编程有三大特征:封装、继承和多态。
一、封装
1.1基本介绍
封装就是把抽象出的数据[属性]和对数据的操作[方法]封装到一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作。
1.2封装的好处
(1)隐藏实现细节:方法(连接数据库)<--调用(传入参数...)。
(2)可以对数据进行验证,保证安全合理。
1.3封装的实现步骤(三步)
(1)将属性进行私有化:private修饰(作用是不能直接修改属性)
(2)提供一个公共的(public 修饰)set方法,用于对属性判断并赋值
set方法基本语法如下:
public void setXxx(类型 参数名){
属性=参数名;
}
Xxx:表示某个属性,实现数据验证的业务逻辑
(3)提供一个公共的(public 修饰)get方法,用于获取属性的值
get方法基本语法如下:
public 类型 getXxx(){
return xxx;
}
Xxx:表示某个属性,实现数据验证的业务逻辑。
1 4封装实例:
class Cat{
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
二 、继承
2.1基本介绍
当多个类存在相同的属性(成员变量)和成员方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有子类不需要重新定义这些属性和方法,只需通过extends关键字来声明继承父类即可。
2.2继承基本语法
class 子类 extends 父类{
}
说明:
(1)子类会自动拥有父类定义的属性和方法。
(2)父类又叫超类、基类。
(3)子类又叫派生类。
2.3继承的好处
(1)提高代码的复用性。
(2)提高代码的扩张性和维护性。
2.4注意事项及使用细节
(1)子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。
(2)子类必须调用父类的构造器,完成父类的初始化。
(3)当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无 参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
(4)如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)。
(5)super在使用时,必须放在构造器第一行(super只能在构造器中使用)。
(6) super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器。
(7)java所有类都是Object类的子类,Object是所有类的基类。
(8)父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)。
(9)子类最多只能继承一个父类(指直接继承),即java中是单继承机制。
(10)不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。
思考:如何让A类继承B类和C类?
答:A继承B,B继承C。
三、super关键字
3.1基本介绍
super代表父类的引用,用于访问父类的属性、方法、构造器。
3.2基本语法
(1)访问父类的属性,但不能访问父类的私有(private)属性。eg. super.属性名
(2)访问父类的方法,但不能访问父类的私有(private)方法。eg. super.方法名(参数列表)
(3)访问父类的构造器。eg. super(参数列表);只能放在构造器的第一句,并且只能出现一句。
3.3使用super的好处及其使用细节
(1)调用父类的构造器好处:分工明确,父类属性由父类初始化,子类的属性由子类初始化。
(2)当子类中有和父类中的成员(属性和方法)重名时,为访问父类的成员,必须通过super来调用。如果没有重名,使用super/this和直接访问是一样的效果。
(3)super的访问不限于直接父类,如果有爷爷类并和本类中的有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则,当然也要遵守访问权限的相关规则。
3.4super和this的比较
区别点 | this | super |
---|---|---|
访问属性 | 访问本类的属性;若本类中没有该属性,则从父类中开始寻找,遵循就近原则。 | 从父类开始查找属性 |
调用方法 | 访问本类的方法;若本类中没有该方法,则从父类中开始寻找,遵循就近原则。 | 从父类开始查找方法 |
调用构造器 | 调用本类构造器必须放在构造器的第一行 | 调用父类构造器必须放在子类构造器的第一行 |
特殊点 | 表示当前对象 | 子类中访问父类对象 |
四、方法重写/覆盖(override)
4.1基本介绍
方法重写就是子类有一个方法和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类这个方法重写了父类的那个方法。
4.2方法重写案例:
public class Test2 {
public static void main(String[] args) {
Animals animals = new Animals();
Dog dog = new Dog();
animals.est();
dog.est();
}
}
class Animals{
public void est(){
System.out.println("动物吃东西");
}
}
class Dog extends Animals{
@Override
public void est() {
System.out.println("小狗吃狗粮");
}
}
4.3注意事项及细节
(1)子类的方法的参数、方法名称,要和父类方法的参数、方法名称完全一样。
(2)子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类。
(3)子类方法不能缩小父类方法的访问权限,即子类访问修饰符的访问权限不能比父类的小。
4.4方法重写与方法重载的比较
名称 | 发生范围 | 方法名 | 形参列表 | 返回类型 | 访问修饰符 |
---|---|---|---|---|---|
方法重载 | 本类 | 必须一样 | 参数类型、个数或顺序至少有一个不同 | 无要求 | 无要求 |
方法重写 | 父子类 | 必须一样 | 和父类相同 | 子类重写的方法的返回类型和父类的返回类型一致,或是父类的返回类型的子类 | 子类方法不能缩小父类方法的访问范围 |
五、多态
5.1基本介绍
方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承基础至上的。
5.2多态的具体体现
(1)方法的多态:方法重写和方法重载体现多态
(2)对象的多态:
①:一个对象的编译类型和运行类型可以不一致。
②:编译类型在定义对象时,就确定了,不能改变。
③:运行类型是可以变化的、
④:编译类型看定义时=号的左边,运行类型看=号的右边。简记:左编译右运行。
5.3注意事项及使用细节
5.3.1多态的前提
两个对象存在继承关系
5.3.2多态的向上转型
(1)本质:父类的引用指向了子类的对象
(2)语法:
父类类型 引用名 = new 子类类型()
可类比为如下代码,方便理解:
int y=666;
double x= y;
(3)特点:
①编译类型看=左边,运行类型看=右边;
②可以调用父类中的所有成员(遵守访问权限);
③不能调用子类中的特有成员,因为在编译阶段,能调用哪些成员,由编译类型决定;
④ 最终运行效果看子类的具体实现,即调用方法时,按照从子类开始查找方法。
5.3.3多态的向下转型
(1)语法:
子类类型 引用名 = (子类类型)父类引用
可类比为如下代码,方便理解:
double y = 3.14;
int x = (int) y;
(2)特点:
①:只能强转父类的引用,不能强转父类的对象。
就好比你能改变小狗的名字,但不能把小狗变成小猫。
②:要求父类的引用必须指向的是当前目标类型的对象。
③:当向下转型后,可以调用子类类型中的成员
5.3.4补充
(1)属性没有重写之说!属性的值看编译类型。
(2)instanceof 比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型
①语法:
引用名 instanceof 类名
②返回类型为boolean型:对象的运行类型为XX类型或XX类型的子类型返回true,否则返回false。
5.4Java 重要特性: 动态绑定机制
(1)当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定。
(2)当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用。
即对象方法有绑定,属性无绑定,就近原则,哪里声明,哪里使用。
来看看下面的代码运行后会输出什么:
public class Test5 {
public static void main(String[] args) {
F d=new S();
System.out.print(d.sum());
System.out.println(d.sum2());
}
}
class F{
public int i=10;
public int sum(){
return getI()+20;
}
public int sum2(){
return i+20;
}
public int getI(){
return i;
}
}
class S extends F{
public int i=70;
//将下面注释注销再运行看看
// public int sum(){
// return getI()+30;
// }
// public int sum2(){
// return i+50;
// }
public int getI() {
return i;
}
}
答案是: 90 30
怎么样,你做对了吗?再试着把S类中的注释注销,然后看看运行结果,这对理解动态绑定机制很有用!
5.5多态的应用
(1)多态数组
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型。eg:
public class Test4 {
public static void main(String[] args) {
Animals_ []animals=new Animals_[3];
animals[0]=new Dog_();
animals[1]=new Cat_();
animals[2]=new Animals_();
for(int i=0;i<animals.length;i++){
animals[i].eat();
}
}
}
class Animals_{
public void eat(){
System.out.println("动物吃...");
}
}
class Dog_ extends Animals_{
@Override
public void eat() {
System.out.println("小狗吃狗粮");
}
}
class Cat_ extends Animals_{
@Override
public void eat() {
System.out.println("小猫吃猫粮");
}
}
(2)多态参数
方法定义的形参类型为父类类型,实参类型可以为子类类型。
结语
感谢您的耐心阅读,希望这篇博客能够为您带来新的视角和启发。如果您觉得内容有价值,不妨动动手指,给个赞👍,让更多的朋友看到。同时,点击关注🔔,不错过我们的每一次精彩分享。若想随时回顾这些知识点,别忘了收藏⭐,让知识触手可及。您的支持是我们前进的动力,期待与您在下一次分享中相遇!
路漫漫其修远兮,吾将上下而求索。