Java_01_002-static 关键字

 

static 关键字,用于修饰成员变量和成员方法,被修饰的成员属于类,而不是单单属于某个实例对象。也就是说,既然属于类,那么不创建实例对象也可以调用了。

 

◆ 静态变量


静态变量,也叫类变量,即在书写上等同于被 static 关键字修饰的成员变量。

类的所有对象都共享同一个类变量的数据,任何对象都可以更改所在类的类变量的值,也可以在不创建该类的对象的情况下对类变量执行访问或修改操作。

1. 语法格式
<权限修饰符> static <数据类型> <变量名称>;

// eg:
static String classroom;
  • 权限修饰符非必要,无修饰符等同于 default
2. 源码示例

以学生为例,每个学生都是独立的个体,但会有很多学生属于同一个教室,因此以教室编号作为其静态变量。

public class Student {
    /**
     * 成员变量
     */
    private String name;

    /**
     * 静态变量
     *
     * 多个对象共享同一份数据
     */
    public static String classroom;

    public Student(){
        System.out.println("无参构造方法...");
    };
    public Student(String name){
        System.out.println("全参构造方法...");
        this.name = name;
    }
    
    public String getName() {
        return name;
    }

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

    public static String getClassroom() {
        return classroom;
    }

    public static void setClassroom(String classroom) {
        Student.classroom = classroom;
    }
}

 

◆ 静态方法


静态方法,也叫类方法,在书写上等同于被 static 关键字修饰的成员方法。

1. 语法格式
<修饰符> static <返回值类型> <方法名称> (<参数列表>){
	[方法体]
}

// eg:
public static String getClassroom() {
	return classroom;
}
public static void setClassroom(String classroom) {
    Student.classroom = classroom;
}

  • 类方法可以直接访问类变量和类方法,包括它本身

  • 类方法不可以直接访问普通成员变量或成员方法,但成员方法可以直接访问类变量或静态方法,因为内存中会先行加载并调用静态的内容,而后非静态的内容才会产生

  • 静态方法中,不能使用 this 关键字,因为 this 指针代表当前对象,其本质上也是非静态的内容

2. 源码示例
/**
* 成员方法
*/
public void show(){
    System.out.println("成员方法...");
    // 成员方法可以访问成员变量
    System.out.println(name);
    // 成员方法可以访问静态变量
    System.out.println(classroom);

}

/**
* 静态方法
*/
public static void location(){
    System.out.println("静态方法...");
    System.out.println(classroom);

    // 不能直接访问非静态变量
    // System.out.println(name);
    // 不能使用this关键字
    // System.out.println(this);
}

 

◆ 静态代码块


静态代码块,即定义在成员同层级位置上,以 static 关键字修饰的代码块。

系统启动时,其随着类的加载而执行且仅执行一次,优先于包括 main 方法和构造方法在内的所有方法的执行。

1. 语法格式
static {
	[执行语句]
}
  • 一般用于给类变量赋初始值
2. 源码示例
/*
 * 静态代码块
 *
 * 类第一次使用时,静态代码块执行,且仅执行唯一的一次
 * 另外,静态代码块总是优先于非静态执行,所以,静态代码块比构造方法先执行
 *
 * 一般用于一次性的对静态成员变量进行赋值
 */	
static {
    System.out.println("静态代码块执行...");
    classroom = "201";
}

 

◆ 测试用例


static 修饰的内容都是随着类的加载而加载的,并且仅加载一次。在内存中存在一块被我们称为静态区的固定区域,用于专门存储静态内容,所以,其可以直接被类名调用,又因为它有限与对象存在,所以,可以该类的所有对象共享。

1. 语法格式
// 访问类变量
[类名称].[类变量名];
[对象名称].[类变量名];
// 调用静态方法
[类名].[静态方法名(参数列表)];
[对象名称].[静态方法名(参数列表)];

// eg:
Student.classroom;
Student.location();
  • 多个对象均属于一个类,共享使用同一个静态内容,因此可以通过对象名访问静态成员,但是不建议这样,不仅语义上不通顺,而且会出现警告信息
2. 源码示例
import org.junit.Assert;
import org.junit.Test;

public class StudentTest {

    @Test
    public void testBlock() {
        // 静态代码块代码会在类使用之前执行
        System.out.println(Student.classroom);
        Assert.assertEquals("201", Student.classroom);
    }

    @Test
    public void testVariable() {
        // 可以通过对象访问类变量
        Student joyce = new Student("Joyce");
        Assert.assertEquals("Joyce", joyce.getName());
        Assert.assertEquals("201", joyce.classroom);
        joyce.classroom = "205";
        // 建议通过类名称进行访问,而非对象名称
        Assert.assertEquals("205", Student.classroom);
    }

    @Test
    public void testMethod() {
        // 可以通过对象调用类方法
        Student joyce = new Student("Joyce");
        Assert.assertEquals("Joyce", joyce.getName());
        joyce.setClassroom("203");
        Assert.assertEquals("203", joyce.getClassroom());
        // 建议通过类名称进行调用,而非对象名称
        Student.setClassroom("203");
        Student.location();
    }
}

测试用例全部通过,并打印如下信息:

// testBlock
静态代码块执行...
201
    
// testVariable
全参构造方法...

// testMethod 
全参构造方法...
静态方法...
203

 

◆ 应用场景

static 关键字,可以修饰变量、方法和代码块。在使用的过程中,主要应用还是想在不创建对象的情况下调用方法,我们一般将提供大量静态方法的类称为工具类。

以一个猜数的游戏为例,简单介绍下工具类的强大:

  • 生成一个随机数
  • 10次猜数机会,每次会获得一个反馈
  • 猜对或者机会完全消耗则游戏结束
@Test
public void testGuess() {
    double random = Math.random() * 100;
    long actual = Math.round(random);
    boolean isSuccess = false;

    for (int i = 0; i < 10; i++) {
        Scanner scanner = new Scanner(System.in);
        int expected = scanner.nextInt();
        if (expected > actual){
            System.out.println("Too bigger!");
        }else if (expected < actual){
            System.out.println("Too Smaller!");
        }else {
            isSuccess = true;
            System.out.println("Success!");
            break;
        }
    }
    if (!isSuccess){
        System.out.println("Game over!");
    }
}
  • java.lang.Math 是一个数学相关的工具类,random() 可以获取一个[0.1.0] 之间的伪随机数,round() 可以获取最接近浮点数的整数,相当于四舍五入
  • java.util.Scanner 是一个扫描器,我们可以通过它,获取从键盘录入的数据

 


上述所云,诚为一家之言,如有疏漏谬误,欢迎批评指正!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值