封装、继承、抽象类

news2024/10/11 4:10:42

面向对象共有三个特征:封装,继承,多态。

封装

封装表现:

(1)方法就是一个最基本封装体。

(2)类其实也是一个封装体。

封装的好处:

(1)提高了代码的复用性。

(2)隐藏了实现细节,还要对外提供可以访问的方式。便于调用者的使用。

(3)提高了安全性。

关键字 私有 private

public class Person {
    String name;
    void eat() {
        System.out.println(name + "在吃饭");
    }
}

public class Test {
    public static void main(String[] args) {
        //测试:Car类中的run方法。
        //1、创建 Person 类型的对象,并把该对象赋值给变量 person,或者说让变量 person 指向Person 类型的对象
        Person person1 = new Person();
        Person person2 = new Person();
        //2、通过已有的对象调用该对象的属性,对该对象的属性进行赋值或者赋值 对象.属性
        person1.name = "小明";
        person2.name = "小强";
        //3、通过已有的对象调用该对象的方法 对象.方法名(参数列表)
        person1.eat();
        person2.eat();
    }
}

        通过上述代码发现,虽然我们用Java的属性的行为可以任意访问和使用。

        可是怎么才能不让访问呢?需要使用一个Java中的关键字也是一个修饰符 private(私有,权限修饰符)。只要将Person的属性和行为私有起来,这样就无法直接访问。

public class Person {
    private String name;
    void eat() {
        System.out.println(name + "在吃饭");
    }
}

        这样虽然将人的名字私有了,但是这样就无法给 name 属性赋值了,所以还需要提供访问方式,只要对外提供可以访问的方法,让其他程序访问这些方法。

        一般对成员属性的访问动作:赋值(设置 set),取值(获取 get),因此对私有的变量访问的方式可以提供对应的 setXxx 或者 getXxx 的方法,如果方法私有的话,外部无法调用,只能通过 Person 类的公共方法(如 doing())间接调用。。

public class Person {
    private String name;

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

    public String getName() {
        return name;
    }

    private void eat() {
        System.out.println(name + "在吃饭");
    }

    public void doing(){
        eat();
    }

}


public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person();
        person1.setName("小明");
        person2.setName("小强");
        person1.doing();
        person2.doing();
    }
}

打印结果:

        这样同样实现了对属性的定义和方法的使用。

总结:

        类中不需要对外提供的内容都私有化,包括属性和方法。

         以后再描述事物,属性都私有化,并提供 setXxx 和 getXxx 方法对其进行访问。

注意:

        私有仅仅是封装的体现形式而已。

         private 它表示私有的,是一个权限修饰符。 用关键字private修饰成员变量的时候,可以将属性私有化,在其他类里面不能够直接访问属性,但 是在本类当中可以访问。

        以后类的成员变量都是用private修饰,只有想让成员变量能够被访问的时候它才能够被访问。

那是不是想让某个属性可以被访问就去掉该属性前面的关键字private?

        不是,我们可以提供专门的访问方式,对外提供可以方法方法,让其他类或者程序通过访问此方法去访问到属性。同时我们还可以在方法中对一些属性的数据进行验证。

如:

public class Person {
    private String name;

    public void setName(String name) {
        // 由于是设置成员变量的值,这里可以加入数据的验证
        if (name.length() < 2) {
            System.out.println("名字的长度不能小于2");
            this.name = "默认名";
            return;
        }
        this.name = name;
    }

    public String getName() {
        return name;
    }

    private void eat() {
        System.out.println(name + "在吃饭");
    }

    public void doing(){
        eat();
    }

}

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person();
        person1.setName("哼");
        person2.setName("小强");
        person1.doing();
        person2.doing();
    }
}

打印结果:

        这里就对人的名字属性做了校验,如果名字的长度小于2就给一个默认的名字并返回。

this关键字

        当在方法中出现了局部变量和成员变量同名的时候,那么在方法中怎么区别局部变量成员变量呢? 可以在成员变量名前面加上this.来区别成员变量和局部变量。

示例:

public class Person {
    private String name; //成员变量

    public void setName(String name) {
        this.name = name;
    }
    private void eat() {
        String name = "小明"; // 局部变量
        System.out.println(name + "在吃饭");   // 调用的局部变量
        System.out.println(this.name + "在吃饭"); // 调用的成员变量
    }

    public void doing(){
        eat();
    }

}


