JAVA面向对象三大特征

news2025/1/15 23:09:08

1.面向对象的三大特征包括封装、继承和多态。

  1. 封装:封装是指将数据和操作数据的方法绑定起来,外界对数据的访问只能通过已定义的接口。这种特性有两层含义,一层是将属性和行为看成一个密不可分的整体,将这两者封装在一个对象中;另一层含义是信息隐藏,把不需要让外界知道的信息隐藏起来。这种特性可以保护对象内部的结构和数据,使得对成员变量的访问只能通过已定义的接口实现。
  2. 继承:继承指从已有的类(也称为父类、基类、超类)得到继承信息创建新类(也称为子类、派生类)的过程。子类继承父类的特征和行为,使得子类对象实例具有父类的实例和方法,子类从父类继承方法,使得子类具有父类相同的行为。继承可以减少代码的重复性,提高代码的可维护性和可重用性。
  3. 多态:多态指允许不同的对象对同一消息(发送消息即函数调用)作出不同的响应。多态的实现条件包括继承和重写。子类可以重写父类的方法,使得子类可以根据自己的需要实现特定的行为。多态可以增强代码的可读性和可维护性,同时也可以提高代码的灵活性和扩展性。

总之,封装、继承和多态是面向对象编程的三大基本特征,它们使得程序更加模块化、可维护性和可重用性更高。

2.封装

好处:

1.隐藏实现细节,只管调用

2.可以对数据进行验证,保证安全合理 (private 在同类可改)

封装入门

package com.hspedu;

public class Encapsulation01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("jack8080");
        person.setAge(300);
        person.setSalary(30000);
        System.out.println(person.info());
    }
}
/*
* 要求:年龄,工资为隐私
* 数据验证:年龄(1-120) 不合理给默认年龄
* name 2-6个字符
* */
class Person {
    public String name;
    private int age;
    private double salary;
    //使用快捷键 
    public String getName() {
        return name;
    }

    public void setName(String name) {
        if(name.length() >= 2 && name.length() <= 6){
            this.name = name;
        }else {
            System.out.println("name 需要在2-6个字符");
            this.name = "无名人";
        }
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age >= 1 && age <= 120){
            this.age = age;
        } else {
            System.out.println("输入年龄需要在 1-120");
            this.age = 18; //给默认年龄
        }
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    //写一个方法,返回属性信息
    public String info() {
        return "信息为 name=" + name + " age=" + age + " 薪水=" + salary;
    }

}

封装与构造器 

package com.hspedu;

public class Encapsulation01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("jack8080");
        person.setAge(300);
        person.setSalary(30000);
        System.out.println(person.info());
        //使用构造器指定属性
        Person smith = new Person("smith", 80, 50000);
        System.out.println("===smith的信息===");
        System.out.println(smith.info());
    }
}
/*
* 要求:年龄,工资为隐私
* 数据验证:年龄(1-120) 不合理给默认年龄
* name 2-6个字符
* */
class Person {
    public String name;
    private int age;
    private double salary;
    public Person(){

    }

    public Person(String name, int age, double salary) {
        //用构造器会被破解,要在构造器中使用方法
//        this.name = name;
//        this.age = age;
//        this.salary = salary;
        setName(name);
        setAge(age);
        setSalary(salary);
    }

    //使用快捷键
    public String getName() {
        return name;
    }

    public void setName(String name) {
        if(name.length() >= 2 && name.length() <= 6){
            this.name = name;
        }else {
            System.out.println("name 需要在2-6个字符");
            this.name = "无名人";
        }
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age >= 1 && age <= 120){
            this.age = age;
        } else {
            System.out.println("输入年龄需要在 1-120");
            this.age = 18; //给默认年龄
        }
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    //写一个方法,返回属性信息
    public String info() {
        return "信息为 name=" + name + " age=" + age + " 薪水=" + salary;
    }

}

3.继承 

好处:

1.代码复用,在父类中定义相同的属性和方法

2.拓展性,维护性提高了

细节:

1.可以用父类的公共方法将私有属性,方法返回数据给子类

访问级别访问控制修饰符同类同包子类不同包
公开public
受保护protected×
默认没有修饰符××
私有private×××

2.子类必须调用父类的构造器,完成父类初始划 默认子类有super();调用父类无参构造器。若父类没有无参构造器,得用super(参数列表)去指定。

3.子类调用父类的构造器,要将super放在第一行

4.super()和this()都只能放在构造器第一行,因此两个方法不能共存在一个构造器

5.Object是所有类的基类 ctrl + H 可以看到类的继承关系(IDEA) 

6.子类最多只能继承一个父类,且与父类要有逻辑关系



