为什么在Java中默认情况下接口变量是静态变量和最终变量?
为什么在Java中默认情况下接口变量是静态变量和最终变量?
Answers:
从Philip Shaw的Java接口设计常见问题解答中:
接口变量是静态的,因为不能单独实例化Java接口。必须在不存在任何实例的静态上下文中分配变量的值。final修饰符确保分配给接口变量的值是一个真正的常量,不能由程序代码重新分配。
static
修饰符的解释完全是虚假的。类的公共实例变量是其接口的一部分,没有理由不应该interface
像实例方法那样在Java中抽象它们。interface
不能直接实例化Java 没关系-您仍然可以拥有实现的类的实例,interface
明智的是要求它们具有某个公共实例变量。关于的部分final
完全没有提供解释-只是描述了什么final
意思。
由于interface没有直接的对象,因此访问它们的唯一方法是使用类/接口,因此这就是为什么如果interface变量存在,则它应该是静态的,否则它将根本无法被外界访问。现在,由于它是静态的,因此它只能保存一个值,实现它的任何类都可以更改它,因此将一团糟。
因此,如果根本没有接口变量,它将是隐式静态的,最终的并且显然是公共的!
interface
。一个类将实现该接口,并声明实例变量(根据接口的要求)。它的构造函数(或其他方法)设置实例变量。当实例化该类的实例时,您将能够访问其实例变量。
(这不是哲学上的答案,而是更多实际的答案)。static
修饰符的要求是显而易见的,已被其他人回答。基本上,由于无法实例化接口,因此访问其字段的唯一方法是使它们成为类字段- static
。
的背后的原因interface
字段自动成为final
(常数)是为了防止不同的实现意外更改接口变量的值可无意中影响其它实施方式的行为。想象一下下面的场景,其中一个interface
属性没有final
被Java 明确地变成:
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
时,其行为可能会受到另一个类的影响,这在情况下可能是灾难性的(显然是)。performAction()
CleanAction
由于我们不知道an的每个实现interface
将如何使用这些变量,因此它们必须隐式为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
我认为这是接口变量是静态的原因之一。
不要在Interface内部声明变量。
static final
在实际为static和final的变量之前看到未编写的代码。
因为:
Static
:因为我们没有接口的对象,所以我们应该避免使用对象级别的成员变量,而应该使用类级别的变量,即静态的。
Final
:,这样我们就不会为变量设置不明确的值(钻石问题-多重继承)。
而且根据文档界面,这是合同而非实施。
参考:Abhishek Jain 对quora 的回答
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
该变量不同于实例变量。
刚刚在Eclipse中尝试过,interface中的变量默认为final,所以您不能更改它。与父类相比,变量肯定是可变的。为什么?在我看来,class中的变量是一个将由孩子继承的属性,孩子可以根据他们的实际需要对其进行更改。相反,接口仅定义行为,而不定义属性。在接口中放入变量的唯一原因是将它们用作与该接口相关的const。不过,根据以下摘录,这不是一个好习惯:
“在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));
}
}