(十二)static关键字

目录

        前言:

        一、static静态关键字

        二、static应用知识:工具类

        三、static应用知识:代码块

        四、static应用知识:单例

        五、面向对象三大特征之二:继承

前言:

static是计算机高级语言关键字

        像在VB,C#,C,C++,Java,PHP,Objective-C,JavaScript中我们可以看到static作为关键字和函数出现,在其他的高级计算机语言如FORTRAN、ALGOL、COBOL、BASIC、LISP、SNOBOL、PL/1、Pascal、PROLOG、Ada等语言中也是有出现的,只是有着不同的作用,对于其具体作用,有需要的时候是可以具体查阅的。

一、static静态关键字

1.static是什么?修饰成员变量的用法?

        ①static是静态的意思,可以修饰成员变量和成员方法。

        ②static修饰成员变量表示该成员变量只在内存中只存储一份,可以被共享访问、修改。

2.成员变量可以分为2类。

        ①静态成员变量(有static修饰,属于类,内存中加载一次):常表示如在线人数信息、等需要被共享信息,可以被共享访问。

        访问格式:

                类名.静态成员变量。(推荐)

                对象.静态成员变量。(不推荐)

        ②实例成员变量(无static修饰,存在于每个对象中):长表示姓名name、年龄age、等属于每个对象的信息。

        访问格式:

                对象.实例成员变量

代码演示:

//类的五大成分(成员变量、成员方法、工具类、代码块、内部类)
public class Demo1 {
    //相同包下的类可以直接访问,不同包下的类必须导包,才可以使用! 导包的语法格式:import 包名.类名;
    public static void main(String[] args) {
        //static修饰成员变量的作用和访问特点
        //1.类名。静态1成员变量
        System.out.println(user.onlineNumber);//161
​
        user u = new user();
        u.onlineNumber++;//新增一个人
        System.out.println(u.onlineNumber);
​
        //注意:如果这个类中使用不同包下的相同的类名,此时默认只能导入一个类的包,另一个类则要使用全名访问。
        //权限修饰符:控制一个成员能够被访问的范围 : 可以修饰成员变量,方法,构造器,内部类。
    }
}

3.两种成员变量各自在什么情况下定义?

        ①静态成员变量:表示在线人数等需要被共享的信息。

        ②实例成员变量:属于每个对象,且每个对象的该信息不同时(如:name、age、money.......等)。

4.每种成员方法的使用场景是怎么样的?

        ①表示对象自己的行为的,且方法中需要直接访问实例成员,则该方法必须申明成实例方法。

        ②如果该方法是以执行一个通用功能为目的,或者需要方便访问,则可以申明成静态方法。

5.static修饰成员方法的基本用法

代码演示:

import ArrayList.Student;
​
/**
 * 成员方法的分类
 * 静态成员变量(方法)(有static修饰,归属于类),建议用类名访问,也可以用对象访问  通用的功能  属于类
 * 实例成员方法(变量)(无static修饰,归属于对象),只能用对象触发访问   自己的方法  属于对象
 */
public class static_Demo2 {
    /**
     * 实例成员变量,无static修饰,属于对象
     */
    private String name;
​
    public static int getmax(int age1 ,int age2) {
        return age1>age2 ? age1:age2;
    }
​
    /**
     * 实例方法:属于对象的,只能用对象触发访问
     */
​
    public void student(){
        System.out.println(name + "好好学习,天天向上");
    }
    public static void main(String[] args) {
        //1.类名,静态方法变量
        System.out.println(static_Demo2.getmax(10,3));
        //2.注意:同一个类中,访问静态方法,类名可以省略不写
        System.out.println(getmax(10, 32));
        Student s = new Student(13, "吴磊", 34, "卓越一班");
​
        //3.对象调用静态方法(语法可行,但不推荐)
        System.out.println(s.getAge());
    }
}

6.static修饰成员方法的内存原理

(十二)static关键字_第1张图片

 