public class ExtendsExercise {
    public static void main(String[] args) {
        B b = new B();
    }
}

class A {
    A() {
        System.out.println("a");
    }
    A(String name) {
        System.out.println("a name");
    }
}

class B extends A {
    B(){
        this("abc");
        System.out.println("b");
    }
    B(String name) {
        System.out.println("b name");
    }
}

结果:

方法重写(覆盖)

方法重写是指在子类中重新定义(或覆盖)其父类中已有的方法,使其具有不同的实现。方法重写是面向对象编程中实现多态性的重要手段之一。

方法重写需要满足以下条件:

  1. 方法名、参数列表必须与父类中被重写的方法相同。
  2. 访问修饰符不能降低(可以提升)。
  3. 返回类型必须与父类中被重写方法的返回类型相同或是其子类。
  4. 抛出的异常类型必须是父类中被重写方法所抛出异常类型的子集,或者子类方法不抛出异常。

方法重写使得子类可以根据自己的需要实现特定的行为,增强了代码的可读性和可维护性,同时提高了代码的灵活性和扩展性。

方法重载和方法重写

是面向对象编程中的两个重要概念,它们都可以实现多态性,但它们之间存在明显的区别。下面是一个表格,总结了方法重载和方法重写的主要区别:

特征方法重载方法重写
定义在同一类中定义多个同名方法,参数列表不同在子类中重新定义父类中的方法
目的实现多态性,提供不同的实现方式实现多态性,子类根据需要实现特定行为
参数列表不同方法名,参数列表不同相同方法名,参数列表相同
返回类型可以不同,但通常是相同或子类关系相同或子类关系
访问修饰符可以不同,但通常是相同或更宽松的限制可以不同,但通常是相同或更宽松的限制
异常类型可以不同,但通常是相同或更宽松的限制相同或子类关系
执行时间编译时多态性,在编译时确定实际调用的方法运行时多态性,在运行时确定实际调用的方法
使用场景方法重载通常用于操作类别的不同对象方法重写通常用于子类扩展父类的行为或接口的实现

这个表格总结了方法重载和方法重写的主要区别。通过理解这些区别,开发人员可以更好地运用这两个概念来设计和实现面向对象的程序。

着重注意super调用构造器和方法 

package com.hspedu.extend_.exercise;

public class OverrideExercise {
    public static void main(String[] args) {
        Person jack = new Person("jack", 10);
        System.out.println(jack.say());
        student smith = new student("smith", 20, 123456, 99.8);
        System.out.println(smith.say());
    }
}



package com.hspedu.extend_.exercise;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String say() {
        return "name=" + name + " 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;
//    }
}



package com.hspedu.extend_.exercise;

public class student extends Person {
    private int id;
    private double score;

    public student(String name, int age, int id, double score) {
        super(name, age);
        this.id = id;
        this.score = score;
    }

    public String say() {
        return super.say() + " id=" + id + " score=" + score;
    }

//    public int getId() {
//        return id;
//    }
//
//    public void setId(int id) {
//        this.id = id;
//    }
//
//    public double getScore() {
//        return score;
//    }
//
//    public void setScore(double score) {
//        this.score = score;
//    }
}

结果: 

4.多态

多态是建立在封装和继承的基础上的。两个对象(类)要存在继承关系

1.方法的多态:

        重写和重载就体现多态。

 2.对象的多态:

(1)一个对象的编译类型和运行类型可以不一致

(2) 编译类型在定义对象时,就确定了,不能改变

(3)运行类型是可以变化的.
(4)编译类型看定义时=号 的左边,运行类型看=号的右边

eg:父类的引用指向子类的对象

Animal animal = new Dog(); [animal编译类型是Anima,运行类型是Dog]

animal = new Cat();[animal 运行类型变为Cat, 编译类型仍为Animal]

ps:找的是运行类型的方法 ,在编译阶段,调用由编译类型决定

3.多态的向上转型

1) 本质:父类的引用指向了子类的对象  Animal animal = new Dog();  //运行类型为编译类型的子类
2) 语法:父类类型引用名 = new 子类类型();

3) 特点:编译类型看左边,运行类型看右边。
可以调用父类中的所有成员(需遵守访问权限),不能调用子类中特有成员,下方不能写animal.catchMouse;预知如何解局,请看向下转型。
最终运行效果看子类的具体实现!

package com.hspedu.extend_.exercise;

public class poly {
    public static void main(String[] args) {
        //多态的向上本质:父类的引用指向了子类的对象
        //语法: 父类类型引用名 = new 子类类型()//object obj = new Cat();
        Animal animal = new Cat();
        System.out.println("ok");
        //最终效果看子类的具体实现
        animal.eat();
        animal.run();
        animal.show();
        animal.sleep();
    }
}



