📜  Java中的静态和非静态空白最终变量

📅  最后修改于: 2022-05-13 01:55:27.409000             🧑  作者: Mango

Java中的静态和非静态空白最终变量

变量为我们提供了程序可以操作的命名存储。类中有两种类型的数据变量:
实例变量:实例变量在类中声明,但在方法、构造函数或任何块之外。当为堆中的对象分配空间时,会为每个实例变量值创建一个槽。实例变量在使用关键字“new”创建对象时创建,并在对象被销毁时销毁。它们是对象的属性,因此只能使用对象访问它们。

静态变量:类变量也称为静态变量,在类中使用 static 关键字声明,但在方法、构造函数或块之外。每个类只有一个类变量的副本,无论从中创建了多少对象。它们是类的属性而不是对象的属性,因此可以直接使用类名以及使用对象来使用它们。

// Java code to illustrate use of instance and static variables
public class Emp {
    String name;
    int salary;
    static String company;
    public void printDetails()
    {
        System.out.println("Name: " + name);
        System.out.println("Company: " + company);
        System.out.println("Salary: " + salary);
    }
    public static void main(String s[])
    {
        Emp.company = "GeeksForGeeks";
        Emp g = new Emp();
        g.name = "Shubham";
        g.salary = 100000;
  
        Emp sp = new Emp();
        sp.name = "Chirag";
        sp.salary = 200000;
  
        g.printDetails();
        sp.printDetails();
  
        g.company = "Google";
        g.salary = 200000;
        System.out.println("\nAfter change\n");
        g.printDetails();
        sp.printDetails();
    }
}

输出:

Name: Shubham
Company: GeeksForGeeks
Salary: 100000
Name: Chirag
Company: GeeksForGeeks
Salary: 200000

After change

Name: Shubham
Company: Google
Salary: 200000
Name: Chirag
Company: Google
Salary: 200000

在上面的示例中,通过更改公司名称,它会反映在所有其他对象中,因为它是一个静态变量。但是改变 g 的薪水并不会改变 s 的薪水,因为薪水是一个实例变量。

空白最终变量:已声明但未分配的最终变量称为空白最终变量。它只能在构造函数中初始化。如果它没有被初始化,它会引发编译错误,因为它应该在程序中的某处被赋予一个值,并且也只能从构造函数中获得。

静态空白最终变量:它是声明为静态的空白最终变量。也就是说,声明了但没有赋值或没有初始化的最终静态变量称为静态空白最终变量。它只能通过静态块进行初始化。
这是一个说明空白最终变量初始化的示例-

// Java program to illustrate initialization 
// of blank final variables
public class GFG {
    private static final int a;
    private final int b;
    static
    {
        a = 1;
    }
    GFG(int c)
    {
        b = c;
    }
    public static void main(String s[])
    {
        GFG g1 = new GFG(10);
        GFG g2 = new GFG(20);
        System.out.println(GFG.a);
        System.out.println(g1.b);
        System.out.println(g1.b);
    }
}

输出:

1
10
10

在上面的示例中,b 使用构造函数初始化,而 a 使用静态块。

预测以下程序的输出:

// Java program to illustrate 
// static blank final variable
public class UserLogin {
    public static final long GUEST_ID = -1;
    private static final long USER_ID;
    static
    {
        try {
            USER_ID = getID();
        }
        catch (IdNotFound e) {
            USER_ID = GUEST_ID;
            System.out.println("Logging in as guest");
        }
    }
    private static long getID()
        throws IdNotFound
    {
        throw new IdNotFound();
    }
    public static void main(String[] args)
    {
        System.out.println("User ID: " + USER_ID);
    }
}
class IdNotFound extends Exception {
    IdNotFound() {}
}

输出:

prog.java:8: error: variable USER_ID might already have been assigned
USER_ID = GUEST_ID;
^
1 error

USER_ID 字段是一个静态的空白final。很明显,只有在分配给 USER_ID 失败的情况下才会在 try 块中抛出异常,因此在 catch 块中分配给 USER_ID 是完全安全的。静态初始化程序块的任何执行都将导致对 USER_ID 进行一次分配,这正是空白决赛所需要的。但是这个程序失败了,因为,一个空白的最终字段只能在程序中肯定没有分配的点上分配。

在这里,编译器不确定它是否在 try 块中分配,因此程序无法编译。我们可以通过删除静态块并在声明时初始化 USER_ID 来解决这个问题。

// Java program to illustrate 
// static blank final variable
public class UserLogin {
    public static final long GUEST_ID = -1;
    private static final long USER_ID = getUserIdOrGuest();
    private static long getUserIdOrGuest()
    {
        try {
            return getID();
        }
        catch (IdNotFound e) {
            System.out.println("Logging in as guest");
            return GUEST_ID;
        }
    }
    private static long getID()
        throws IdNotFound
    {
        throw new IdNotFound();
    }
    public static void main(String[] args)
    {
        System.out.println("User ID: " + USER_ID);
    }
}
class IdNotFound extends Exception {
    IdNotFound() {}
}

输出:

Logging in as guest
User ID: -1