public class Test {
    public static void main(String[] args) {
        Person person= new Person();
        person.setName("小欣");
        person.doing();
    }
}

打印结果:

        this代表的是对象,方法当中的 this,谁去调用这个方法,this 就代表谁。当对象刚刚创建出来 的时候,this 就已经存在了。

成员变量和局部变量的区别:

1、定义的位置不同

        成员变量:定义在类中,但是定义在方法之外的变量,我们称之为成员变量;

        局部变量:定义在在类的方法中或者{}语句里面的的变量;

2、在内存中的位置不同

        成员变量:存储在堆内存的对象中的;

        局部变量:存储在栈内存的方法中;

3、初始化不同

        成员变量:因为存储在堆内存中,所以有一个默认的初始化值;

        局部变量:没有默认的初始化值,必须手动的进行赋值,然后才可以使用;

4、声明周期不同

        成员变量:随着对象的出现而出现在堆内存中,随着对象的消失而消失;

        局部变量:随着方法的运行而出现在栈内存中,随着方法执行结束而消失;

继承

继承的概念

        Java中类的继承,是指在现有类的基础上去构建声明一个全新的类,构建出来的新类我们称之为子类, 现有的类我们称之为父类,子类会自动拥有父类所有可继承的属性和方法,同时子类还可以拥有自己独有的属性和方法。

继承的格式 在写程序的时候,如果想声明一个类继承另一个类,需要使用extends关键字

class 子类 extends 父类{

}

继承的好处

(1)提高了代码的复用性,提高开发效率。

(2)继承让类与类之间产生了关系,为多态提供了前提。

继承的注意事项:

(1)Java 中类只支持单继承,不允许多继承,也就说一个类只能够有一个直接父类。

(2)多个类可以同时继承自同一个父类,一个父类允许有多个子类。

(3)继承可以是多层继承,也就是说一个类是其他类的子类的同时,又可以是另一个类的父类。

(4)在 Java 当中,子类和父类是一种相对的概念。

(5)所有的类都是间接或者直接继承自Object类,Object类称之为根类或者祖宗类。

子父类中成员的特点

子父类中成员变量的特点

(1)子父类中出现不同名的成员变量,这个时候访问没有任何问题。

(2)子父类中出现同名的成员变量的时候,在子类中直接访问成员变量,实际上访问的是子类的成员变 量而非父类的成员变量,如果想要在子类中访问父类的成员变量,必须使用关键字 superr,但是如果这个成员变量是私有的(private修饰的),即使使用了super关键字也不能够访 问。

示例:

public class Fu {
    String name = "爸爸"; //成员变量
}

public class Zi extends Fu{
    String name = "儿子"; //成员变量

    void speak(){
        System.out.println(super.name + "对" + name + "说");
    }
}

public class Test {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.speak();
    }
}

打印结果:

子父类中成员方法的特点

        当程序在子类中调用方法的时候,首先会在子类中查找有没有对应的方法,如果子类中存在这样的方法就执行子类中相应的方法,如果子类中不存在就会到父类中去查找,依次类推,如果父类中也不存在,则去父类的父类中查找。

        子父类中出现了相同的方法的时候,如果子类想要访问调用父类的方法的时候,就需要使用关键字 super。

示例:

public class Fu {
    void speak(){
        System.out.println("爸爸在说话");
    }
}

public class Zi extends Fu{

    void speak(){
        super.speak(); //调用父类中的 speak 方法
        System.out.println("儿子在说话");
    }
}

public class Test {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.speak();
    }
}

打印结果:

方法的重写(override)

        子父类中出现了一模一样的方法时(方法声明部分一模一样,但是方法体不一定一样),会出现覆盖操作,即子类的方法会把父类的方法覆盖掉,我们称之为重写、override、覆盖、复写。

示例:

public class Fu {
    void speak(){
        System.out.println("爸爸在说话");
    }
}

public class Zi extends Fu{

    void speak(){
        System.out.println("儿子在说话");
    }
}

public class Test {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.speak();
    }
}

打印结果:

方法重写的作用:

        当子类需要父类的功能,但是对于功能主体(方法体)子类又拥有自己独特的内容,如果子类直接继承父类的方法肯定不合适,这个时候我们可以把从父类那继承过来的方法的方法体部分进行重写,这 样子类既继承了父类的功能,但是又对该功能进行了独有的实现。

方法重写的注意点:

(1)子类重写父类的方法的时候,必须保证子类方法的权限大于等于父类方法的权限的。