//-------------------------------

package com.hspedu.extend_.exercise;

public class Animal {
    String name = "动物";
    int age = 10;
    public void sleep(){
        System.out.println("睡");
    }
    public void run(){
        System.out.println("跑");
    }
    public void eat(){
        System.out.println("吃");
    }
    public void show(){
        System.out.println("hello,你好");
    }
}


//----------------------------------

package com.hspedu.extend_.exercise;

public class Cat extends Animal{
    public void eat(){ //方法重写
        System.out.println("猫吃鱼");
    }
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}

4.多态的向下转型 

1) 语法:子类类型引用名=(子类类型)父类引用;

2)只能强转父类的引用,不能强转父类的对象
3)要求父类的引用必须指向的是当前目标类型的对象

4)当向下转型后,可以调用子类类型中所有的成员

        //希望可写cat.catchMouse;
        //向下转型
        //语法:子类类型引用名=(子类类型)父类引用;
        Cat cat = (Cat) animal;//此时,编译类型和运行类型皆为Cat
        cat.catchMouse();

5.多态细节 

1.属性没有重写之说!属性的值看编译类型 //方法从运行类型开始查找

package com.hspedu.extend_.exercise;

public class PolyDetail {
    public static void main(String[] args) {
        Base base = new Sub();
        System.out.println(base.count);
    }
}

class Base {
    int count = 10;
}

class Sub extends Base {
    int count = 20;
}

结果为 :10

2.在Java中,instanceof是一个关键字,用于判断一个对象是否属于某个类(子类)或接口。返回值为boolean类型。

eg:System.out.println(base instanceof Base);反映对象(运行类型)与类的关系。

6.动态绑定机制 

 
1.    当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定  //运行类型有的方法优先使用运行类型。
2.    当调用对象属性时,没有动态绑定机制,哪里声明,那里使用

 7.多态数组(多态的应用)

package com.hspedu.extend_.exercise.polyarr;

public class PloyArray {
    public static void main(String[] args) {
        Person[] persons = new Person[5];
        persons[0] = new Person("jack", 20);
        persons[1] = new Student("jack", 18, 100);
        persons[2] = new Student("smith", 19, 30.1);
        persons[3] = new Teacher("scott", 30, 20000);
        persons[4] = new Teacher("king", 50, 25000);

        //循环遍历多态数组,调用say
        for (int i = 0; i < persons.length; i++) {
            //person[i] 编译类型是 Person,运行类型根据实际情况由JVM来判定
            System.out.println(persons[i].say());//动态绑定机制
        }
    }
}



------------------分割线-------------------
package com.hspedu.extend_.exercise.polyarr;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String say() {
        return name + "\t" + age;
    }
}


------------------分割线-------------------
package com.hspedu.extend_.exercise.polyarr;

public class Student extends Person{
    private double score;

    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }

    //重写父类的say方法

    @Override
    public String say() {
        return super.say() + " score=" + score;
    }
}


------------------分割线-------------------
package com.hspedu.extend_.exercise.polyarr;

public class Teacher extends Person{
    private double salary;

    public Teacher(String name, int age, double salary) {
        super(name, age);
        this.salary = salary;
    }

    @Override
    public String say() {
        return super.say() + " salary" + salary;
    }
}


结果: 

综合进阶:

package com.hspedu.extend_.exercise.polyarr;

public class PloyArray {
    public static void main(String[] args) {
        Person[] persons = new Person[5];
        persons[0] = new Person("jack", 20);
        persons[1] = new Student("jack", 18, 100);
        persons[2] = new Student("smith", 19, 30.1);
        persons[3] = new Teacher("scott", 30, 20000);
        persons[4] = new Teacher("king", 50, 25000);

        //循环遍历多态数组,调用say
        for (int i = 0; i < persons.length; i++) {
            //person[i] 编译类型是 Person,运行类型根据实际情况由JVM来判定
            System.out.println(persons[i].say());//动态绑定机制
            //调用特有方法 --> 向下转型
            //只能强转父类的引用,不能强转父类的对象
            if(persons[i] instanceof Student) {
                ((Student)persons[i]).study(); //向下转型
            } else if (persons[i] instanceof Teacher) {
                ((Teacher)persons[i]).teach(); //向下转型
            } else {
                System.out.println("类型有误");
            }
        }



    }
}




------------------分割线-------------------
package com.hspedu.extend_.exercise.polyarr;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //构造器不能直接使私有属性公有化,但可以通过在构造器中设置公共方法来间接实现。

    public String getName() {
        return name;
    }

