欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java基础知识(八)单例设计模式&继承和覆盖&super、this、final

程序员文章站 2022-06-17 18:02:44
...

分析一下主函数中Person p = new Person("zhangsan,20");执行时的执行顺序和内存使用情况。

Java基础知识(八)单例设计模式&继承和覆盖&super、this、final

1、先找到Person.class文件调入内存,先执行静态代码块(如果有)为类初始化。

2、在new Person("zhangsan,20");执行时,在堆内存建立对象,在栈内存开空间给主函数的变量p。

3、name和age属性先赋默认值。

4、这里由于name没有赋初值(有的话先执行,称为显式初始化)所以执行构造代码块给这个对象初始化所有对象公有的内容。

5、执行构造函数,给这个对象具体的初始化。

6、把对象在堆内存中的地址赋给栈内存中的p。

小注意点:非静态前边省略的是this.  而静态前面省略的是类名.    静态中不出现this

Java基础知识(八)单例设计模式&继承和覆盖&super、this、final

有一本书叫《设计模式》去看看。

设计模式:解决某一类问题总结出的行之有效的方法。java共23种设计模式。

单例设计模式:解决在一个类中只存在一个对象的问题。

1、为了保证只有一个对象,禁止外类创建对象 (把构造函数私有)

2、外类无法创建对象,只能在本类中创建一个对象(私有一个静态对象)

3、为了把本类中创建的对象提供给外界,提供一个接口。(写一个get 方法return这个对象)

//需要使用单例时,将下面三步加上即可。
//写法一:(称为  饿汉式)

class Single
{
    private static Single a = new Single();   // 别忘记static 因为下面get方法是static 
    
    private Single(){}

    public static Single getInstence()   //static方法只能访问静态成员,加它是为了可以用类名调用
    {
        return a;
    }
}


//写法二:对象的延时加载(称为 懒汉式)
class Single
{
    private static Single s= null;
    private Single(){}
    public static synchronized Single getInstence() //synchronized:每次只允许一个程序进入
    {
        if(s==null)
        {
            s=new Single();
            return s;
        }
    }
}

 

 

继承:提高代码复用性。让类与类之间有了一种关系,这个关系是多态的前提。还可以用于代码日后扩展。

注意:千万不要为了获取其它类的功能,简化代码而继承。必须是类与类之间有所属关系才可以继承。

java只支持单继承不支持多继承。多继承有安全隐患:当父类中定义了相同的方法,但方法内容不同时,不知该用哪个。

java支持多层继承。C继承B,B继承A是可以的。C可以用A中的东西。

使用:查阅父类功能,创建子类的对象。

除了继承关系还有几种关系:

继承:谁是谁的一种。

聚集:谁里边有谁。

聚合:事物联系紧密。

组合:紧密程度稍小。

父类对象的引用,用super。本类对象的引用 ,用this。

当运行子类时,首先加载到堆内存的是父类的class文件,父里面的东西无论子能不能用都会放在堆里子对象中。

子类要访问本类中成员变量时用this,要访问父类成员时用super。

父类对象可以指向子类对象。

当父类和子类的方法定义上一样时(名、参数、修饰词一样,内容不一样),子类调用的是自己的方法,称为重写或覆盖。父类的方法还是在子类对象中但是,没被调用。

当子类中写的方法和父类中的功能相似时,没必要重新定义一个方法,而是要重写父类中的方法将父类方法覆盖掉。

注意:子类方法覆盖父类方法必须权限大于等于父类。 静态只能覆盖静态。

修改原有代码一定是灾难。不要去改原码。

class Tel
{
    void show()
    {
        System.out.println("number");
    }
}

class NewTel extends Tel
{
    void show()
    {
        super.show();
        System.out.println("name");
    }
}

重载:名字相同列表不同。

重写/覆盖:子父类方法必须一模一样

 

子父类中的构造函数。

子类每个构造函数第一行默认(隐式)都是super();子类运行构造函数时先运行super();

先调用父类构造函数中参数为空的那个构造函数。

为什么子类一定要先访问父类的空构造函数呢?

因为父类中的数据子类可以直接获取,所以子类对象在建立时需要查看父类是如何对这些数据初始化的,所以子类在初始化对象的时候先访问父类的构造函数。如果要访问父类中某个指定的构造函数需要手动指定。

super();语句只能定义在构造函数第一行。this语句也只能定义在构造函数第一行。因为初始化动作要先做。拿到父类中数据后得看看父类对其初始化做了什么事。

构造函数中要么有super()要么有this();

子类中至少有一个构造函数去访问父类,至少一个。

子类的所有的构造函数默认都会访问父类中空参数构造函数,因为每一个子类的构造函数第一行都有一句隐式的super()。当父类中没有空参数的构造函数时,子类必须手动通过super和this()语句的形式指定要访问的父类构造函数。当然,子类构造函数第一行也可以手动通过this ()语句访问本类的构造函数。

以上就是子类的实例化过程。

所有父类的总父类是object,所有类都继承于它。

 

final关键字:

1、被final修饰的类不可以被继承。继承的弊端是打破了封装性。

2、被final修饰的方法不能被覆盖。为了避免被子类覆盖,用final修饰。

3、被final修饰的变量只能赋值一次,既可以修饰成员变量也可以修饰局部变量。在描述事物时有些值是固定的,为了增强阅读性都给这些值起了个名字方便阅读而这个值不需要改变所以加上final修饰。由final修饰后变成常量,常量书写规范是所有字母大写,如果有多个单词,单词间用下划线连接。

4、内部类当定义在类中局部位置上时,只能访问该局部被final 修饰的变量。