面向对象编程·上

news2025/1/12 12:19:36

面向对象编程·上

  • 1.包
    • 1.1导入包中的类
    • 1.2静态导入
    • 1.3将类放到包中
    • 1.4包的访问权限控制 - [只能在当前包当中使用]
    • 1.5常见的系统包
  • 2.继承
    • 2.1背景
    • 2.2语法规则
      • 2.2.1super[不能出现在静态方法当中]作用总结 父类对象的引用
    • 2.3protected 关键字
    • 2.4更复杂的继承关系
    • 2.5final 关键字
    • 2.6组合
  • ⭐小提问⭐

大家好,我是晓星航。今天为大家带来的是面向对象编程相关的讲解!😀

1.包

包 (package) 是组织类的一种方式.

使用包的主要目的是保证类的唯一性.

例如, 你在代码中写了一个 Test 类. 然后你的同事也可能写一个 Test 类. 如果出现两个同名的类, 就会冲突, 导致代码不能编译通过.

1.1导入包中的类

Java 中已经提供了很多现成的类供我们使用. 例如:

public class Test {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();
        // 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
    }
}

可以使用 java.util.Date 这种方式引入 java.util 这个包中的 Date 类.

但是这种写法比较麻烦一些, 可以使用 import 语句导入包.

import java.util.Date;
    public class Test {
        public static void main(String[] args) {
            Date date = new Date();
            // 得到一个毫秒级别的时间戳
            System.out.println(date.getTime());
        }
    }

如果需要使用 java.util 中的其他类, 可以使用 import java.util.*

import java.util.*;
    public class Test {
        public static void main(String[] args) {
            Date date = new Date();
            // 得到一个毫秒级别的时间戳
            System.out.println(date.getTime());
        }
    }

提问:util地下有很多的类。难道一下子全部导入了吗?

答:不是的。Java处理的时候,需要谁,他才会拿谁。C语言里面,通过include关键字,导入之后,就会把这个头文件的内容全部拿过来。

但是我们更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况.

import java.util.*;
import java.sql.*;
    public class Test {
        public static void main(String[] args) {
            // util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
            Date date = new Date();
            System.out.println(date.getTime());
        }
    }
// 编译出错
//Error:(5, 9) java: 对Date的引用不明确
//java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配

在这种情况下需要使用完整的类名

import java.util.*;
import java.sql.*;
    public class Test {
        public static void main(String[] args) {
            java.util.Date date = new java.util.Date();
            System.out.println(date.getTime());
        }
    }

注意事项: import 和 C++ 的 #include 差别很大. C++ 必须 #include 来引入其他文件内容, 但是 Java 不需要.import 只是为了写代码的时候更方便. import 更类似于 C++ 的 namespaceusing

1.2静态导入

使用 import static 可以导入包中的静态的方法和字段.

import static java.lang.System.*;
public class Test {
    public static void main(String[] args) {
        out.println("hello");
    }
}

使用这种方式可以更方便的写一些代码, 例如

import static java.lang.Math.*;
    public class Test {
        public static void main(String[] args) {
            double x = 30;
            double y = 40;
            // 静态导入的方式写起来更方便一些. 
            // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
            double result = sqrt(pow(x, 2) + pow(y, 2));
            System.out.println(result);
        }
    }

虽然写法很简便,但是在日常工作中我们不提倡使用它。

1.3将类放到包中

基本规则:

  • 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
  • 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.bit.demo1 ).
  • 包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储代码.
  • 如果一个类没有 package 语句, 则该类被放到一个默认包中.

操作步骤1)

  1. 在 IDEA 中先新建一个包(软件包): 右键 src -> 新建 -> 包
  1. 在弹出的对话框中输入包名, 例如 com.bit.demo1
  1. 在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名即可.
  1. 此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了
  1. 同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句

1.4包的访问权限控制 - [只能在当前包当中使用]

我们已经了解了类中的 public 和 private. private 中的成员只能被类的内部使用.

如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外部的类使用.

下面的代码给了一个示例. Demo1 和 Demo2 是同一个包中, Test 是其他包中.

