您的位置:首页 > 娱乐 > 八卦 > 七、面向对象编程(中级)

七、面向对象编程(中级)

2024/12/23 5:46:50 来源:https://blog.csdn.net/weixin_44063529/article/details/141476054  浏览:    关键词:七、面向对象编程(中级)

文章目录

  • 一、IDEA
    • 1.1 IDEA下载安装
    • 1.2 IDEA的使用
    • 1.3 IDEA常用的快捷键
  • 二、包
    • 2.1 包的基本介绍
    • 2.2 包的本质分析
    • 2.3 包的命名
    • 2.4 常用的包
    • 2.5 如何引入包
  • 三、访问修饰符
  • 四、面向对象的三大特征
    • 4.1 封装
    • 4.2 继承
      • 4.2.1 为什么需要继承
      • 4.2.2 继承的基本介绍
      • 4.2.3 继承的深入讨论/细节问题
      • 4.2.4 继承的本质分析(内存分析,重要)
    • 4.3 super关键字
    • 4.4 super与this的比较
    • 4.5 方法重写/覆盖(override)
    • 4.6 方法重写与重载比较
    • 4.7 多态
      • 4.7.1 基本介绍
      • 4.7.2 多态注意事项和细节讨论
      • 4.7.3 java的动态绑定机制(非常非常重要)
      • 4.7.4 多态的应用
  • 五、Object类详解
    • 5.1 equals方法
    • 5.2 hashCode方法
    • 5.3 toString()方法
    • 5.4 finalize方法
  • 六、断点调试
  • 七、细节知识
    • 7.1 访问修饰符
    • 7.2 继承的细节
    • 7.3 继承的本质分析(内存分析,重要)
    • 7.4 super细节
    • 7.5 方法重写的细节
    • 7.6 多态的理解
    • 7.7 java的动态绑定机制(非常非常重要)

一、IDEA

1.1 IDEA下载安装

在这里插入图片描述

1.2 IDEA的使用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.3 IDEA常用的快捷键

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、包

2.1 包的基本介绍

在这里插入图片描述

2.2 包的本质分析

在这里插入图片描述

2.3 包的命名

在这里插入图片描述

2.4 常用的包

在这里插入图片描述

2.5 如何引入包

在这里插入图片描述

建议:我们需要使用哪个类就导入哪个类,不建议使用 * 导入
在这里插入图片描述

在这里插入图片描述

三、访问修饰符

在这里插入图片描述

在这里插入图片描述

注:上述多个访问范围之间是或的关系(如:protected修饰的属性或方法可以被 同类同包子类 访问);另外 同包 指的是 完全相同的包路径(子包路径不算相同)

四、面向对象的三大特征

  • 基本介绍
    面向对象编程有三大特征:封装继承多态

4.1 封装

  • 基本介绍
    在这里插入图片描述

  • 封装的理解和好处
    在这里插入图片描述

  • 封装的实现步骤
    在这里插入图片描述

  • 快速入门
    在这里插入图片描述

public class Hello {public static void main(String[] args) {Person person = new Person();person.setAge(900);}
}class Person {public String name;private int age;private double salary;private String job;public Person() {}public Person(String name, int age, double salary, String job) {setAge(age);setJob(job);setName(name);setSalary(salary);}public void setName(String name) {if (name.length() >= 2 && name.length() <= 6) {this.name = name;return;}System.out.println("输入的名字长度必须在2-6之间");}public void setAge(int age) {if (age >= 1 && age <= 120) {this.age = age;return;}System.out.println("年龄必须在1-120");}public void setSalary(double salary) {this.salary = salary;}public void setJob(String job) {this.job = job;}public String getName() {return name;}public int getAge() {return age;}public double getSalary() {return salary;}public String getJob() {return job;}
}

4.2 继承

4.2.1 为什么需要继承

在这里插入图片描述

4.2.2 继承的基本介绍

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.2.3 继承的深入讨论/细节问题

在这里插入图片描述

