Java接口无法实例化却能运行?解析背后实现原理
我在学习Spring松耦合特性时遇到一个困惑:理论上Java接口无法被实例化,但我接触到一段代码,其中GameRunner类中定义了private GamingConsole game;这样的接口类型变量,且代码能够正常运行。相关代码如下:
定义的接口
public interface GamingConsole { void up(); void down(); void left(); void right(); }
包含接口变量的GameRunner类
public class GameRunner { private GamingConsole game; // 我以为这里是在实例化接口 public GameRunner(GamingConsole game) { this.game = game; } public void run() { System.out.println("Running Game" + game); game.up(); game.down(); game.left(); game.right(); } }
调用类
public class AppGamingBasicJava { public static void main(String[] args) { // var game = new MarioGame(); // var game = new SuperContraGame(); var game = new PacManGame(); var gameRunner = new GameRunner(game); gameRunner.run(); } }
我想知道这段代码实际在做什么,为何看似实例化接口却能正常运行,以及代码的具体运行机制。
解答
变量声明≠实例化
private GamingConsole game;只是声明了一个接口类型的变量,并没有实例化接口。接口类型的变量相当于一个"通用引用",它可以指向任何实现了该接口的具体类实例,这是Java多态特性的核心用法。真正的实例化在调用类中
AppGamingBasicJava的main方法里,var game = new PacManGame();才是实例化操作——PacManGame必然是实现了GamingConsole接口的具体类(它会重写接口中所有抽象方法)。这个具体类的实例被赋值给GamingConsole类型变量,完全符合Java的多态规则。GameRunner的执行逻辑
当把PacManGame实例传入GameRunner的构造方法后,GameRunner中的game变量就指向了这个具体实例。调用gameRunner.run()时,实际执行的是PacManGame中重写的up()、down()等方法,接口本身没有方法实现,不会被执行。松耦合的核心体现
GameRunner只依赖GamingConsole这个抽象接口,不关心具体是哪个游戏类。不管是换成MarioGame还是新增其他实现了接口的游戏类,都不需要修改GameRunner的代码,这就是Spring松耦合特性的基础——依赖抽象而非具体实现,大幅提升代码的扩展性和可维护性。
内容的提问来源于stack exchange,提问作者Jitin Kumar