Demo1.java

package com.bit.demo;
public class Demo1 {
    int value = 0;
}

Demo2.java

package com.bit.demo;
    public class Demo2 {
        public static void Main(String[] args) {
            Demo1 demo = new Demo1();
            System.out.println(demo.value);
        }
    }
// 执行结果, 能够访问到 value 变量
//10

Test.java

import com.bit.demo.Demo1;
    public class Test {
        public static void main(String[] args) {
            Demo1 demo = new Demo1();
            System.out.println(demo.value);
        }
    }
// 编译出错
//Error:(6, 32) java: value在com.bit.demo.Demo1中不是公共的; 无法从外部程序包中对其进行访问

如果val没有加权限 那么它的权限默认是 包访问权限

1.5常见的系统包

  1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2. java.lang.reflect:java 反射编程包;
  3. java.net:进行网络编程开发包。
  4. java.sql:进行数据库开发的支持包。
  5. java.util:是java提供的工具程序包。(集合类等) 非常重要
  6. java.io:I/O编程开发包。

2.继承

意义:可以对代码进行重用,大大的减少了代码量

2.1背景

代码中创建的类, 主要是为了抽象现实中的一些事物(包含属性和方法).

有的时候客观事物之间就存在一些关联关系, 那么在表示成类和对象的时候也会存在一定的关联.

例如, 设计一个类表示动物

注意, 我们可以给每个类创建一个单独的 java 文件. 类名必须和 .java 文件名匹配(大小写敏感).

// Animal.java 
        public class Animal {
            public String name;

            public Animal(String name) {
                this.name = name;
            }

            public void eat(String food) {
                System.out.println(this.name + "正在吃" + food);
            }
        }
// Cat.java 
        class Cat {
            public String name;

            public Cat(String name) {
                this.name = name;
            }

            public void eat(String food) {
                System.out.println(this.name + "正在吃" + food);
            }
        }
// Bird.java 
        class Bird {
            public String name;

            public Bird(String name) {
                this.name = name;
            }

            public void eat(String food) {
                System.out.println(this.name + "正在吃" + food);
            }

            public void fly() {
                System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
            }
}

这个代码我们发现其中存在了大量的冗余代码.

仔细分析, 我们发现AnimalCat以及 Bird 这几个类中存在一定的关联关系:

  • 这三个类都具备一个相同的 eat 方法, 而且行为是完全一样的.
  • 这三个类都具备一个相同的 name 属性, 而且意义是完全一样的.
  • 从逻辑上讲, Cat 和 Bird 都是一种 Animal (is - a 语义).

此时我们就可以让 Cat 和 Bird 分别继承 Animal 类, 来达到代码重用的效果.

此时, Animal 这样被继承的类, 我们称为 父类 , 基类超类, 对于像 Cat 和 Bird 这样的类, 我们称为 子类, 派生类和现实中的儿子继承父亲的财产类似, 子类也会继承父类的字段和方法, 以达到代码重用的效果.

2.2语法规则

基本语法

class 子类 extends 父类 {

}
  • 使用 extends 指定父类.
  • Java 中一个子类只能继承一个父类 (而C++/Python等语言支持多继承).
  • 子类会继承父类的所有 public 的字段和方法.
  • 对于父类的 private 的字段和方法, 子类中是无法访问的.
  • 子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用.

对于上面的代码, 可以使用继承进行改进. 此时我们让 Cat 和 Bird 继承自 Animal 类, 那么 Cat 在定义的时候就不必再写 name 字段和 eat 方法.

class Animal {
    public String name;
    public Animal(String name) {
        this.name = name;
    }
    public void eat(String food) {
        System.out.println(this.name + "正在吃" + food);
    }
}
class Cat extends Animal {
    public Cat(String name) {
        // 使用 super 调用父类的构造方法.
        super(name);
    }
}
class Bird extends Animal {
    public Bird(String name) {super(name);
    }
    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat("小黑");
        cat.eat("猫粮");
        Bird bird = new Bird("圆圆");
        bird.fly();
    }
}

