为什么在Java中接口变量默认是静态的和最终的?


当前回答

摘自Philip Shaw的Java接口设计常见问题解答:

接口变量是静态的,因为Java接口不能自己实例化;变量的值必须在不存在实例的静态上下文中赋值。最后一个修饰符确保分配给接口变量的值是一个真正的常量,不能被程序代码重新分配。

其他回答

界面是双方之间的契约,是不变的,刻在石头上,因此是最终的。参见契约式设计。

(这不是一个哲学上的答案,而是一个更实际的答案)。对静态修饰符的要求是显而易见的,这一点已经被其他人回答了。基本上,由于接口不能被实例化,访问它的字段的唯一方法是使它们成为一个类字段——静态的。

接口字段自动变成final(常量)的原因是为了防止不同的实现意外地改变接口变量的值,这可能会无意中影响其他实现的行为。想象一下下面的场景,接口属性没有被Java显式地变成final:

public interface Actionable {
    public static boolean isActionable = false;

    public void performAction();
}

public NuclearAction implements Actionable {

    public void performAction() {
        // Code that depends on isActionable variable
        if (isActionable) {
            // Launch nuclear weapon!!!
        }
    }
}

现在,想想如果实现Actionable的另一个类改变了接口变量的状态会发生什么:

public CleanAction implements Actionable  {

    public void performAction() {
        // Code that can alter isActionable state since it is not constant
        isActionable = true;
    }
}

如果这些类是由类加载器在单个JVM中加载的,那么当CleanAction的performAction()在CleanAction的执行之后(在同一个线程中或以其他方式)被调用时,核动作的行为可能会受到另一个类CleanAction的影响,在这种情况下,这可能是灾难性的(从语义上来说)。

由于我们不知道接口的每个实现将如何使用这些变量,因此它们必须隐式地为final。

由于接口没有直接的对象,访问它们的唯一方法是使用类/接口,因此这就是为什么如果接口变量存在,它应该是静态的,否则外界将无法访问它。现在因为它是静态的,它只能保存一个值,任何实现它的类都可以改变它,因此它将是一团糟。

因此,如果有一个接口变量,它将是隐式静态的,最终的和明显的公共!!

public interface A{
    int x=65;
}
public interface B{
    int x=66;
}
public class D implements A,B {
    public static void main(String[] a){
        System.out.println(x); // which x?
    }
}

这是解决方案。

System.out.println(A.x); // done

我认为这就是为什么界面变量是静态的原因之一。

不要在接口中声明变量。

接口:系统需求服务。

在接口中,变量默认由public,static,final访问修饰符赋值。 因为:

public:有时候接口可能被放在其他包中。所以它需要从项目中的任何地方访问变量。

static:这样不完整的类不能创建对象。所以在项目中,我们需要访问没有对象的变量,这样我们就可以在interface_filename.variable_name的帮助下访问

final:假设一个接口由许多类实现,并且所有类都试图访问和更新接口变量。这样会导致数据变化不一致,影响到其他类。所以它需要用final声明访问修饰符。