(2)所谓的一模一样并不是单单指方法名一样,而是要求方法的返回值类型、方法名、参数列表都一模 一样。

方法重写和重载的区别?

(1)重载是指同一个类中的多个方法,而重写指的是拥有父子关系的不同类中的方法。

(2)重载指的是方法名相同,参数列表不同的多个方法,跟返回值类型无关。

(3)重写指的是子父类中除了方法体之外完全相同的两个方法(返回值类型、方法名、参数列表都要求 一样)。

抽象类

        有时候,某个父类只知道子类应该包含有哪些方法,但是无法确定子类是如何具体实现这些方法的。这个时候我们也可以向上抽取,但是只能够抽取方 法的声明,不能够抽取方法主体,这个时候会出现一种只有声明但是没有具体如何实现(方法体)的方法,这种方法就叫 抽象方法。

        抽象方法必须使用关键字 abstract修饰,同时定义了抽象方法的类变成了抽象类,该类也需要使用关 键字 abstract修饰;

抽象类&抽象方法的定义

//抽象类
修饰符 abstract class 类名{
    //抽象方法
    public abstract 返回值类型 方法名(参数列表);
}

抽象类的特点

(1)由于抽象方法所在的类必定是抽象类,抽象方法一定要定义在抽象类当中。

(2)抽象类中可以没有抽象方法。

(3)抽象类中既可以有抽象方法,也可以拥有非抽象方法。

(4)抽象类不能够直接创建对象。 原因:如果抽象类可以创建对象,那么就可以调用抽象方法,抽象方法没有方法体,调用没有任何意 义;

(5)一个类如果继承自抽象类,要么这个类本身就是一个抽象类,要么对抽象类里面所有的抽象方法进行重写。

抽象类一定是一个父类吗?为什么?

        抽象类一定是一个父类,因为它是通过不断抽取而来的;但是从语法角度讲,抽象类可以不是父类, 但是这样没有任何意义。

抽象类可以没有抽象方法,那么既然可以没有抽象方法,那么还把该类定义成抽象类还有意义么?         有意义的,我们可以让该类不能够直接创建对象,该类中定义的方法可以让该类的子类去使用;

抽象的关键字 abstract 不能够和哪些关键字共存?

(1)private:对于父类的私有方法,子类是无法继承得到并进行覆盖重写吗,如果abstract和private 一起使用修饰方法,如果abstract修饰的抽象方法需要子类去重写实现,但是private修饰的方法子类根本无法继承得到并重写,它们之间相同冲突矛盾;

(2)final:它表示最终的,也就是说被fianl修饰的方法不能够进行改变重写,跟abstract修饰的抽象方法需要子类去重 写实现相矛盾;

(3)static:被static修饰的方法属于类,如果在父类中有一个static修饰的方法,子类可以继承使用, 但是不能够进行重 写(因为该方法属于父类的),如果在子类中出现了一个跟父类一模一样的被static修饰的方法,那么子类中的方法 是属于子类,父类的方法属于父类,子类中的方法并不是对父类方法的重写;

        总结:静态方法能够被继承,但是不能被重写,跟abstract修饰的抽象方法需要子类去重写实现相矛盾。

final关键字的特点:

(1)final修饰类 被final修饰的类不可以被继承,即不能够派生子类,但是它可以继承自其他类(可以有父类);

(2)修饰方法 被final修饰的方法不能够被重写(覆盖、@Override),但是可以被继承;如果连继承都不想被继 承,我们可以使用关键字private修饰;

(3)修饰成员变量当创建完对象之后,我们不可以对final修饰的成员变量重写赋值;

(4)修饰局部变量 被final修饰的基本类型的变量(包括String类型),被称之为常量,因为这些变量只能够被赋值一 次,永远代表的是基本类型的数据或者String类型的某个字符串;被final修饰的引用类型的变量,它指向的是某个对象的地址,也就是说这个变量指向的地址不能够改变,即不能够再指向其他的对象,只能表示该地址对应的对象,但是虽然地址不能够 改变,但是地址对应的对象的本身的属性是可以改变的。

小案例:

(1)根据人类信息的描述,确定每个人都有名字、要进行工作。把这些共同的属性与工作抽取到父类中(人类),关于工作的内容由具体的人来进行指定,工作内容: 学生:xx正在写作业;老师:xx正在改作业;

(2)创建老师和学生对象,完成工作方法的调用;

示例:

定义人类(抽象类)