extends 英文原意指 “扩展”. 而我们所写的类的继承, 也可以理解成基于父类进行代码上的 “扩展”.

例如我们写的 Bird 类, 就是在 Animal 的基础上扩展出了 fly 方法.

如果我们把 name 改成 private, 那么此时子类就不能访问了.

class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
// 编译出错
//Error:(19, 32) java: name 在 Animal 中是 private 访问控制

父类构造的同时,也要帮助子类来进行构造。(用super来构造子类的方法)

子类构造前(报错):

子类构造后(不报错):

因此在父类使用构造方法时,也要帮助子类一起使用构造方法

当子类和父类都有自己的name使用父类时,我们会优先使用子类自己的name。

eg:子类name:hehe。父类name:没赋值(null)。

打印输出结果:null;

基本格式为:

public 类名(参数即类型,参数即类型) {
    super(参数,参数);
}

2.2.1super[不能出现在静态方法当中]作用总结 父类对象的引用

1、super();//调用父类的构造方法

2、super.func();

3、super.data;

注:super只能在当前类的构造方法中出现(出现在其他地方会报错),而且必须放在第一行。

2.3protected 关键字

刚才我们发现, 如果把字段设为 private, 子类不能访问. 但是设成 public, 又违背了我们 “封装” 的初衷.

两全其美的办法就是 protected 关键字.

  • 对于类的调用者来说, protected 修饰的字段和方法是不能访问的
  • 对于类的 子类同一个包的其他类 来说, protected 修饰的字段和方法是可以访问的
// Animal.java
public class Animal {
    protected String name;
    public Animal(String name) { this.name = name;
    }
    public void eat(String food) {
        System.out.println(this.name + "正在吃" + food);
    }
}
// Bird.java 
public class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void fly() {
        // 对于父类的 protected 字段, 子类可以正确访问
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
// Test.java 和 Animal.java 不在同一个 包 之中了. 
public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal("小动物");
        System.out.println(animal.name); // 此时编译出错, 无法访问 name 
    }
}

小结: Java 中对于字段和方法共有四种访问权限

  • private: 类内部能访问, 类外部不能访问
  • 默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.
  • protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.
  • public : 类内部和类的调用者都能访问

什么时候下用哪一种呢?

我们希望类要尽量做到 “封装”, 即隐藏内部实现细节, 只暴露出 必要 的信息给类的调用者.

因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限. 例如如果一个方法能用 private, 就尽量不要用public.

另外, 还有一种 简单粗暴 的做法: 将所有的字段设为 private, 将所有的方法设为 public. 不过这种方式属于是对访问权限的滥用, 还是更希望同学们能写代码的时候认真思考, 该类提供的字段方法到底给 “谁” 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用).

2.4更复杂的继承关系

刚才我们的例子中, 只涉及到 Animal, Cat 和 Bird 三种类. 但是如果情况更复杂一些呢?

针对 Cat 这种情况, 我们可能还需要表示更多种类的猫~

这个时候使用继承方式来表示, 就会涉及到更复杂的体系.

// Animal.java 
public Animal { 
 ...
        }
// Cat.java 
        public Cat extends Animal { 
 ...
        }
// ChineseGardenCat.java 
        public ChineseGardenCat extends Cat { 
 ...
        }
// OrangeCat.java 
        public Orange extends ChineseGardenCat { 
 ...
        } 
......

如刚才这样的继承方式称为多层继承, 即子类还可以进一步的再派生出新的子类.

时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会更加复杂.

但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.

如果想从语法上进行限制继承, 就可以使用 final 关键字

2.5final 关键字

曾经我们学习过 final 关键字, 修饰一个变量或者字段的时候, 表示 常量 (不能修改).

final int a = 10;
a = 20; // 编译出错

final 关键字也能修饰类, 此时表示被修饰的类就不能被继承.

final public class Animal { 
     ...
}
public class Bird extends Animal { 
     ...
}
// 编译出错
//Error:(3, 27) java: 无法从最终com.bit.Animal进行继承

final 关键字的功能是 限制 类被继承