7.static的注意事项

        ①静态方法只能访问静态的成员,不可以直接访问实例成员。

        ②实例方法可以访问静态成员,也可以访问实例成员。

        ③静态方法中是不可以出现this关键字的。


import ArrayList.Student;

/**
 * 成员方法的分类
 * 静态成员变量(方法)(有static修饰,归属于类),建议用类名访问,也可以用对象访问  通用的功能  属于类
 * 实例成员方法(变量)(无static修饰,归属于对象),只能用对象触发访问   自己的方法  属于对象
 */
public class static_Demo2 {
    /**
     * 实例成员变量,无static修饰,属于对象
     */
    private String name;

    public static int getmax(int age1 ,int age2) {
        return age1>age2 ? age1:age2;
    }

    /**
     * 实例方法:属于对象的,只能用对象触发访问
     */

    public void student(){
        System.out.println(name + "好好学习,天天向上");
    }
    public static void main(String[] args) {
        //1.类名,静态方法变量
        System.out.println(static_Demo2.getmax(10,3));
        //2.注意:同一个类中,访问静态方法,类名可以省略不写
        System.out.println(getmax(10, 32));
        Student s = new Student(13, "吴磊", 34, "卓越一班");

        //3.对象调用静态方法(语法可行,但不推荐)
        System.out.println(s.getAge());
    }
    /**
     * 1.静态方法只能访问静态的成员,不可以直接访问实例成员
     * 2.实例方法可以访问静态成员,也可以访问实例成员
     * 3.静态方法中不可出现this关键字
     */

    /**
     * 静态成员
     */

    public static int onlineNumber = 10;
    public static void test(){
        System.out.println("=====test======");
    }
    /**
     * 实例成员
     */
    private String name2;
    public void run(){
        System.out.println(name2+"跑得快~");
    }
    //1.静态方法只能访问静态的成员,不可以直接访问实例成员
    public static void test1(){
        System.out.println(static_Demo2.onlineNumber);
        System.out.println(onlineNumber);
        test();
        static_Demo2 t = new static_Demo2();
        System.out.println(t.name2);//不能直接访问,间接访问
    }
    //2.实例方法可以访问静态成员,也可以访问实例成员
    public void go(){
        System.out.println(static_Demo2.onlineNumber);
        System.out.println(onlineNumber);
        test();
        System.out.println(name2);
        System.out.println(this);//this可以出现在实例方法中
        run();
    }
    //3.静态方法中不可出现this关键字
    public static void test3(){
        //System.out.println(this);this只能代表当前对象
    }
}

二、static应用知识:工具类

1.工具类是什么?

        类中都是一些静态方法,每个方法都是以完成一个公用的功能为目的,这个类用来给系统开发人员共同使用的。

2.例题: 验证码工具类

工具类:

import java.util.Random;
/**
 * 工具类
 */
public class static_login {
    /**
     * 由于工具类无法创建对象,所以把其构造器私有化会显得很专业
     */
    private static_login(){
    }
    /**
     * 静态方法
     */
    public static String createVerifyCode(int n) {
        //1.定义一个变量记住验证码
        String code = " ";
        //2.定义一个变量记住全部验证码字符
        String data = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPSADFGHJKLZXCVBNM1234567890";
        //3.定义一个循环生成几个随即索引,去获取字符
        Random r = new Random();
        for (int i = 0; i < n; i++) {
            //4.获取随即索引的对应字符。链接给code
            int index = r.nextInt(data.length());
            code +=data.charAt(index);
        }
        return code;
    }
}

实现类:

public class login {
    public static void main(String[] args) {
        System.out.println(static_login.createVerifyCode(5));
    }
}

3.为什么工具类中的方法不用实例方法做?

        ①实例方法需要创建对象调用;

        ②此时用对象只是为了调用方法,这样只会浪费内存。

4.工具类定义时的其他要求:

        由于工具里面都是静态方法,直接用类名即可访问,因此,工具类无需创建对象,建议将工具类的构造器进行私有。