//    public void setName(String name) {
//        this.name = name;
//    }

    public String say() {
        return name + "\t" + age;
    }
}



------------------分割线-------------------
package com.hspedu.extend_.exercise.polyarr;

public class Student extends Person{
    private double score;

    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }

    //重写父类的say方法

    @Override
    public String say() {
        return super.say() + " score=" + score;
    }

    //特有方法
    public void study() {
        System.out.println("学生 " + getName() + " 在学java");
    }
}




------------------分割线-------------------
package com.hspedu.extend_.exercise.polyarr;

public class Teacher extends Person{
    private double salary;

    public Teacher(String name, int age, double salary) {
        super(name, age);
        this.salary = salary;
    }

    @Override
    public String say() {
        return super.say() + " salary" + salary;
    }


    //特有方法
    public void teach() {
        System.out.println("老师 " + getName() + " 在讲课");
    }
}




结果:

jack    20
类型有误
jack    18 score=100.0
学生 jack 在学java
smith    19 score=30.1
学生 smith 在学java
scott    30 salary20000.0
老师 scott 在讲课
king    50 salary25000.0
老师 king 在讲课

Process finished with exit code 0

8.多态参数(多态的应用)

形参类型为父类类型,实参类型允许为子类类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1266453.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【虚拟机】Docker基础 【一】

1.1.部署MySQL 首先&#xff0c;我们利用Docker来安装一个MySQL软件&#xff0c;大家可以对比一下之前传统的安装方式&#xff0c;看看哪个效率更高一些。 如果是利用传统方式部署MySQL&#xff0c;大概的步骤有&#xff1a; 搜索并下载MySQL安装包上传至Linux环境编译和配置…

c++|类与对象(中)

目录 一、类的6个默认成员函数 二、构造函数 2.1概念 2.2七大特性 三、析构函数 3.1概念 3.2特性 四、拷贝构造函数 4.1概念 4.2特性 五、赋值运算符重载 5.1运算符重载 5.2赋值运算符重载 5.3前置和后置重载 六、const成员函数 七、取地址及const取地址操作符重…

AI 学习笔记(持续更新)

What is AI PS &#xff1a;代码块里的统一是 gpt4 回复 在大模型中 1 b 10 亿参数的含义 AI 目前是什么&#xff1f; 目前的人工智能&#xff08;AI&#xff09;是指使计算机和机器能够模仿人类智能的技术&#xff0c;包括学习、推理、解决问题、知觉、语言理解等能力。A…

每日一练2023.11.28——A-B【PTA】

题目链接&#xff1a;L1-011 A-B 题目要求&#xff1a; 本题要求你计算A−B。不过麻烦的是&#xff0c;A和B都是字符串 —— 即从字符串A中把字符串B所包含的字符全删掉&#xff0c;剩下的字符组成的就是字符串A−B。 输入格式&#xff1a; 输入在2行中先后给出字符串A和B…

基于Spring Boot的疫苗接种系统-计算机毕设 附源码 32315

基于Spring Boot的疫苗接种系统 摘 要 预防预接种工作实行网络信息化管理&#xff0c;是我国免疫规划工作发展的需要。接种信息实行网络信息化不仅是预防接种工作步入了一个新的台阶&#xff0c;更重要的是解决了多年疫苗接种过程种&#xff0c;免疫接种剂次不清&#xff0c;难…

接手了一个外包开发的项目,我感觉我的头快要裂开了~

嗨&#xff0c;大家好&#xff0c;我是飘渺。 最近&#xff0c;我和小伙伴一起接手了一个由外包团队开发的微服务项目&#xff0c;这个项目采用了当前流行的Spring Cloud Alibaba微服务架构&#xff0c;并且是基于一个“大名鼎鼎”的微服务开源脚手架&#xff08;附带着模块代…

JAVA基础进阶(一)

一、什么是继承 把相同的属性和行为抽离出来放到父类&#xff0c;再让子类使用extends关键字继承父类后&#xff0c;就可以直接使用父类公共的属性和方法了&#xff0c;提高了代码的复用性可以降低重复代码的书写。 子类既有自己类的属性和行为&#xff0c;也有父类的属性和行…

两个mongo表,A和B,以A中的_id记录的为准, 删掉B表中A表中没有的记录

