JAVA之旅(六)——单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖


java也越来越深入了,大家加油吧!咱们一步步来

一.单例设计模式

  • 什么是设计模式?

    JAVA当中有23种设计模式,解决某一问题最有效的方法

  • 单例设计模式

    解决一个类在内存中只存在一个对象

想要保证对象唯一该怎么做》

  • 1.为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象
  • 2.还为了让其他程序访问到该类对象,只好在本类中自定义一个对象
  • 3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式

这三步怎么怎么实现呢?

  • 1.将构造函数私有化
  • 2.在类中创建一个本类对象
  • 3.提供一个方法可以获取到该对象

然后我们的代码就出来了

/**
 * 单例模式
 *
 * @author LGL
 *
 */
public class Single {

    // 将构造函数私有化
    private Single() {

    }

    // 在类中创建一个本类对象
    private static Single s = new Single();

    // 提供一个方法可以获取到该对象
    public static Single getInstance() {

        return s;
    }
}

当然,我们还有一种写法——懒汉式

/**
 * 单例模式
 * 懒汉式
 * @author LGL
 *
 */
public class Single {

    private static Single s = null;

    public Single() {
        // TODO Auto-generated constructor stub
    }

    public static Single getInstance() {
        if (s == null)
            s = new Single();

        return s;

    }
}

也有这么一种写法

/**
 * 单例模式
 * 饿汉式
 *
 * @author LGL
 *
 */
public class Single {

    private static Single s = new Single();

    public Single() {
        // TODO Auto-generated constructor stub
    }

    public static Single getInstance() {
        return s;

    }
}

单例模式的写法多种多样,只要掌握这个思想就可以了

饿汉式的特点:single类一进内存就已经创建好了对象

懒汉式的特点:对象是方法被调用时才初始化,也叫作对象的延迟加载

Single类进内存还没有存在,只有调用了getInstance()方法时才建立对象,这就叫做延迟加载

我们一般用饿汉式,因为他安全,简单

二.继承

面向对象的思想中的一个思想,继承,我们可以这样去理解,我们可以定义一个学生类,他有名字和年龄,还有一个学习的方法

/**
 * 学生
 * @author LGL
 *
 */
class Student {

    String name;

    int age;

    void study() {
        System.out.println("学习");
    }
}

然后我们可以再定义一个工人类


/**
 * 工人
 * @author LGL
 *
 */
class Worker {

    String name;

    int age;

    void work() {
        System.out.println("工作");
    }
}

他同样有名字和年龄还有一个工作的方法

这个时候我们可以发现,他们都存在相同的关系,他们都是人,人都具备年龄和姓名,所以我们可以将学生和工人的共性提取出来描述,只要让学生和工人与单独描述的类有关系就行,也就是继承

/**
 * 人
 *
 * @author LGL
 *
 */
class Person {
    String name;

    int age;
}

这个Person就叫做父类,超类,基类

然后我们的工人和学生就可以这样去写


/**
 * 学生
 *
 * @author LGL
 *
 */
class Student extends Person {

    void study() {
        System.out.println("学习");
    }
}

/**
 * 工人
 *
 * @author LGL
 *
 */
class Worker extends Person {

    void work() {
        System.out.println("工作");
    }
}

他们是Person的子类,继承是源于生活,所以工人不能继承学生,没有伦理性,千万不要为了获取其他类的功能,简化代码而继承,必须是类与类之间有所属关系才可以继承,is a 的关系

继承的优点

  • 1.提高代码的复用性
  • 2.让类与类之间产生关系,有了这层关系才有了多态的特性

JAVA语言中,java只支持单继承,不支持多继承

  • 为什么不能多继承?

    因为多继承容易带来安全隐患,当多个父类中定义了相同的功能,当功能内容不同时,子类对象不确定运行哪一个,但是JAVA保留了这种机制,并用另一种体现形式来表示,多实现。

JAVA支持多层继承,也就是一个继承体系

如何使用一个继承体系的功能?

  • 想要使用体系,先查阅体系中父类的描述,因为父类中定义的是该体系中的共性内容,通过了解共性功能就可以知道该体系的基本功能,那么,这么体系已经可以基本使用了。

  • 那么集体调用时,要创建最子类的对象,为什么?一是因为有可能父类不能创建对象,二是创建子类对象可能使用更多的功能,包括基本的也包括特有的

简单的说一句:查阅父类功能,创建子类对象使用功能

三.聚集关系

这个概念可能很多人不是很熟悉,确实我们实际开发当中很少提到,我们对象和对象之间,不光有继承关系,还有组合关系,

  • 聚合

    球员是球队中的一个,球队中有球员,这就是聚合关系

  • 组合

    手是人身体的一部分,腿是身体的一部分,这就是组合关系,你说这和聚合没什么不同,那你就错了,要知道,球队少了个球员没事,人少胳膊少腿就有事哦,所以组合关系更加紧密一点