5.工具类是什么,有什么好处?

        ①内部都是一些静态方法,每个方法完成一个功能;

        ②一次编写,处处可用,提高代码的复用性;

6.工具类有什么要求?

        建议工具类的构造器私有化处理

三、static应用知识:代码块

1.代码块概述:

        ①代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类),定义在类中方法外。

        ②在java类下,使用{}括起来的代码被称为代码块。

2.代码块分类:

①静态代码块

        格式: static{}

        特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次。

使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。

②构造代码块

        格式: {}

        特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并在构造器执行前执行。

使用场景:初始化实例资源。

代码演示:

public class static_Demo {
    /**
     * 代码块:在Java类下 :使用{}括起来的代码被称为代码块
     */
​
    /**
     * 静态代码块:static{}  初始化静态资源
     * 特点: 需要通过static关键字修饰,随着类的加载而加载,并自动触发,只执行一次
     * 使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用,(用于在程序启动时,进行静态资源的初始化操作)
     */
​
    /**
     * 构造代码块{}
     * 特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行
     * 使用场景:初始化实例资源
     */
    private String name;
    static {
        System.out.println("==================静态代码块被触发执行了=========");
    }
​
    public static_Demo3(){
​
        System.out.println("========无参构造器被触发==============");
    }
    {
        name = "张三";
        System.out.println("========实例(构造)代码块被触发执行================");
    }
    public static void main(String[] args) {
        System.out.println("main方法执行");
        static_Demo3 s1 = new static_Demo3();
        System.out.println(s1.name);
​
        static_Demo3 s2 = new static_Demo3();
        System.out.println(s2.name);
    }
}

四、static应用知识:单例

1.什么是设计模式(Design pattern)

        ①开发中经常遇到一些问题,一个问题通常有n种解法的,但其中肯定有一种解法是最优的,这个最优的解法被人总结出来,称之为设计模式。

        ②设计模式有20多种,对应20多种软件开发中遇到的问题。

2.学设计模式主要是学2点

        第一:这种模式用来解决什么问题。

        第二:遇到这种问题了,该模式是怎么写的,他是如何解决这个问题的。

3.单例模式

        ①可以保证系统中,应用该模式的这个类永远只有一个实例,即一个类永远只能创建一个对象。

        ②例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。

4.单例的实现方式很多

        ①饿汉单例模式

        ②懒汉单例模式

        .......

5.饿汉单例设计模式

        在用类获取对象的时候,对象已经提前为你创建好了

设计步骤:

        ①定义一个类,把构造器私有;

        ②定义一个静态变量存储一个对象。

代码演示:

单例类:

/**
 * 使用饿汉单例实现单例类
 */
public class singleIntstance {
    /**
     * 2.饿汉单例是在获取对象前,对象已经提前准备好一个,这个对象只能是一个,所以定义静态成员变量记住
     */
    public static singleIntstance instance = new singleIntstance();
    /**
     * 把构造器私有化
     */
    private singleIntstance(){
        System.out.println("创建了一个饿汉单例对象");
    }
}

实现单例类:

public class Test {
    public static void main(String[] args) {
        //饿汉单例
        singleIntstance s1 = singleIntstance.instance;
        singleIntstance s2 = singleIntstance.instance;
        System.out.println(s1==s2);
​
    }
}

6.懒汉单例设计模式

        在真正需要该对象的时候,才去创建一个对象(延迟加载对象)。

设计步骤:

        ①定义一个类,把构造器私有;

        ②定义一个静态变量存储一个对象。

        ③提供一个返回单例对象的方法。

代码演示:

单例类:

