为什么接口变量默认为静态和final ?

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

454354 次浏览

因为其他任何东西都是实现的一部分,而接口不能包含任何实现。

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

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

source

static -因为接口不能有任何实例。最后,因为我们不需要改变它。

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

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

Java不允许在接口中定义抽象变量和/或构造函数。解决方案:简单地在你的接口和你的实现之间挂起一个抽象类,它只像这样扩展抽象类:

 public interface IMyClass {


void methodA();
String methodB();
Integer methodC();


}


public abstract class myAbstractClass implements IMyClass {
protected String varA, varB;


//Constructor
myAbstractClass(String varA, String varB) {
this.varA = varA;
this.varB = VarB;
}


//Implement (some) interface methods here or leave them for the concrete class
protected void methodA() {
//Do something
}


//Add additional methods here which must be implemented in the concrete class
protected abstract Long methodD();


//Write some completely new methods which can be used by all subclasses
protected Float methodE() {
return 42.0;
}


}


public class myConcreteClass extends myAbstractClass {


//Constructor must now be implemented!
myClass(String varA, String varB) {
super(varA, varB);
}


//All non-private variables from the abstract class are available here
//All methods not implemented in the abstract class must be implemented here


}

你也可以使用抽象类没有任意接口,如果你确定以后不想和其他接口一起实现它。请注意,你不能创建一个抽象类的实例,你必须先扩展它。

(“protected”关键字意味着只有扩展类才能访问这些方法和变量。)

斯派罗

Java中,interface不允许你声明任何实例变量。使用在接口中声明的变量作为实例变量将返回编译时错误。

你可以使用static final声明一个常量变量,它不同于实例变量。

接口可以由任何类实现,如果该值被其中一个实现类改变了,那么就会对其他实现类产生误导。接口基本上是指将两个相互关联但又不同的实体组合在一起。因此,在接口内部声明的变量将隐式是final的,也是静态的,因为接口不能被实例化。

设想一个web应用程序,其中定义了接口并由其他类实现它。因为你不能创建一个接口的实例来访问变量,所以你需要一个静态关键字。由于它是静态的,任何值的变化都会反映到其他实现它的实例。所以为了防止这种情况,我们将其定义为最终结果。

界面是双方之间的契约,是不变的,刻在石头上,因此是最终的。看到合同设计

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

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

不要在接口中声明变量。

公共:用于所有类的可访问性,就像接口中呈现的方法一样

静态: as接口不能有一个对象,即interfaceName。variableName可以用来引用它,也可以直接在实现它的类中引用variableName。

最后:使它们成为常量。如果两个类实现了相同的接口,并且您赋予它们更改值的权利,那么在var的当前值中就会发生冲突,这就是为什么只允许一次初始化。

而且所有这些修饰符对于接口来说都是隐式的,你真的不需要指定它们中的任何一个。

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

interface字段自动变成final(常量)的原因是为了防止不同的实现意外地改变接口变量的值,这可能会无意中影响其他实现的行为。想象一下下面的场景,一个interface属性没有被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中加载的,那么NuclearAction的行为可能会受到另一个类CleanAction的影响,当CleanActionperformAction()CleanAction的执行之后被调用时(在同一个线程中或以其他方式),这在这种情况下可能是灾难性的(从语义上来说)。

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

刚刚在Eclipse中尝试过,interface中的变量默认为final,所以不能更改它。与父类相比,变量绝对是可变的。为什么?在我看来,class中的变量是一种属性,它会被孩子继承,孩子可以根据自己的实际需要来改变它。相反,接口只定义行为,不定义属性。在接口中放入变量的唯一原因是将它们作为与该接口相关的常量使用。然而,根据以下摘录,这并不是一个好的做法:

在Java早期,在接口中放置常量是一种流行的技术,但现在许多人认为这是一种令人讨厌的接口使用,因为接口应该处理对象提供的服务,而不是它的数据。同样,类使用的常量通常是实现细节,但将它们放在接口中会将它们提升到类的公共API。”

我也试过要么放静电要么不放根本没有区别。代码如下:

public interface Addable {
static int count = 6;


public int add(int i);


}


public class Impl implements Addable {


@Override
public int add(int i) {
return i+count;
}
}


public class Test {


public static void main(String... args) {
Impl impl = new Impl();


System.out.println(impl.add(4));
}
}

因为:

Static:因为我们不能有接口的对象,所以我们应该避免使用对象级成员变量,而应该使用类级变量,即静态变量。

Final:这样变量的值就不会有歧义(Diamond问题-多重继承)。

根据文档,接口是契约而不是实现。

参考:Abhishek Jain在quora上的回答

接口:系统需求服务。

在接口中,变量默认由公共的,静态的,决赛访问修饰符赋值。 因为:< / p >

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

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

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

我觉得所有这些答案都没有抓住OP问题的重点。 OP没有要求确认他们的声明,他们想知道为什么他们的声明是标准 回答这个问题需要一些信息。 首先,让我们谈谈遗传。 假设有一个名为a的类,其实例变量名为x.

创建类a时,它继承Object类的所有属性。在您不知情的情况下,当您实例化A时,您也实例化了一个Object对象,而A指向它作为它的父对象。

现在假设你创建了一个类B,它继承了a。

当你创建一个类B时,你也创建了一个类a和一个对象。 B可以访问变量x,这意味着B.x和B.A.x是一样的,Java只是为你隐藏了抓取A的魔力

不让我们谈论接口… 接口不是继承。如果B要实现Comparable接口,B不会创建Comparable实例并将其称为父实例。相反,B承诺拥有Comparable所拥有的东西

我们在这里不谈一点理论……接口是一组你可以用来与某物交互的函数。它不是事物本身。例如,你通过与朋友交谈、分享食物、跳舞、靠近他们来与他们交流。但是你不能继承它们——你没有它们的副本。

接口类似。只有一个接口,所有对象都与它相关联。由于接口作为一个类只存在一次(与它自身的实例相反),因此实现该接口的每个对象都不可能拥有自己的接口副本。这意味着每个变量只有一个实例。这意味着变量由所有使用该接口的类共享(也称为静态)。

至于我们为什么要公开它们… 私人是没用的。函数是抽象的,内部不能有任何代码来使用私有变量。它永远不会被使用。如果变量被标记为受保护,那么只有类的继承者才能使用这些变量。我不认为你可以从接口继承。那么公开是唯一可行的选择

剩下的唯一设计决策就是“最终”。您可能打算在一个类的多个实例之间更改共享变量。(例如:也许你有5个玩家在玩大富翁,你想要一个棋盘存在,这样你就可以让所有的玩家都满足界面和一个单一的共享棋盘——可能你想要根据玩家的功能来改变棋盘……)[我不推荐这种设计]

但是对于多线程应用程序,如果你不把变量设置为静态的,你以后会有困难,但我不会阻止你。去做吧,然后学习为什么那样会伤害你

就是这样。最终公共静态变量