• 类与对象(中级)


    目录

    1. 包

    1.1 包的概念

    1.2 导入包中的类

    1.3 自定义包

    1.4 常见的包

    2. Java三大特性 --  封装

    3. Java三大特性 --  继承

     3.1 继承的概念:

    3.2 继承的语法

     3.3 父类成员访问

    3.3.1 子类中访问父类的成员变量

    3.3.2 子类中访问父类的成员方法

    4. super关键字

    4.1 子类构造方法

    4.2 super 和 this 的区别


    面向对象的编程共有的三大特征即封装,继承,多态。

    在了解封装之前先来了解一下包的概念。

    1. 包

    1.1 包的概念

    在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。有点类似于目录。比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件,也可以对某个文件夹下的音乐进行更详细的分类

    在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。

    1.2 导入包中的类

    Java 中已经提供了很多现成的类供我们使用. 例如Date类:可以使用 java.util.Date 导入 java.util 这个包中的 Date类:

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

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

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

    如果需要使用 java.util 中的其他类, 可以使用 import java.util.*
    但是一般不推荐这种写法,一整个 util 包中包涵了非常多的类太大。建议需要哪个类就是用哪个类。

    对于某些类而言,可能会有几个包中都有该类,但是该类在不同的包中的作用不同,我们需要正确的引用。

    1. import java.util.*;
    2. import java.sql.*;
    3. public class Test {
    4. public static void main(String[] args) {
    5. // util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
    6. Date date = new Date();
    7. System.out.println(date.getTime());
    8. }
    9. }

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

    1.3 自定义包

    基本语法: 例如: package com.csdn。

    package 是关键字,表示打包;后面的com.csdn 表示项目名称

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

    1.4 常见的包

    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. Java三大特性 --  封装

    面向对象程序三大特性:封装、继承、多态。这里主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节。

    介绍:封装(encapsulation)就是把抽象出来的数据(属性)和对数据的操作(方法)封装到一起,数据被保护在内部,程序的其他部分只有被授权的操作(方法),才可以对数据进行操作。

    理解与目的:

    1. 隐藏实现细节,也就是我们上一章说的,把大象装进冰箱有几步的问题;我们在装的不是不用注意细节,用的就是这个封装。

    2. 可以对数据进行验证,保证安全合理。及比如我们登入qq需要账号密码一般。

    实现细节:

    1. 将属性私有化:private(不能直接修改属性)。

    2. 提供一个公共的(public)set方法,用于对属性的赋值。

    3.  提供一个公共的(public)get方法,用于获取属性的值。

    例如:设计一个程序,不能随便查看人的年龄、工资,并且对年龄的进行合理的验证;年龄在1-100之前,有名字,name 在2 - 6 个字符之前。

    1. class Person {
    2. public String name;//名字公开
    3. private int age;//年龄和薪水私有化
    4. private double salary;
    5. public String getName() {
    6. return name;
    7. }
    8. public void setName(String name) {
    9. this.name = name;
    10. }
    11. public int getAge() {
    12. return age;
    13. }
    14. public void setAge(int age) {
    15. this.age = age;
    16. }
    17. public double getSalary() {
    18. return salary;
    19. }
    20. public void setSalary(double salary) {
    21. this.salary = salary;
    22. }
    23. @Override
    24. public String toString() {
    25. return "Person{" +
    26. "name='" + name + '\'' +
    27. ", age=" + age +
    28. ", salary=" + salary +
    29. '}';
    30. }
    31. }
    32. public class Main {
    33. public static void main(String[] args) {
    34. Person person = new Person();
    35. person.setName("jack");
    36. person.setAge(6);
    37. person.setSalary(6000.0);
    38. System.out.println(person.toString());
    39. }

    我们只有通过暴露出的公开方法才可以进行访问,不然直接的.age就会出错。

     如果想要对年龄进行验证只需要加个判断条件。

    3. Java三大特性 --  继承

     3.1 继承的概念:

    继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。

    例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用。
    图示:

     上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类或超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。
    从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态(后序讲)。

    3.2 继承的语法

    在Java中如果要表示类之间的继承关系,需要借助extends关键字,具体如下:

    修饰符 class 子类 extends 父类 {
    // ...
    }

    原理图:

     3.3 父类成员访问

    在继承体系中,子类将父类中的方法和字段继承下来了,那在子类中能否直接访问父类中继承下来的成员呢?

    3.3.1 子类中访问父类的成员变量

    1. 当子类和父类不存在同名成员变量

    1. public class Base {
    2. int a;
    3. int b;
    4. }
    5. public class Derived extends Base{
    6. int c;
    7. public void method(){
    8. a = 10; // 访问从父类中继承下来的a
    9. b = 20; // 访问从父类中继承下来的b
    10. c = 30; // 访问子类自己的c
    11. }
    12. }

    2. 子类和父类成员变量同名

    1. public class Base {
    2. int a;
    3. int b;
    4. int c;
    5. }
    6. public class Derived extends Base{
    7. int a; // 与父类中成员a同名,且类型相同
    8. char b; // 与父类中成员b同名,但类型不同
    9. public void method(){
    10. a = 100; // 访问父类继承的a,还是子类自己新增的a?
    11. b = 101; // 访问父类继承的b,还是子类自己新增的b?
    12. c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
    13. // d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
    14. }
    15. }

    在子类方法中 或者 通过子类对象访问成员时:
    如果访问的成员变量子类中有,优先访问自己的成员变量。
    如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
    如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
    成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找

    3.3.2 子类中访问父类的成员方法

    1 成员方法名字不同

    1. class Base {
    2. public void methodA(){
    3. System.out.println("Base中的methodA()");
    4. }
    5. }
    6. public class Derived extends Base{
    7. public void methodB(){
    8. System.out.println("Derived中的methodB()方法");
    9. }
    10. public void methodC(){
    11. methodB(); // 访问子类自己的methodB()
    12. methodA(); // 访问父类继承的methodA()
    13. // methodD(); // 编译失败,在整个继承体系中没有发现方法methodD()
    14. }
    15. }

    总结:成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。

    2. 成员方法名字相同

    1. class Base {
    2. public void methodA(){
    3. System.out.println("Base中的methodA()");
    4. }
    5. public void methodB(){
    6. System.out.println("Base中的methodB()");
    7. }
    8. }
    9. public class Derived extends Base{
    10. public void methodA(int a) {
    11. System.out.println("Derived中的method(int)方法");
    12. }
    13. public void methodB(){
    14. System.out.println("Derived中的methodB()方法");
    15. }
    16. public void methodC(){
    17. methodA(); // 没有传参,访问父类中的methodA()
    18. methodA(20); // 传递int参数,访问子类中的methodA(int)
    19. methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),基类的无法访问到
    20. }
    21. }

    【说明】
    通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
    通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;

    4. super关键字

    基本介绍:super代表父类的引用,用于访问父类的属性、方法、构造器。

    super可以访问父类的属性和方法,但是有权限要求,由private修饰的不可以访问。

    4.1 子类构造方法

    父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。

    看例题:

    1. class Base {
    2. public Base(){
    3. System.out.println("Base()");
    4. }
    5. }
    6. public class Derived extends Base{
    7. public Derived(){
    8. // super(); // 注意子类构造方法中默认会调用基类的无参构造方法:super(),
    9. // 用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,
    10. // 并且只能出现一次
    11. System.out.println("Derived()");
    12. }
    13. }
    14. class Test {
    15. public static void main(String[] args) {
    16. Derived d = new Derived();
    17. }
    18. }

    在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整

    使用细节总结:

    1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构
    造方法
    2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的
    父类构造方法调用,否则编译失败。
    3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。
    4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现

    4.2 super 和 this 的区别

    【相同点】
    1. 都是Java中的关键字
    2. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
    3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
    【不同点】

    1. 访问属性

    this访问本类的属性,如果本类没有此属性,再去父类中继续查找;super直接访问父类的属性。

    2. 调用方法

    this访问本类的方法,如果本类没有此方法,再去父类中继续查找;super直接访问父类的方法。

    3. 调用构造器

    this调用本类构造器;super调用父类构造器

    4. 表示对象

    this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用。

    5. 默认调用

    构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有

  • 相关阅读:
    fmx 边框设计
    wpf prism左侧抽屉式菜单
    华为路由器交换机DHCP配置实例(二层、三层交换机)
    全球领先飞瞳引擎™云服务全球两千+企业用户,集装箱识别集装箱箱况残损检测,正常箱号识别率99.98%以上,箱信息识别及铅封识别免费
    一点点安全资料:网络安全扩展
    argparse.ArgumentParser() 用法解析
    [Vue] 自定义命令
    RabbitMQ实现延迟消息的方式-死信队列、延迟队列和惰性队列
    QTableWidget 的使用
    结构体 2.招聘
  • 原文地址:https://blog.csdn.net/weixin_67807492/article/details/127788442