在 Class 中初始化在接口中声明的 Java 集合

Initialize a Java Collection in Class that was declared in Interface

在接口中声明了一个Vector并将其设置为null,想稍后在实现接口的class中初始化它,java下面的代码出错了,我怎么能以其他方式初始化它?

import java.util.Vector;

interface machine {
    Vector<Integer> temp = null;
    public int compute();
}

class App implements machine {
    App(Vector<Integer> x) {
        //error here, can't assign value to temp as it is declared in interface, any other way of initializing??
        temp = x;
    }

    @Override
    public int compute() {
        int sum = 0;
        for (int x : temp) {
            sum += x;
        }
        return sum;
    }
}

public class Finals {
    public static void main(String[] args) {
        Vector<Integer> x = new Vector<>();
        for (int i = 0; i < 10; i++) {
            x.add(i);
        }
        App a = new App(x);
        System.out.println(a.compute()); 
    }
}

根据我的理解,您不能这样做,因为接口变量是静态最终的,因此您必须在接口本身中进行初始化。

Java 语言在设计时考虑了以下想法:

  • 字段从未真正被视为类型“public API”的一部分。是的,可以编写 public 字段并可以从外部对其进行修改,但是几乎没有 java 代码可以做到这一点,而且许多语言特性根本不支持它。例如,方法引用存在(someExpr::someMethodName 是合法的 java),但是没有字段引用这样的东西。

  • 接口存在传达API - 传达类型应该能够做什么,它是不是 旨在传达如何 的事情。换句话说,接口(因此得名)是,实现号。

将这两个概念加在一起,您就会明白为什么您想要的(在界面中放置一个字段)不受支持。字段不是接口的一部分(规则 #1),因此它必须是实现,接口不能携带实现细节(规则 #2),因此:你不能将字段放在接口中.

因此,java 语言规范规定接口中的任何字段声明本质上都是 public static final - 它是一个常量。你不能让它成为 not-public-static-final - 将 private 作为修饰符放在它上面是编译器错误。没有表示 'unstatic'.

的修饰符

您有 2 个选择:

  • 您打算将该字段仅用作实现:您决定实现此接口的 所有 class 将需要此字段,因此,可能以及在界面中声明它并保存输入,对吗?那么,您在那里所做的是将 实现 的共同方面组合在一起。 Java 支持这一点,但 仅在摘要中 classes。这种情况一直发生在 java 中:有 java.util.List(接口)和 java.util.AbstractList(实现该接口的抽象 class,它提供了一堆常见的行为) 和 java.util.ArrayList(最常用的实现。它扩展了 AbstractList)。

  • 您实际上需要该字段的 'interface' 部分:您想在接口文件本身(通过 default 方法)或代码中编写一些代码接收类型为您的 machine 接口的对象,并希望直接访问该字段。在罗马时,像罗马人一样行事。编程时 java,像其他 java 程序员一样工作。这意味着:不要将字段视为接口 - 如 API。如果 'a machine' 的本质(也就是说:一个对象是 class 的一个实例,并且 class 实现了 machine)是它可以提供一个表示 temp 概念的整数列表,然后 使接口的一部分 :在接口中写入 Vector<Integer> getTemp;,并让每个实现 class 提供一个实现。如果您期望所有实施 classes 可能只是想要:

private Vector<Integer> temp;

public Vector<Integer> getTemp() {
  return temp;
}

然后你可以把它放在实现接口的抽象 class 中,并让你所有的实现实现抽象 class.

如果这一切都在你的脑海中飞来飞去,我可以让它更简单:

  • 无论你写不写,接口里的所有字段decls都必然是public static final。您不能声明不是的字段,语言根本不允许您这样做。
  • 这是有充分理由的 - 请参阅上面的解释。

注意:

您似乎使用了一些非常过时的(此时至少有 25 年了!!)指南。因此,此代码不会通过任何审查。 Vector 已过时,不应使用,并且已过时 20 年:你想要 ArrayList,大概。 Java 约定规定 TypesGoLikeThis、methodNamesLikeThis、variableNamesAlsoLikeThis 和 CONSTANTS_LIKE_THIS。因此,它将是 public interface Machine,而不是 public interface machine。编译器可以让你做任何你想做的事,但如果你不遵守约定,当你将它与任何其他 java 代码集成时,你的代码会变得不必要地奇怪和不方便。