Java讲课笔记12:static关键字

相信大家对static关键字并不陌生,回顾一下我们在第一次课创建的第一个Java程序HelloWorld.java:
在这里插入图片描述
主方法的修饰符里就有static,为什么主方法必须有static修饰符呢?通过本讲的学习,你会找到答案的。

零、本讲学习目标

1、掌握静态变量的使用

2、掌握静态方法的使用

3、掌握静态代码块的使用

一、static关键字的用处

Java中的static关键字,用于修饰类的成员,如成员变量、成员方法以及代码块等,被static修饰的成员具备一些特殊性。比如被static关键字修饰的成员变量、方法可以被类直接访问,而不需要预先构造类的实例化对象。

二、静态变量

1、静态变量的定义

  • 原因:在定义一个类时,只是在描述某类事物的特征和行为,并没有产生具体的数据。只有通过new关键字创建该类的实例对象后,系统才会为每个对象分配内存空间,存储各自的数据。有时候,开发人员希望某些特定的数据在内存里只有一份,而且能被一个类的所有实例对象所共享。例如某个学校所有学生共享同一个学校名称,此时完全不必在每个学生对象所占用的内存空间中都声明一个变量来表示学校名称,而可以在对象以外的空间声明一个表示学校名称的变量让所有对象来共享。这种能被类的所有对象共享的变量就是静态变量。
  • 定义:在一个Java类中,可以使用static关键字来修饰成员变量,该变量被称作静态变量。

2、静态变量的内存分配示意图

在这里插入图片描述
从图可以看出,所有学生对象共享一个名称为schoolName的变量。在一个Java类中,要实现这种功能可以使用static关键字来修饰成员变量,该变量被称作静态变量,它可以被所有实例所共享。

3、静态变量的访问

  • 通过类名访问:静态变量被所有实例共享,可以使用“类名.变量名”的形式来访问。
  • 通过对象名访问:静态变量也可以“对象名.变量名”的形式来访问,当然同一个类的不同对象访问的静态变量值都是相同的。

4、静态变量案例演示

  • 创建Student类,包含实例变量name和age、静态变量schoolName
    在这里插入图片描述
package net.hw.lesson12;

/**
 * 功能:学生类
 * 作者:华卫
 * 日期:2020年5月1日
 */
public class Student {
    static String schoolName; // 静态变量schoolName
    private String name; // 实例变量name
    private int age; // 实例变量age

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
    public void speak() {
        System.out.println("我叫" + name + ",今年" + age + "岁了,是" + schoolName + "的学生。");
    }
}
  • 创建TestStudent类,创建对象,设置属性,调用方法
    在这里插入图片描述
package net.hw.lesson12;

/**
 * 功能:测试Student类
 * 作者:华卫
 * 日期:2020年5月1日
 */
public class Example1201{
    public static void main(String[] args) {
        // 给静态变量赋值
        Student.schoolName = "泸州职业技术学院";

        // 创建第1个学生对象,并设置属性
        Student stu1 = new Student();
        stu1.setName("李晓红");
        stu1.setAge(19);

        // 创建第2个学生对象,并设置属性
        Student stu2 = new Student();
        stu2.setName("洪晓熙");
        stu2.setAge(18);

        // 调用两个学生对象的方法
        stu1.speak();
        stu2.speak();

        // 通过对象名访问静态变量
        System.out.println("stu1.schoolName = " + stu1.schoolName);
        System.out.println("stu2.schoolName = " + stu2.schoolName);
        
        // 通过类名访问静态变量
        System.out.println("Student.schoolName = " + Student.schoolName);
    }
}

运行程序,查看结果:
在这里插入图片描述
由于schoolName是静态变量,既可以通过Student.schoolName的方式进行调用,也可以通过Student的实例对象进行调用,比如stu1.schoolName和stu2.schoolName。第11行代码将变量schoolName赋值为“泸州职业技术学院”后,两个学生对象stu1和stu2的schoolName属性值均为“泸州职业技术学院”。

5、使用static关键字注意事项

注意,static关键字只能用于修饰成员变量,不能用于修饰局部变量,否则编译会报错。
在这里插入图片描述

三、静态方法

普通成员方法也叫实例方法,表明只有在实例化对象之后才能调用,如果想不创建对象就能调用某个方法,那么此时可以考虑使用静态方法。

1、静态方法的定义

在一个类中,被static关键字修饰的方法称为静态方法。

2、静态方法的访问

  • 方法一、通过类名来访问:类名.方法
  • 方法二、通过对象名来访问:对象名.方法

3、静态方法案例演示

  • 在Student类定义静态方法
    在这里插入图片描述
  • 创建Example1202类,通过两种方式调用静态方法
    在这里插入图片描述