“限制” 这件事情意味着 “不灵活”. 在编程中, 灵活往往不见得是一件好事. 灵活可能意味着更容易出错.

是用 final 修饰的类被继承的时候, 就会编译报错, 此时就可以提示我们这样的继承是有悖这个类设计的初衷的.

我们平时是用的 String 字符串类, 就是用 final 修饰的, 不能被继承.

2.6组合

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果.

例如表示一个学校:

public class Student { 
    ...
}
public class Teacher { 
    ...
}
public class School {
    public Student[] students;
    public Teacher[] teachers;
}

组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段.这是我们设计类的一种常用方式之一.

组合表示 has - a 语义

在刚才的例子中, 我们可以理解成一个学校中 “包含” 若干学生和教师.

继承表示 is - a 语义

在上面的 “动物和猫” 的例子中, 我们可以理解成一只猫也 “是” 一种动物

⭐小提问⭐

下面我们为大家准备了一些问题为了使大家更好地理解我们的包和继承相关的知识,希望大家先自习思考然后再去搜寻答案,下一篇文章我们为大家一一解答这些小问题!!!😆

1.查import和package的区别(通过import导包)

答:

2.查两个相同的类名 怎么导入不报错?

答:

3.问一下两个是不是文件夹?

答:

4.重写和重载的区别?

答:

5.this 和 super 以及this. 和 super.的区别?

答:

至此我们面向对象编程的(上)便全部讲解完毕了,如果有疑惑一定一定要在评论区和作者积极探讨哦!🧐

感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘

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

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

相关文章

电容笔和触控笔有什么区别?值得入手电容笔品牌推荐

电容笔与传统的触控笔最大的不同之处是,电容笔具有良好的防误触和倾斜压感,能有效地降低书写过程中的麻烦。如果我们想要 IPAD和电容笔一起很好地使用,而且我们就没有过多的预算的话。那么,这款平替电容笔,就是最好的选…

看懂这篇文章-你就懂了数据库死锁产生的场景和解决方法

一、什么是死锁 加锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。任何事务都需要获得相应对象上的锁才能访问数据,读取数据的事务通常只需要获得读锁(共享锁),修改数据的事务需要获得…

京东神灯文档:JVM参数GC线程数ParallelGCThreads合理性设置

目录 1. ParallelGCThreads参数含义 2. ParallelGCThreads参数设置 3. ParallelGCThreads参数实验 4. ParallelGCThreads扫描结果 5. ParallelGCThreads修改建议 1. ParallelGCThreads参数含义 在讲这个参数之前,先谈谈JVM垃圾回收(GC)算法的两个优化标的&…

ERP (SAP) Integrator Delphi Edition

ERP (SAP) Integrator Delphi Edition ERP(SAP)Integrator支持RFC和SAP服务,并允许开发人员轻松编写桌面、服务器和移动应用程序。它提供了一种连接到SAP R/3和NetWeaver系统的简单方法,并使应用程序能够进行远程功能调用,以便向这些远程功能…

SQL Server 卸载和安装

在莫不知名链接下载sql失败了,然就几天变化,让我从sql Server2019到2022了, 首先讲一下卸载吧,很简单一共就5步, 先停止服务,有关sql server的相关服务全部停止,再进入控制面板 > 卸载程序…

解决:Uncaught (in promise) TypeError: Failed to fetch 的问题

1、问题展示: 其一、报错的代码信息为: Access to fetch at .......... from origin ................. has been blocked by CORS policy: Response to preflight request doesnt pass access control check: Redirect is not allowed for a preflight…

HashSet和HashMap

目录 一、HashSet 1、HashSet简单介绍 2、HashSet的常用方法 3、HashSet保证元素不重复的原理 二、HashMap 1、HashMap简单介绍 2、HashMet的常用方法 3、使用LinkedHashMap集合保证元素添加顺序 三、HashSet和HashMap的区别和联系 1、区别 2、联系 一、HashSet 1、Has…

Web3 入门教程 1 —— 认知篇