// 基础父类
package com.extends_;public class Base {// 4个属性public int n1 = 100;protected int n2 = 200;int n3 = 300;private int n4 = 400;public int getN4() { // 构建公共方法使子类可以访问私有属性return this.n4;}public Base() {}public void test100() {System.out.println("test100()....");}protected void test200() {System.out.println("test200()....");}void test300() {System.out.println("test300()....");}private void test400() {System.out.println("test400()....");}
}
// 子类(与父类同包)
package com.extends_;public class Sub extends Base {public Sub() {}public void sayOk() {// 非私有的属性和方法可以在子类直接访问// 私有属性和方法不能在子类直接访问(n4无法直接访问)System.out.println(n1 + "" + n2 + "" + n3);int n4 = getN4();// 通过父类的公共方法对私有属性进行访问System.out.println("n4:"+n4);test100();test200();test300();
//        test400(); 无法直接访问}
}

在这里插入图片描述

在这里插入图片描述

  • 注意第6点,使用了this()后则编译器不会默认添加一个super()

在这里插入图片描述

在这里插入图片描述

4.2.4 继承的本质分析(内存分析,重要)

public class ExtendsTest{public static void main(String[] args){Son son = new son(); // 内存的布局System.out.println(son.age); // 访问父类中的属性age}
}class GrandPa{String name = "大头爷爷";String hobby = "旅游";
}class Father extends GrandPa{String name = "大头爸爸";int age = 39;
}class Son extends Father{String name = "大头儿子";
}

在这里插入图片描述

  • 执行流程:
    1. 方法区加载类信息 ,顺序由继承关系决定(Object --> GrandPa --> Father --> Son)并建立类之间的关系
    2. 在堆中创建Son的实例,按继承关系创建属性初始化(各父类中的变量会存储在独立的二级堆空间中)
    3. 将Son实例的引用赋值给main方法栈中的son引用变量
    4. 若使用son调用属性方法,则遵守以下原则:
      1. 首先看子类是否有该属性 (方法)
      2. 如果子类有这个属性 (方法),并可以访问,则返回信息
      3. 如果子类没有这个属性 (方法),就看父类有没有这个属性 (方法)(如果父类有该属性 (方法),并可以访问,就返回信息…)
      4. 如果父类没有就按照(3)的规则,继续找上级父类,直到Object。注意:如果某一父类中有该属性 (方法)但由于访问修饰符限制(如:private)无法直接访问,则java编译器会停止向其父类寻找,直接返回无法访问的编译错误

4.3 super关键字

  • 基本介绍
    注意:super不是一个对象引用,super是一个指示java编译器调用父类实例域的特殊关键字
    在这里插入图片描述

  • super的细节
    在这里插入图片描述

public class A{public void say(){System.out.println("A say~~");}
}public class B extends A{public void test(){// say();// this.say();super.say();}
}
  • 在B的方法中调用say()(与this.say()等同)的执行流程如下:
    1. 首先看子类是否有该属性 (方法)
    2. 如果子类有这个属性 (方法),并可以访问,则返回信息
    3. 如果子类没有这个属性 (方法),就看父类有没有这个属性 (方法)(如果父类有该属性 (方法),并可以访问,就返回信息…)
    4. 如果父类没有就按照(3)的规则,继续找上级父类,直到Object。注意:如果某一父类中有该属性 (方法)但由于访问修饰符限制(如:private)无法直接访问,则java编译器会停止向其父类寻找,直接返回无法访问的编译错误
      注意:使用 super.say() 会跳过上述第一步,直接从其父类开始查找

在这里插入图片描述

4.4 super与this的比较

在这里插入图片描述

4.5 方法重写/覆盖(override)

  • 基本介绍
    在这里插入图片描述

  • 方法重写注意事项和使用细节
    在这里插入图片描述

4.6 方法重写与重载比较

在这里插入图片描述

4.7 多态

4.7.1 基本介绍

在这里插入图片描述

在这里插入图片描述

注意 编译类型运行类型 的概念

4.7.2 多态注意事项和细节讨论

  • 调用方法使用运行类型,直接访问属性使用 编译类型
    在这里插入图片描述
public class Animal{public void eat(){System.out.println("...");}
}class Cat extends Animal{public void eat(){ // 方法重写System.out.println("吃鱼");        }
}class Dog extends Animal{public void eat(){ // 方法重写System.out.println("吃骨头");        }
}
public class Test{public static void main(String[] args){Animal animal = new Cat(); // 父类的引用指向了子类的实例// 可以调用父类中的所有成员(需要遵守访问权限)// 但是不能调用子类的特有的成员 (因为需要通过java的编译)// 因为在编译阶段,能调用哪些成员,是由编译类型来决定的// 最终的运行效果看子类的具体实现,即调用方法时,按照从子类开始查找方法// 然后调用,规则和我们前面讲的方法调用规则一致animal.eat(); // 调用重写的实现}
}

在这里插入图片描述

在这里插入图片描述

  • null 数据也可以使用 instanceof,其结果为 false
public class Test{public static void main(String[] args){BB bb = new BB();System.out.println(bb instanceof BB); // trueSystem.out.println(bb instanceof AA); // true// aa的编译类型是AA,运行类型是BBAA aa = new BB();System.out.println(aa.n); // "a",说明访问的是编译类型对应的属性值System.out.println(aa instanceof AA); // trueSystem.out.println(aa instanceof BB); // true,说明 instanceof 判断的是aa的运行类型是否是BB}
}class AA{String n = 'a';
}class BB extends AA{String n = 'b';
}

4.7.3 java的动态绑定机制(非常非常重要)

  1. 当调用对象 方法 的时候,该方法会和该对象的 内存地址/运行类型 绑定
  2. 当调用对象 属性 时,没有动态绑定机制,哪里声明,哪里使用
public class Test{public static void main(String[] args){A a = new B(); // 向上转型// 动态绑定机制: // (1)调用 B 类继承的sum方法(sum() 与 B 的实例绑定,这里 this --> new B()); // (2)其中getI() (同this.getI())则调用B中重写的方法; // (3)B中的getI()方法中的 i (同this.i)没有动态绑定机制则返回B的成员变量ISystem.out.println(a.sum()); // 30// 动态绑定机制: // (1)调用 B 类继承的sum1方法(sum1() 与 B 的实例绑定,这里 this --> new B()); // (3)其中的 i (同this.i)没有动态绑定机制则返回A的成员变量ISystem.out.println(a.sum1()); // 20}
}class A{ // 父类public int i = 10;public int sum(){return getI() + 10;}public int sum1(){return i + 10;}public int getI(){return i;}
}class B{ // 子类public int i = 20;public int getI(){return i;}
}

4.7.4 多态的应用

在这里插入图片描述

在这里插入图片描述

五、Object类详解

5.1 equals方法

  • Object 类的 equals 方法实现的是判断是否是同一个对象
    在这里插入图片描述

在这里插入图片描述

// 自定义equals方法
public class Person{private String name;private int age;private char gender;public Person(String name, int age, char gender){this.name = name;this.age = age;this.gender = gender;}public boolean equals(Obejct obj){if (obj == this){return true;}if(obj instanceof Person){Person pObj = (Person) obj ;return this.name.equals(pObj .name) && this.age == pObj.age && this.gender == pObj.gender;}return false;}    }

5.2 hashCode方法

在这里插入图片描述

5.3 toString()方法

在这里插入图片描述

5.4 finalize方法

在这里插入图片描述

六、断点调试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

七、细节知识

7.1 访问修饰符

  • 成员变量方法可以被:publicprotected默认private修饰
  • 类只能被:public默认修饰
    在这里插入图片描述

注:上述多个访问范围之间是或的关系(如:protected修饰的属性或方法可以被 同类同包子类 访问)。另外 同包 指的是 完全相同的包路径(子包路径不算相同)

7.2 继承的细节

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 注意第6点,使用了this()后则编译器不会默认添加一个super()

在这里插入图片描述

7.3 继承的本质分析(内存分析,重要)

public class ExtendsTest{public static void main(String[] args){Son son = new son(); // 内存的布局}
}class GrandPa{String name = "大头爷爷";String hobby = "旅游";
}class Father extends GrandPa{String name = "大头爸爸";int age = 39;
}class Son extends Father{String name = "大头儿子";
}

在这里插入图片描述

  • 执行流程:
    1. 方法区加载类信息 ,顺序由继承关系决定(Object --> GrandPa --> Father --> Son)并建立类之间的关系
    2. 在堆中创建Son的实例,按继承关系创建属性初始化(各父类中的变量会存储在独立的二级堆空间中)
    3. 将Son实例的引用赋值给main方法栈中的son引用变量
    4. 若使用son调用属性方法,则遵守以下原则:
      1. 首先看子类是否有该属性 (方法)
      2. 如果子类有这个属性 (方法),并可以访问,则返回信息
      3. 如果子类没有这个属性 (方法),就看父类有没有这个属性 (方法)(如果父类有该属性 (方法),并可以访问,就返回信息…)
      4. 如果父类没有就按照(3)的规则,继续找上级父类,直到Object。注意:如果某一父类中有该属性 (方法)但由于访问修饰符限制(如:private)无法直接访问,则java编译器会停止向其父类寻找,直接返回无法访问的编译错误

7.4 super细节

注意:super不是一个对象引用(不能赋值给引用变量),super是一个指示java编译器调用父类实例域的特殊关键字
在这里插入图片描述

public class A{public void say(){System.out.println("A say~~");}
}public class B extends A{public void test(){// say();// this.say();super.say();}
}
  • 在B的方法中调用say()(与this.say()等同)的执行流程如下:
    1. 首先看子类是否有该属性 (方法)
    2. 如果子类有这个属性 (方法),并可以访问,则返回信息
    3. 如果子类没有这个属性 (方法),就看父类有没有这个属性 (方法)(如果父类有该属性 (方法),并可以访问,就返回信息…)
    4. 如果父类没有就按照(3)的规则,继续找上级父类,直到Object。注意:如果某一父类中有该属性 (方法)但由于访问修饰符限制(如:private)无法直接访问,则java编译器会停止向其父类寻找,直接返回无法访问的编译错误
      注意:使用 super.say() 会跳过上述第一步,直接从其父类开始查找
      在这里插入图片描述

7.5 方法重写的细节

在这里插入图片描述

7.6 多态的理解

  • 注意 编译类型运行类型 的概念
  • 调用方法使用运行类型,直接访问属性使用 编译类型
    在这里插入图片描述

在这里插入图片描述

public class Animal{public void eat(){System.out.println("...");}
}class Cat extends Animal{public void eat(){ // 方法重写System.out.println("吃鱼");        }
}class Dog extends Animal{public void eat(){ // 方法重写System.out.println("吃骨头");        }
}
public class Test{public static void main(String[] args){Animal animal = new Cat(); // 父类的引用指向了子类的实例// 可以调用父类中的所有成员(需要遵守访问权限)// 但是不能调用子类的特有的成员 (因为需要通过java的编译)// 因为在编译阶段,能调用哪些成员,是由编译类型来决定的// 最终的运行效果看子类的具体实现,即调用方法时,按照从子类开始查找方法// 然后调用,规则和我们前面讲的方法调用规则一致animal.eat(); // 调用重写的实现}
}

在这里插入图片描述

在这里插入图片描述

public class Test{public static void main(String[] args){BB bb = new BB();System.out.println(bb instanceof BB); // trueSystem.out.println(bb instanceof AA); // true// aa的编译类型是AA,运行类型是BBAA aa = new BB();System.out.println(aa.n); // "a",说明访问的是编译类型对应的属性值System.out.println(aa instanceof AA); // trueSystem.out.println(aa instanceof BB); // true,说明 instanceof 判断的是aa的运行类型是否是BB}
}class AA{String n = 'a';
}class BB extends AA{String n = 'b';
}

7.7 java的动态绑定机制(非常非常重要)

  1. 当调用对象 方法 的时候,该方法会和该对象的 内存地址/运行类型 绑定
  2. 当调用对象 属性 时,没有动态绑定机制,哪里声明,哪里使用
public class Test{public static void main(String[] args){A a = new B(); // 向上转型// 动态绑定机制: // (1)调用 B 类继承的sum方法(sum() 与 B 的实例绑定,这里 this --> new B()); // (2)其中getI() (同this.getI())则调用B中重写的方法; // (3)B中的getI()方法中的 i (同this.i)没有动态绑定机制则返回B的成员变量ISystem.out.println(a.sum()); // 30// 动态绑定机制: // (1)调用 B 类继承的sum1方法(sum1() 与 B 的实例绑定,这里 this --> new B()); // (3)其中的 i (同this.i)没有动态绑定机制则返回A的成员变量ISystem.out.println(a.sum1()); // 20}
}class A{ // 父类public int i = 10;public int sum(){return getI() + 10;}public int sum1(){return i + 10;}public int getI(){return i;}
}class B{ // 子类public int i = 20;public int getI(){return i;}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com