【Java】:static 和 final 修饰符的使用

146 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

1️⃣前言

大家好,我是翼同学。今天笔记的内容是:

  • 自定义类的使用
  • 方法定义的位置
  • static和final修饰符的使用

2️⃣内容

2.1、自定义类

一般来说,创建一个完整程序需要设计若干类,并组合到一起,其中只有一个类有main方法。

类定义的一般格式如下:

class className {
    
    // method...

    // field...
}

习惯上将类的属性写在后面,而将类的具体功能(方法)写在前面,这有利于促使人们更加关注类的接口。

我们知道,在一个源文件中,只能有一个公有类(也就是用public修饰符修饰的类),但是可以设置任意个非公有类,并且源文件的名字必须和公有类的名字相同。如果源程序有多个类,则编译后会在目录下创建相应的多个字节码文件。接着将程序中包含main方法的类名字提供给字节码解释器,就可以启动这个程序。

另外,我们可以在一个源文件中定义若干个类,但习惯上,我们更喜欢将每一个类存放在一个单独的源文件中。

2.2、方法定义的位置

在C++中,我们喜欢在类中声明方法,然后在类的外部编写方法的具体实现。如果在类的内部定义方法,则该方法会自动成为内联方法。

而在Java中,所有的方法都必须定义在类的内部,至于哪些方法属于内联方法,则是虚拟机的任务。

2.3、final修饰符

我们可以将类的属性定义为final的,表示该属性为一个常量。构建对象时必须初始化这样的属性。也就是说在构造器中必须初始化常量属性,并且在后续操作中不能修改常量的值。

final修饰符一般用于修饰类中基本数据类型的成员变量,有时又用final修饰符修饰不可变的类。

备注:如果类中的所有方法都不会改变其对象,则称这个类为不可变的类(比如String)。

2.4、static修饰符

2.4.1、静态属性

如果用static修饰符去修饰类中的属性,此时该属性对于每一个对象而言是共享的,每一个对象都有一份自己的拷贝。即使没有对象,静态属性也是存在的。它属于类,而不属于任何独立的对象。

举个例子:

public class Test {
    public static void main(String[] args) {
        // 创建Student数组,每个元素都是类的一个对象
        Student[] stu = new Student[5];
        // 类对象的属性设置
        for(int i = 0; i<5; i++){
            // 先调用构造器
            stu[i] = new Student();
            //再调用更改器方法
            stu[i].setId();
        }
        // 输出数组元素
        for(int i = 0; i<5; i++){
            System.out.println("学生"+(i+1)+"的编号为:"+stu[i].getId());
        }
    }
}
// Student类的设计
class Student {
    // 方法:
    public void setId(){
        id = nextId;
        nextId++;
    }
    public int getId() {
        return id;
    }
    // 属性:
    private int id;
    private static int nextId = 1;
}

可以看到,Student类中,id就是学生的编号,其中每一个元素的id值都被设置为静态属性nextId当前的值,设置完后静态属性nextId的值自增加一。

2.4.2、静态常量

静态常量的应用也很广泛。比如Math类中的PI属性就是一个静态常量:

public class Math {
    ...
    public static final double PI = 3.14159265358979323846;
    ...
}

如果没有加上static修饰符,则该属性就成为Math类中的一个常规常量,每一个Math对象都有它自己的一份PI拷贝。

2.4.3、静态方法

一旦用修饰符static修饰方法后,该方法就是一个静态方法,此时无法向对象调用静态方法。我们可以将静态方法理解为没有this参数的方法。一般的,我们建议使用类名来访问静态方法,而不是使用对象来调用静态方法,并且静态方法不能操作对象,也就是不能访问常规属性,但可以访问静态属性。

举个例子,Math类中的pow方法就是一个静态方法。

Math.pow(2, 3);  //=> 8

另外可以注意到,main方法也是一个静态方法。main方法不对任何对象进行操作,静态的main方法将执行并创建程序所需要的对象。

总结静态方法的使用:

  • 场景一:方法不用访问对象的状态(属性),所需要的参数都是通过显式参数提供。此时可以定义为静态方法。
  • 场景二:方法只需要访问类中的静态属性,此时可以定义为静态方法。

3️⃣写在最后

好了,今天的笔记就记到这里。