package net.hw.lesson12;

/**
 * 功能:调用静态方法
 * 作者:华卫
 * 日期:2020年5月1日
 */
public class Example1202 {
    public static void main(String[] args) {
        // 设置静态属性值
        Student.schoolName = "泸州职业技术学院";
        
        // 用“类名.方法”方式调用静态方法
        Student.tell();

        // 实例化对象
        Student stu = new Student();
        // 用“对象名.方法”方式调用静态方法
        stu.tell();
    }
}
  • 运行程序,查看结果
    在这里插入图片描述

4、静态方法注意事项

在一个静态方法中只能访问用static修饰的成员,原因是没有被static修饰的成员需要先创建对象才能访问,而静态方法在被调用时可以不创建任何对象。
在这里插入图片描述

四、静态代码块

1、静态代码块的定义

  • 在Java中,使用一对大括号包围起来的若干行代码被称为一个代码块。
  • 在Java中,使用static关键字修饰的代码块称为静态代码块。

2、静态代码块执行情况

当类被加载时,静态代码块会执行,并且只会执行一次

3、静态代码块的作用

在程序中,经常使用静态代码块来对类的成员变量进行初始化。

4、静态代码块案例演示

  • 创建Person类
    在这里插入图片描述
package net.hw.lesson12;

/**
 * 功能:静态代码块
 * 作者:华卫
 * 日期:2020年5月1日
 */
public class Person {
    static String country;
    static {
        country = "中国";
        System.out.println("执行Person类的静态代码块");
    }

    public void speak() {
        System.out.println("我是" + country + "人。");
    }
}
  • 创建测试类Example1203
    在这里插入图片描述
package net.hw.lesson12;

/**
 * 功能:测试Person类
 * 作者:华卫
 * 日期:2020年5月1日
 */
public class Example1203 {
    static {
        System.out.println("执行Example1203的静态代码块");
    }

    public static void main(String[] args) {
        // 实例化两个Person对象
        Person p1 = new Person();
        Person p2 = new Person();

        // 调用对象方法
        p1.speak();
        p2.speak();
    }
}
  • 运行程序,查看结果
    在这里插入图片描述
    在主方法中创建了两个Person对象,但在两次实例化对象的过程中,静态代码块中的内容只输出了一次,这就说明静态代码块在类第一次使用时才会被加载,并且只会加载一次。

五、了解Math类的静态成员

在这里插入图片描述
上述案例,我们输出了Math的静态属性E和PI,调用了Math的静态方法sqrt()。

如何能查看一个类的源码呢?很简单,将鼠标移到该类上,左手按着Ctrl键,同时点击鼠标左键,即可打开该类的源码文件进行查看。
在这里插入图片描述

  • 查看Math.java文件内容
    在这里插入图片描述
  • 摘录Math类部分源码
package java.lang;
import java.util.Random;

import sun.misc.FloatConsts;
import sun.misc.DoubleConsts;

/**
 * @author  unascribed
 * @author  Joseph D. Darcy
 * @since   JDK1.0
 */

public final class Math {

    /**
     * Don't let anyone instantiate this class.
     */
    private Math() {}

    /**
     * The {@code double} value that is closer than any other to
     * <i>e</i>, the base of the natural logarithms.
     */
    public static final double E = 2.7182818284590452354;

    /**
     * The {@code double} value that is closer than any other to
     * <i>pi</i>, the ratio of the circumference of a circle to its
     * diameter.
     */
    public static final double PI = 3.14159265358979323846;

    /**
     * Returns the trigonometric sine of an angle.  Special cases:
     * <ul><li>If the argument is NaN or an infinity, then the
     * result is NaN.
     * <li>If the argument is zero, then the result is a zero with the
     * same sign as the argument.</ul>
     *
     * <p>The computed result must be within 1 ulp of the exact result.
     * Results must be semi-monotonic.
     *
     * @param   a   an angle, in radians.
     * @return  the sine of the argument.
     */
    public static double sin(double a) {
        return StrictMath.sin(a); // default impl. delegates to StrictMath
    }   
}
  • Math.java文件有2370行
    在这里插入图片描述
  • 查看Math类的结构
    在这里插入图片描述

六、课后作业

1、创建Circle类

  • 定义双精度静态变量r
  • 定义双精度静态常量PI = 3.1414926
  • 定义访问静态变量r的静态方法setR()与getR()
  • 定义获取圆面积的静态方法getArea()

2、创建TestCircle类

  • 添加静态代码块,输出“计算圆面积”
  • 在主方法里从键盘输入圆半径
  • 调用Circle的静态方法计算圆面积
  • 输出圆面积,保留两位小数

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/howard2005/article/details/105882303