public abstract class Person {
    public String name;

    public String getName() {
        return name;
    }

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

    abstract void work();
}

定义老师类 Teacher 继承 人类 Person:

public  class Teacher extends Person {

    @Override
    void work() {
        System.out.println(getName() + "正在改作业");
    }
}

定义学生类 Student 继承 人类 Person:

public class Student extends Person{

    @Override
    void work() {
        System.out.println(getName() + "正在写作业");
    }
}

在测试类中,创建老师和学生对象,完成工作方法的调用:

public class Test {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        teacher.setName("张老师");
        Student student = new Student();
        student.setName("小明");
        teacher.work();
        student.work();
    }
}

打印结果:

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

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

相关文章

Jquery serialize()、serializeArray()、$.param()

param()方法 1.定义&#xff1a;param() 方法创建**数组或对象**的序列化表示。》》该序列化值可在进行 AJAX 请求时在 URL 查询字符串中使用。2.语法&#xff1a;$.param(object,trad)object&#xff1a;必需&#xff0c;规定要序列化的数组或对象。trad&#xff1a;可选。布尔…

如何提高LabVIEW编程效率

提高LabVIEW编程效率对开发者来说非常重要&#xff0c;尤其是在处理复杂项目或紧迫的开发周期时。以下是一些可以显著提升LabVIEW编程效率的技巧&#xff0c;从代码结构、工具使用到团队协作的多个角度进行详细分析&#xff1a; 1. 模块化设计 模块化设计 是提高代码可维护性和…

Linux——grep-wc-管道符

grep命令 利用关键字过滤文件行&#xff0c;找到关键字所在那一行 wc命令 统计文件行数&#xff0c;单词数量 wc命令 不带选项全选 wc -c test.txt 字节bytes数量 wc -m test.txt 字符数量 wc -l test-txt 行数 wc -w test-txt 单词数量 管道符 | 将左边命令的…

【LLM论文日更】| BGE-M3E embedding模型

论文&#xff1a;https://arxiv.org/pdf/2402.03216代码&#xff1a;GitHub - FlagOpen/FlagEmbedding: Retrieval and Retrieval-augmented LLMs机构&#xff1a;BAAI领域&#xff1a;embedding model发表&#xff1a; ​ 研究背景 研究问题&#xff1a;这篇文章要解决的问…

AI时代大厂AI项目管理学习路线

AI时代避免被裁员&#xff0c;大厂AI项目管理学习路线主要包括&#xff1a; 1、AI项目管理基础技能。 2、项目管理AI技术知识。 3、数据分析与决策。 4、AI项目管理工具。 5、AI项目管理知识扩展。 01 AI项目管理基础技能。 AI项目管理基础技能构成了项目管理的骨架&…

SQL 干货 | 使用 EXISTS 编写 SELECT 查询

基于 SQL 中的 EXISTS 运算符为我们提供了一种基于其他数据是否存在&#xff08;或不存在&#xff09;来检索数据的简便方法。更具体地说&#xff0c;它是一个逻辑运算符&#xff0c;用于评估子查询的结果&#xff0c;并返回一个布尔值&#xff0c;该值指示是否返回了行。尽管 …

《用comfyUI挑战全网AI图片产品实践案例》之comfyUI抠图工作流,用免费打败收费,实现素材自由

近段时间AI非常的火。目前有很多软件已经拥抱了AI&#xff0c;加入了AI的一些功能。像AI绘画的功能&#xff0c;基本上是每个大厂的软件产品都会配备。但是呢&#xff0c;这些功能都是要付费的。而且是按月收费或者是按年收费。整体算下来十分的不划算。所以我尝试用stable dif…

基础岛 第3关 :浦语提示词工程实践

作业 基础任务 (完成此任务即完成闯关) 背景问题&#xff1a;近期相关研究发现&#xff0c;LLM在对比浮点数字时表现不佳&#xff0c;经验证&#xff0c;internlm2-chat-1.8b (internlm2-chat-7b)也存在这一问题&#xff0c;例如认为13.8<13.11。 任务要求&#xff1a;利用…

嵌入式面试——FreeRTOS篇(五) 事件标志组

本篇为&#xff1a;FreeRTOS事件标志组篇 1、事件标志组介绍 答&#xff1a; 事件标志位&#xff1a;用一个位&#xff0c;来表示事件是否发生。 事件标志组是一组事件标志位的合集&#xff0c;可以简单的理解事件标志组&#xff0c;就是一个整数。 2、事件标志组的特点 答&am…