public class singleIntstance {
    /**
     * 懒汉单例:在真正需要该对象时,才去创建一个对象(延迟加载对象)
     */
    //第一次拿对象:此时需要创建对象
    /**
     * 2、定义一个静态的成员变量负责存储一个对象,只加载一次,只有一份
     */
    private static singleIntstance instance;
    /**
     * 3、提供一个方法,对外返回单例对象
     */
    public static singleIntstance getInstance(){
        if (instance == null) {
            //第一次来拿对象
            instance = new singleIntstance();
        }
        return instance;
    }
    /**
     * 1、构造器私有化
     */
    public singleIntstance(){
        System.out.println("");
    }
​
​
}

实现单例类:

public class singlelntstance_Test {
    public static void main(String[] args) {
        //懒汉单例
        singleIntstance s1 = singleIntstance.getInstance();
        singleIntstance s2= singleIntstance.getInstance();
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s1==s2);
    }
}

五、面向对象三大特征之二:继承

1.什么是继承?

        java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起父子关系。

public class Student extends people{}

        Student称为子类(派生类),people称为父类(基类或超类)。

        父类(super)、子类(this)

作用:当子类继承父类后,就可以直接使用父类公共的属性和方法了。

2.继承规范:

        ①子类们相同特征(共性属性,共性方法)放在父类中定义。

        ②子类独有的属性和行为应该定义在子类自己里面。

3.继承的特点:

        ①子类有自己的构造器,不能继承父类的构造器。

        ②子类是否可以继承父类的私有成员(可以继承父类的私有成员,只是不能直接访问! )。

        ③子类是否可以继承父类的静态成员(不是继承,是共享的父类的) ​ 。

        ④java只能继承一个父类,不支持多继承,不过支持多层继承。 多层继承: A继承B,B继承C;

        ⑤object :object是祖宗类

4.在子类中给访问成员(成员变量、成员方法)满足:就近原则(局域对象<子类对象<父类对象)

        ①先子类局部范围找。

        ②然后子类成员范围找。

        ③然后父类成员范围找,如果父类范围还没有找到则报错。

5.如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办?

        ①可以通过super关键字,指定访问父类的成员。

        格式:super.父类成员变量/父类成员方法

        ②可以通过this关键字,指定访问子类的成员。

        格式:this.子类成员变量/子类成员方法

6.继承后:方法重写

        在继承体系中,子类出现了和父类中一摸一样的方法声明,我们就称子类这个方法是重写的方法。

7.方法重写的应用场景

        ①当子类需要父类的功能,但父类的该功能不完全满足自己的需求时。

        ②子类可以重写父类中的方法。

8.@Override重写注解:

        放在重写后的方法上,作为重写是否正确的校验注解。

作用:

        1.这个方法必须是正确重写的;

        2.提高代码的可读性,代码优雅。

注意:

        ①重写方法的名词称、形参列表必须与被重写方法的名称和参数列表一致。

        ②私有方法不能被重写。

        ③子类重写父类方法时,访问权限必须大于或者等于父类。

        ④子类不能重写父类的静态方法,如果重写会报错。

9.方法重写案例:

        旧手机的功能只能是基本的打电话,发信息;

        新手机的功能需要能够在基本的打电话下支持视频通话。基本的发信息下支持发送语音和图片。

public class extends_Test1 {
    public static void main(String[] args) {
        //方法重写
        newphone nw = new newphone();
        nw.call();
        nw.sending();
    }
}
/*
新手机:子类
 */
class newphone extends phone{
    //重写的方法
    @Override//1.这个方法必须是正确重写的;2.提高代码的可读性,代码优雅。
    public void call(){
        super.call();//先用父类的基本功能
        System.out.println("开始视频通话");
    }
    //重写的方法
    @Override
    public void sending(){
        super.sending();//先用父类的基本功能
        System.out.println("发送有趣的图片~~");
    }
}
/*
旧手机:父类
 */
class phone{
    public void call(){
        System.out.println("打电话");
    }
    public void sending(){
        System.out.println("发短信");
    }
}

10.继承后:子类继承父类后构造器的特点:

        子类所有构造器都会先访问父类构造器,再调用自己的构造器,初始化父类的数据。

为什么?

        ①子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。

        ②子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化。

