为什么变量可以赋值给接口类型?

Why can variables be assigned to interface type?

我是 Java 的新手,正在尝试学习界面的概念。我在网上看到了下面的代码。我知道接口不能被实例化。我的问题是,WatchService、Path、WatchKey、WatchEvent都是接口,怎么变量可以赋值给接口类型呢?和实例化一样吗?

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

public class WatchServices {

    public static void main(String[] args) throws IOException {
        WatchService ws1 = FileSystems.getDefault().newWatchService();

        Path p1 = Paths.get("/Users/justin/Desktop/Codes Netbean/JavaRandom");

        WatchKey wk1 = p1.register(ws1, ENTRY_CREATE);

        while(true){
            for(WatchEvent<?> event : wk1.pollEvents()){
                System.out.println(event.kind());
                Path file  = (Path)event.context();
                System.out.println(file);
            }
        } 
    }
}

接口定义了一组可以调用的方法,但并不实现它们。这就是为什么你永远不能说 Runnable x = new Runnable()。可以定义一个class,它实现了接口中的所有方法。它还必须声明它实现了该接口:

interface Runnable {
    public void run();
}

public class RandomTask implements Runnable {
    public void run() {
        System.out.println("Doing some stuff...");
    }

    public void shout() {
        System.out.println("DOING STUFF...");
    }
}

查看 class 如何实现 接口。所以 RandomTask 可运行的,因此您可以在需要 Runnable 的地方分配一个 RandomTask:

Runnable x = new RandomTask();

接口告​​诉您该对象上必须存在哪些方法。我们知道 x 必须有一个 run() 方法,因为它是一个 Runnable。所以我们可以说

x.run();

现在,虽然 程序员知道 x 有一个 shout() 方法,但你不能再访问它了。通过将 x 分配给 Runnable,您将其限制为仅具有为 Runnable 定义的方法。

我举个例子来回答你。

假设我让你给我拿一个sphere。那你给我拿个沙滩球来。

球体不存在,它是一个概念,一个几何物体,沙滩球是一个material可以被认为是球体的物体。

这几乎是一回事,interface 通过其暴露的接口定义对象的特征(可以在假装 implement 该接口的对象上调用的方法)但它是不是 material 对象本身。

所以即使球体不存在,我也可以将沙滩球视为球体。实例化球体没有任何意义,因为球体无法实例化,但我可以将沙滩球视为球体。