R包:APAlyzer从RNA-seq数据计算APA表达丰度

文章目录 介绍教程实战案例数据脚本运行 介绍 今天安利APAlyzer工具&#xff0c;它是通过RNA-seq数据获取3′UTR APA, intronic APA等表达谱的R包。 APAlyzer将bam文件比对到PolyA-DB数据库识别APA。 Most eukaryotic genes produce alternative polyadenylation (APA) isofo…

App推广新利器:Xinstall带你直达指定页面

在移动互联网时代&#xff0c;App的推广与运营对于企业的发展至关重要。然而&#xff0c;如何让用户在推广过程中更便捷地访问到App内的指定页面&#xff0c;一直是困扰开发者和运营者的难题。今天&#xff0c;我们就来介绍一款名为Xinstall的SDK&#xff0c;它能帮助你轻松实现…

Python中10个让你代码更安全的网络请求处理技巧

对Python感兴趣&#xff0c;想要有更深入了解的朋友可以试试我的这份学习方法和资料&#xff0c;​​​​​点这里免费获取 引言 在 Python 网络编程中&#xff0c;使用 requests 库进行 HTTP 请求是一种常见且高效的方式。该库不仅提供了简洁易用的 API&#xff0c;还支持多…

3分钟理清QPS、TPS、RT 以及它们之间的关系

在评估系统性能的时候&#xff0c;我们经常会听到 QPS、TPS、RT、吞吐量等等一些概念&#xff0c;包括在一些面试场景下可能也会遇到这些概念&#xff0c;我们来稍微梳理一下。 做一个简单的概念扫盲。 一 QPS QPS&#xff08;Queries Per Second&#xff09; 是每秒的查询率…

上市四天暴涨又暴跌,扫描全能王背后公司坐上“过山车”

股价四天涨五倍&#xff0c;遇到回调跌一半&#xff0c;扫描全能王母公司——合合信息&#xff0c;一上市就坐上了“过山车”。 合合信息其实早在2021年就向科创板申请上市&#xff0c;并在2023年成功过会&#xff0c;但直到9月13日才开启申购&#xff0c;IPO之路一走就是三年…

使用DBeaver(通用数据库管理工具)连接人大金仓数据库

下载安装DBeaver 下载地址&#xff1a; Download | DBeaver Community 官方甚至提供了&#xff08;解压即可用的&#xff09;免安装绿色版 3、下载人大金仓数据库的JDBC驱动 下载地址&#xff1a;电科金仓-成为世界卓越的数据库产品与服务提供商 数据库驱动管理 创建新驱动 配…

【Vue3 + TS + Vite】从0到1搭建项目框架

前言 没搭建过Vue3的项目&#xff0c;从0开始搭建一下&#xff0c;记录一下自己的步骤。 技术栈&#xff1a; vue3 ts scss pinia vite 我尽量写的详细一些&#xff0c;后续也会记录我在项目过程中&#xff0c;遇到的一些问题。 文章目录 前言环境搭建一、创建项目1. 使用…

JUC-线程池

阻塞队列 概述和架构 分类和核心方法 这里是在讲 为了区分在不同场景下 调用的不同组实现方法 核心方法演示 package com.example.juc.queue;import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Tim…

数据结构哈夫曼树-哈夫曼树代码构造实现(C语言)

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdlib.h> #include<stdio.h> #define N 30 //叶子结点的最大值 #define M 2*N-1 // 结点总数 typedef struct HTNode {int weight;int parent;int Lchild;int Rchild;int flag; }HTNode,HuffmanTree[M1];//Huffman…

2024年腾讯外包面试题(微创公司)

笔试&#xff1a; 1、判断异步执行顺序console.log(1);setTimeout(()>{Promise.resolve().then(()>{console.log(2);})console.log(3);},0);new Promise ((resolve)>{for(let i0; i<1000;i ){if(i1000){resolve();}}console.log(4);}).then(()>{console.log(5);…

不用PS!patchwork快速解决多子图组合问题~~

如果现在你还是将自己制作的图表放在PS或者PPT中进行随意组合的化&#xff0c;那么这篇文章你就得好好看看了&#xff0c;今天小编就给大家安利一个超强的突变自由组合包-patchwork&#xff0c;让你轻松实现多图的自由组合。 更多详细的数据可视化教程&#xff0c;可订阅我们的…