如果你也喜欢Web3,希望在这做些有趣的、有意义的事情,那么我希望这篇文章可以帮助到你。 其实在很早之前,我就计划写一篇《Web3 新手教程》,送给想要进入 Web3 或者刚刚进入 Web3 的小伙伴,但是考虑到两点原因&#xf…

力扣 53. 最大子数组和 --- C语言求解

题目描述: 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。 题解: 此题可以用动态规划和分治法。 方法1. 动态…

《深度学习进阶 自然语言处理》第七章:seq2seq介绍

文章目录7.1 seq2seq模型介绍7.1.1 seq2seq的原理7.1.2 时序数据转换简单举例7.2 seq2seq模型实现7.3 seq2seq模型改进7.3.1 反转输入数据(Reverse)7.3.2 偷窥(Peeky)7.4 seq2seq模型的应用7.5 总结之前文章链接: 开篇介绍:《深度学习进阶 自然语言处理…

MySQL Hash Join前世今生

GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:nw MySQL Hash Join前世今生 因工作需要,对MySQL Hash Join的内部实现做了一些探索和实践&#x…

【Hack The Box】linux练习-- Mango

HTB 学习笔记 【Hack The Box】linux练习-- Mango 🔥系列专栏:Hack The Box 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📆首发时间:🌴2022年11月17日🌴 &#x1f36…

01 基于yum方式部署Kubernetes集群

文章目录1.实验环境准备2.部署单节点的etcd1.在192.168.221.133节点安装etcd服务2.修改etcd的配置文件3.启动etcd并设置开机自启动4.检查集群的健康状态5.操作etcd服务3. master 组件部署1.在192.168.221.133节点安装master服务2.配置apiserver组件3.配置master的组件4.启动服务…

m基于MIMO中继通信和非规则LDPC编译码的matlab仿真,其中波束形成为SVD,MMSE,中继包括AF,DF,CF

目录 1.算法概述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法概述 即在非规则LDPC下,且源节点1个,中继一个,目标节点一个,天线也是1的情况对比三种中继协作协议的误码率。 做非规则LDPC码的以编码协作形…

computed计算方法不被调用的原因;只有在使用时才会被调用

目录 一、问题 二、解决方法 三、总结 一、问题 1.需求:根据组件外部一个变量的值来确定 组件内部的操作。组件外部可以更改filetime的值,filetime有值时这个界面可以操作,否则不可以操作。 我一想 用computed就可以了呀,动态…

Rockwell EDI 850 采购订单报文详解

罗克韦尔(Rockwell)自动化(中国)有限公司(NYSE: ROK)是全球最大的致力于工业自动化与信息化的公司,致力于帮助客户提高生产力,以及世界可持续发展。罗克韦尔自动化总部位于美国威斯康星州密尔沃基市,在全球80多个国家设…

超级明星们的人物化身 NFT 将来到 The Sandbox 元宇宙

超级明星队 NFT 将在 The Sandbox 的全球运动村体验中亮相! ​ The Sandbox 与 Web3 公司 Forj 达成合作,还获得了独特的 BAYC 无聊猿人物化身的授权。 NFTSTAR 在 The Sandbox 建造了新的体验,巴西足球明星内马尔(Neymar JR.&am…

高项 质量管理论文

三个过程 项目质量管理包括执行组织确定质量政策、目标与职责的各过程和活动,从而使项目满足其预定的需求。项目质量管理在项目环境内使用政策和程序,实施组织的质量管理体系;并以执行组织的名义,适当支持持续的过程改进活动。项目…

【408专项篇】C语言笔记-第五章(一维数组与字符数组)

第五章:一维数组与字符数组 第一节:一维数组 1. 数组的定义 C语言提供的数组,通过一个符号来访问多个元素。 特点: 具有相同的数据类型。使用过程中需要保留原始数据。 数组是构造数据类型。所谓数组,是指一组具…

深入理解Python生成器和yield

深入理解Python生成器和yield 我在《Python性能优化指南–让你的Python代码快x3倍的秘诀》中有提到,在处理大文件或大数据集时用生成器可以提高性能。很多朋友会问:“为什么用生成器就能提升性能呢?”。今天,我就带大家深入看一…