可以使用 MongoDB 的聚合管道和 $lookup 操作符来实现这个需求。以下是一个示例的查询语句,假设集合 A 和集合 B 分别对应表 A 和表 B: db.B.aggregate([{$lookup: {from: "A",localField: "_id",foreignField:

双十二有什么好物是值得推荐?智能家居好物推荐

都知十一月份跟十二月份都有两个大促的时间&#xff0c;那就是双十一跟双十二&#xff0c;距离双十一过去已经半个月了&#xff0c;是不是还有很多朋友在双十一的时候也没有买尽兴&#xff0c;别慌&#xff01;错过了双十一咱还有双十二&#xff0c;双十二的优惠力度也不会低于…

Day44力扣打卡

打卡记录 给小朋友们分糖果 II&#xff08;容斥原理 隔板法&#xff09; 链接 def c2(n):return n * (n - 1) // 2 if n > 1 else 0class Solution:def distributeCandies(self, n: int, limit: int) -> int:return c2(n 2) - 3 * c2(n - limit 1) 3 * c2(n - 2 * …

Git 是一种分布式版本控制系统常用指令

Git 是一种分布式版本控制系统&#xff0c;用于跟踪文件的变化并协同多人在同一个项目中进行开发。以下是一些常用的 Git 指令和它们的使用介绍&#xff1a; 1. 初始化一个新仓库 git init 用途&#xff1a;在当前目录初始化一个新的 Git 仓库。使用&#xff1a;在项目根目录执…

Istio新架构揭秘:环境化Mesh

自问世以来&#xff0c;Istio因其使用Sidecar&#xff08;可编程代理与应用容器一同部署&#xff09;而备受认可。这种架构选择使Istio用户能够享受其好处&#xff0c;而无需对其应用进行 drast 改变。这些可编程代理&#xff0c;与应用容器紧密部署在一起&#xff0c;因其能够…

进入最后倒计时!就在深圳福田明天上午9点正式开幕!不容错过!

会展中心介绍 深圳会展中心交通快捷便利&#xff0c;南邻滨河快速干道&#xff0c;与口岸、港口及高速公路相连&#xff0c;驾车驱往深圳火车站仅需15分钟、深圳机场仅需30分钟。地铁1号、4号线在会展中心站接驳&#xff0c;通过市政地下通道可从馆内直达地铁站&#xff0c;仅需…

Paragon NTFS16Mac读写外置移动硬盘专业工具

Paragon NTFS for Mac16是一款非常不错的Mac读写工具&#xff0c;解决了大部分Mac电脑用户无法读取移动硬盘的困扰&#xff0c;Paragon NTFS for 16版一直是Mac OS平台上最受欢迎的NTFS硬盘格式读取工具&#xff0c;有了NTFS for Mac &#xff0c;安装了双系统的Mac用户可以在O…

Redis基本操作及使用

&#x1f4d1;前言 本文主要是【Redis】——Redis基本操作及使用的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一…

线性可分SVM摘记

线性可分SVM摘记 0. 线性可分1. 训练样本到分类面的距离2. 函数间隔和几何间隔、(硬)间隔最大化3. 支持向量 \qquad 线性可分的支持向量机是一种二分类模型&#xff0c;支持向量机通过核技巧可以成为非线性分类器。本文主要分析了线性可分的支持向量机模型&#xff0c;主要取自…

Lesson 08 string类 (上)

C&#xff1a;渴望力量吗&#xff0c;少年&#xff1f; 文章目录 一、STL1. 概念2. STL的六大组件3. STL的重要性 二、string类的介绍与使用1. 介绍2. 使用&#xff08;1&#xff09;string类对象的常见构造&#xff08;2&#xff09;string类对象的容量操作&#xff08;3&…

jetson nano 串口通信

目录 1.UART通信介绍 2.电脑端准备工作 2.1 安装串口调试助手 2.2 硬件接线 3.Jetson Nano端准备工作 3.1安装库文件 3.2修改主板上电启动串口权限 4.示例程序-发送及接收 4.1 开启串口调试助手 4.2 导入示例程序 4.3 执行程序 4.4 查看效果 4.4.1 串口调试端 4.4…

交流负载的原理与应用

交流负载是指能够消耗交流电能的设备或系统&#xff0c;在电力系统中&#xff0c;交流负载是不可或缺的一部分&#xff0c;它们将电能转化为其他形式的能量&#xff0c;以满足人们生产和生活的需求。交流负载的原理与应用涉及到许多方面&#xff0c;包括电气工程、电子技术、自…

RT_Thread_内核包版本与芯片包版本不一致的编译报错排查

按时间线写的&#xff0c;建议看完&#xff0c;因为中间有的步骤不必重蹈覆辙。 1、安装RT_Thread Studio、STM32F4的SDK&#xff0c;新建工程编译报错error: struct serial_configure has no member named flowcontrol 1.1、报错含义 结构体struct serial_configure没有flow…