都是吧对象撮合在一起,像我们继承是秉承一个is a的关系,而聚集是has a的关系,谁里面有谁

这个关系我们就不多做赘述了

我们关系讲完了,现在应该可以用代码去表示表示了,这里我就用当继承关系时,子类和父类之间的变量关系来举例

四.子父类变量关系

我们来探索一下子父类出现后,类成员的特点

    1. 变量
  • 2.函数
  • 3.构造函数

我们一步步来分析

1.变量

我们撸一串代码

//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        /**
         * 子父类出现后,类成员的特点
         */

        Zi z = new Zi();
        System.out.println("num1 = " + z.num1 + "\n" + "num2 = " + z.num2);
    }
}

/**
 * 父类
 *
 * @author LGL
 *
 */
class Fu {

    int num1 = 4;
}

/**
 * 子类
 *
 * @author LGL
 *
 */
class Zi extends Fu {

    int num2 = 5;

}

这样,是不是很容易知道输出的结果

但是我们那会这么简单,我们还有特殊情况

//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        /**
         * 子父类出现后,类成员的特点
         */

        Zi z = new Zi();
        System.out.println("num1 = " + z.num + "\n" + "num2 = " + z.num);
    }
}

/**
 * 父类
 *
 * @author LGL
 *
 */
class Fu {

    int num = 4;
}

/**
 * 子类
 *
 * @author LGL
 *
 */
class Zi extends Fu {

    int num = 5;

}

当子类和父类都有相同的变量的时候,现在该打印什么呢?

没错,打印了子类的值,为什么?因为输出的num前面其实默认带了一个this,如果我们要打印父类的值,需要加super,这是一个新的关键字了

void show(){
        System.out.println(super.num);
    }

结果显而易见了

所以变量的特点:如果子类中出现非私有的同名成员变量时,子类要访问本类中的成员变量,用this,子类访问父类中的同名变量,用super,this和super的使用几乎一致,this代表的是本类对象的引用,super代表父类对象的引用

不过我们也不会这么蛋疼在父类创建又在子类创建,我们来看第二个

2.函数

也就是方法,我们正常的应该是这样写的

//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        /**
         * 子父类出现后,类成员的特点
         */

        Zi z = new Zi();
        z.show1();
        z.show2();
    }
}

/**
 * 父类
 *
 * @author LGL
 *
 */
class Fu {
    void show1() {
        System.out.println("fu");
    }

}

/**
 * 子类
 *
 * @author LGL
 *
 */
class Zi extends Fu {

    void show2() {
        System.out.println("zi");
    }
}

这是很正常的实现

我们当然要说一种特殊情况,子父类方法同名我们该怎么办?我们运行一下

这是子运行了,这种情况叫做覆盖(重写),这个特性的特点

  • 当子类出现和父类一模一样的函数时,当子类对象被调用了该函数,会运行子类函数的内容,如同父类的函数被覆盖一样,这种情况就是覆盖了

当子类继承了父类,沿袭了父类的功能到子类中,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义并重写功能内容

  • 覆盖

    1.子类覆盖父类,必须保证子类权限大于等于父类权限才可以覆盖,否则编译失败

    2.静态只能覆盖静态(一般没人用)

  • 记住

    重载:只看同名函数的参数列表

    重写:字符类方法要一模一样 ,包括返回值类型

3.构造函数

最后一个特点了

//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        /**
         * 子父类出现后,类成员的特点
         */
        Zi z = new Zi();

    }
}

/**
 * 父类
 *
 * @author LGL
 *
 */
class Fu {
    public Fu() {
        System.out.println("fu");
    }
}

/**
 * 子类
 *
 * @author LGL
 *
 */
class Zi extends Fu {
    public Zi() {
        System.out.println("zi");
    }
}

我们现在运行一下

你会疑问,我明明实例化的是子类,怎么父类也实例化了,因为子类构造函数的第一行默认有一个方法

super();

在对子类对象进行初始化时,父类的构造函数也会执行,那就是因为子类的构造函数默认第一行有一条隐式的语句super();他会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super()

  • 为什么子类一定要访问父类中的构造函数?

    因为父类中的数据子类可以直接获取,所有子类建立对象的时候,需要先查看父类如何对这些数据进行初始化的,所有子类对这些对象初始化时,要先访问父类中的构造函数,如果要访问父类中指定的构造函数,可以手动定义super(xx,xx)的方式。

  • 注意

    super语句一定定义在子类构造函数的第一行

  • 结论:

    子类的所有的构造函数,默认都会访问父类中空参数的构造函数,因为子类每一个构造函数内的第一行都有一句隐式的super,当父类中没有空参数的构造函数时,子类必须手动通过super或者this语句的形式指定要访问父类中的构造函数