怎么调用父类构造器?

        子类构造器的第一行语句默认都是:super(),不写也存在。

11.继承后:子类构造器访问父类有参构造器?

①super调用父类有参构造器的作用:

        初始化继承自父类的数据;

②如果父类中没有无参数构造器,只有有参构造器,会出现什么现象呢?

        会报错,因为子类默认是调用父类无参构造器的。

③如何解决?

        子类构造器中可以书写super(...),手动调用父类的有参数构造器。

12.代码演示:

子类:猫类

public class cat extends dog {
    public cat(){
        System.out.println("子类cat无参数构造器被执行~~");
    }
    public cat(String name){
        System.out.println("子类cat有参数构造器被执行~~");
    }
}

父类:狗类

public class dog {
    public dog(){
        System.out.println("父类dog无参数构造器被执行~~");
    }
}

实现类:main

public class test1 {
    public static void main(String[] args) {
        //继承后子类构造器的特点
        cat c1 = new cat();
        System.out.println(c1);
        System.out.println("----------");
        cat c2 = new cat("金毛");
        System.out.println(c2);
    }
}

13.this和super小结

        this:代表本类对象的引用;super:代表父类存储空间的标识

(十二)static关键字_第2张图片

  • this()和super()必须要在第一行,所以一个构造器中不能共存this()和super();

  • this :访问子类当前对象的成员

  • super :在子类方法中指定访问父类的成员

  • this(...) :访问本类兄弟构造器

  • super(...) : 在本类构造器中指定访问父类的构造器

14.代码演示:

动物类(父类):

public abstract class Animal {
    public String name = "动物名";
​
    public void eat() {
        System.out.println("动物要吃东西!");
    }
​
    public static String location = "长隆动物园";
​
    public abstract void run();
}

老虎类(子类):

public class Tiger extends Animal {
    public static boolean location;
    String name = "老虎名";
​
    public void showName(){
        String name = "局部名";
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
        super.eat();
        this.eat();
    }
    @Override // 1、重写校验注解,加上之后,这个方法必须是正确重写的,这样更安全  2、提高代码的可读性
    /**1、重写的名字和形参列表必须与被重写的方法一样
     * 2、私有方法不能被重写
     * 3、子类重写父类方法时,访问权限必须大于或者等于父类( 访问权限:privase < 不写 < protected < public)
     * 4、静态方法不能被子类重写
     */
    public void eat(){
        super.eat();//方法重写,重写父类
        System.out.println("老虎在吃东西");
    }
​
    @Override
    public void run() {
        
    }
}

实现类:

//extends :子类继承父类  让一个类与另一个类建立父子关系,用于提高代码复用性(子类extends 父类)
//父类(super)、子类(this)
public class extends_Demo4 {
    /**  继承的特点:
     * 1、子类有自己的构造器,不能继承父类的构造器
     * 2、子类是否可以继承父类的私有成员(可以继承父类的私有成员,只是不能直接访问! )
     * 3、子类是否可以继承父类的静态成员(不是继承,是共享的父类的)
     * 4、java只能继承一个父类,不支持多继承,不过支持多层继承。  多层继承: A继承B,B继承C;
     * 5、object :object是祖宗类
     * 在子类中给访问成员(成员变量、成员方法)满足:就近原则(局域对象<子类对象<父类对象)
     */
    //子类所有构造器都会先访问父类构造器,再调用自己的构造器,初始化父类的数据
​
    /**
     * this()和super()必须要在第一行,所以一个构造器中不能共存this()和super();
     * this :访问子类当前对象的成员
     * super :在子类方法中指定访问父类的成员
     * this(...) :访问本类兄弟构造器
     * super(...) : 在本类构造器中指定访问父类的构造器
     */
    public static void main(String[] args) {
        Tiger t = new Tiger();
        t.eat();
        System.out.println(Tiger.location);
        t.showName();
​
    }
}

你可能感兴趣的:(JAVA,java)