当然,子类的构造函数也可以指定this来访问本类中的构造函数,子类中至少会有一个构造函数会访问父类中的构造函数,这个结论就是子类的实例化过程,逐级向上查找

父类也向上查找,他找的是JAVA中所有类的老爹——Object

行,我们本篇幅就闲到这里吧,概念多了,反而难以消化,我们要一点点的来

如果有兴趣可以加群:555974449,这可能是迄今为止最和谐的IT群了

JAVA之旅(六)——单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖的更多相关文章

  1. JAVA笔记5__构造块、静态块/单例设计模式/继承/final关键字/super关键字

    public class Main { { //构造块(在构造对象时调用,先于构造方法执行) System.out.println("我是构造块!"); } static{ //静 ...

  2. Java面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式(饿汉式和懒汉式)?

    什么是单例设计模式? 单例设计模式就是一种控制实例化对象个数的设计模式. 为什么要使用单例设计模式? 使用单例设计模式可以节省内存空间,提高性能.因为很多情况下,有些类是不需要重复产生对象的. 如果重 ...

  3. Java中设计模式之单例设计模式-1

    单例作用 1 节省内存 2 可以避免多种状态导致状态冲突 单例的创建步骤 1 私有化构造方法 2 私有化声明的属性 3 getInstance 4 方法需要静态 单例分类 1.懒汉式 2.饿汉式 两种 ...

  4. java基础学习之单例设计模式学习

    最近狂补java基础的我重新学习了下单例,下面直接贴出代码,以作备忘 package com.darling.single; /** * 单例模式 * 单例即在内存中只存在该类的一个实例,要想实现这个 ...

  5. Java高频面试题--单例设计模式

  6. java设计模式之单例设计模式

    单例设计模式 保证一个类在使用过程中,只有一个实例.优势就是他的作用,这个类永远只有一个实例. 优势:这个类永远只有一个实例,占用内存少,有利于Java垃圾回收. 单例设计模式关键点 私有的构造方法. ...

  7. Java单例设计模式的实现

    1. 单例设计模式的定义 单例设计模式确保类只有一个实例对象,类本身负责创建自己的对象并向整个系统提供这个实例.在访问这个对象的时候,访问者可以直接获取到这个唯一对象而不必由访问者进行实例化. 单例设 ...

  8. 单例设计模式(Singleton)

    一.单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法) 例如:Hibernate的Se ...

  9. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

随机推荐

  1. 谈谈Circuit Breaker在.NET Core中的简单应用

    前言 由于微服务的盛行,不少公司都将原来细粒度比较大的服务拆分成多个小的服务,让每个小服务做好自己的事即可. 经过拆分之后,就避免不了服务之间的相互调用问题!如果调用没有处理好,就有可能造成整个系统的 ...

  2. Docker标准化开发测试和生产环境

    对于大部分企业来说,搭建 PaaS 既没有那个精力,也没那个必要,用 Docker 做个人的 sandbox 用处又小了点. 可以用 Docker 来标准化开发.测试.生产环境. Docker 占用资 ...

  3. JavaScript 注释

    JavaScript 注释可用于提高代码的可读性. JavaScript 注释 JavaScript 不会执行注释. 我们可以添加注释来对 JavaScript 进行解释,或者提高代码的可读性. 单行 ...

  4. Java9相关资料(JShell简易教程等)

    资源 Java9官网下载地址 Java9官方教程 JShell(Java Shell) 参考资料: JShell User Guide Java9先睹为快:JShell动手实践 以下大部分内容均来自该 ...

  5. 六星经典CSAPP-笔记(12)并发编程(上)

    六星经典CSAPP-笔记(12)并发编程(上) 1.并发(Concurrency) 我们经常在不知不觉间就说到或使用并发,但从未深入思考并发.我们经常能"遇见"并发,因为并发不仅仅 ...

  6. Linux 下的一个全新的性能测量和调式诊断工具 Systemtap,第 1 部分: kprobe

    kprobe 的原理.编程接口.局限性和使用注意事项 本系列文章详细地介绍了一个Linux下的全新的调式.诊断和性能测量工具Systemtap和它所依赖的基础kprobe以及促使开发该工具的先驱DTr ...

  7. Mongo DB 初识

    前言 2016年伊始,开始研究NoSql.看了couchdb,cloudant,cassandra,redis.却一直没有看过排行榜第一的mongo,实属不该.近期会花时间研究下mongo.本文是初识 ...

  8. Activtiy完全解析(一、Activity的创建过程)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/52452218 本文出自:[openXu的博客]   在Android开发过程中,我们几乎每天 ...

  9. 如何查看App provision profile文件中的钥匙链访问组名称

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们因为某些原因希望安全的在多个App中共享一些信息,我们可以 ...

  10. openfire环境搭建

    1.下载源代码:http://www.igniterealtime.org/downloads/source.jsp 2.把源代码解压出的openfire_src文件夹放至eclipse workpl ...