JEP 463:隐式声明的类和实例主要方法(第二预览版)
概括
发展 Java 编程语言,以便学生可以编写他们的第一个程序,而无需了解为大型程序设计的语言功能。学生无需使用单独的语言方言,而是可以为单类程序编写简化的声明,然后随着技能的增长无缝扩展他们的程序以使用更高级的功能。这是预览语言功能。
历史
JEP 445提出了_未命名类和实例main
方法_,该功能已在 JDK 21 中预览。反馈表明该功能应在 JDK 22 中第二次预览,并进行以下重大更改,因此需要修改标题。
-
允许类未命名以及允许没有封闭类声明的源文件隐式声明未命名类的想法主要是一种规范设备,以确保该类不能被其他类使用。然而,这已被证明是一种干扰。我们采用了一种更简单的方法:没有封闭类声明的源文件被认为隐式声明了一个由主机系统选择的名称的类。此类隐式声明的类的行为类似于普通的顶级类,并且不需要额外的工具、库或运行时支持。
-
选择要调用的方法的过程
main
过于复杂,既要考虑该方法是否有参数,又要考虑它是静态方法还是实例方法。在第二个预览中,我们建议将选择过程简化为两个步骤: 如果存在main
带有String[]
参数的候选方法,则我们调用该方法;否则我们调用不带参数的候选main
方法。这里没有歧义,因为类不能声明相同名称和签名的静态方法和实例方法。
目标
-
为 Java 编程提供一个平稳的入门通道,以便教师可以循序渐进地介绍概念。
-
帮助学生以简洁的方式编写基本程序,并随着他们的技能增长而优雅地扩展他们的代码。
-
减少编写简单程序(例如脚本和命令行实用程序)的仪式。
-
不要引入单独的 Java 语言初学者方言。
-
不要引入单独的初学者工具链;学生程序应该使用与编译和运行任何 Java 程序相同的工具来编译和运行。
动机
Java 编程语言非常适合大型团队多年来开发和维护的大型复杂应用程序。它具有丰富的数据隐藏、重用、访问控制、命名空间管理和模块化功能,允许组件在独立开发和维护的同时干净地组合。借助这些功能,组件可以公开定义良好的接口,以便与其他组件交互,同时隐藏内部实现细节,以便允许每个组件独立发展。事实上,面向对象范式本身就是为了将通过明确定义的协议进行交互的各个部分插入在一起而设计的,并抽象出实现细节。这种大型组件的组合称为_大型编程_。该语言还提供了许多对_小型编程_有用的结构——组件内部的一切。近年来,我们既增强了模块的大编程能力,又增强了面向数据编程的小编程能力。
然而,Java 编程语言也旨在成为第一语言。当程序员刚开始时,他们不会在团队中编写大型程序 - 他们单独编写小程序。它们不需要封装和命名空间,这对于单独发展不同人编写的组件很有用。在教授编程时,教师从变量、控制流和子例程等基本编程概念开始。在此阶段,不需要类、包和模块的大概念进行编程。让该语言更受新手欢迎符合 Java 老手的利益,但他们也可能会发现更简洁地编写简单的程序而不需要任何大型脚手架编程是令人愉快的。
考虑一下经典的《你好,世界!》经常被Java学生用作第一个程序的程序:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
对于程序的功能来说,这里有太多的混乱——太多的代码、太多的概念、太多的构造。
-
声明
class
和强制public
访问修饰符是大型编程结构。当用外部组件的定义良好的接口封装代码单元时,它们很有用,但在这个小例子中毫无意义。 -
该
String[] args
参数还用于将代码与外部组件(在本例中为操作系统的 shell)连接。它在这里很神秘且没有帮助,特别是因为它不用于像HelloWorld
. -
修饰符
static
是语言的类和对象模型的一部分。对于新手来说,static
这不仅是神秘的,而且是有害的:要添加更多main
可以调用和使用的方法或字段,学生必须要么将它们全部声明为static
——从而传播一种既不常见也不是好习惯的习惯用法——或者面对之间的区别静态和实例成员并学习如何实例化对象。
新程序员在最糟糕的情况下遇到这些概念,在他们了解变量和控制流之前,并且在他们无法理解大型编程结构对于保持大型程序良好组织的效用时。导师经常告诫我们:“别担心,稍后你就会明白的。”这让他们和他们的学生都不满意,并给学生留下了语言复杂的持久印象。
这个 JEP 的动机不仅仅是为了减少仪式。我们的目标是帮助刚刚接触 Java 语言或一般编程的程序员以按正确顺序介绍概念的方式学习该语言:从基本的小型编程概念开始,然后继续高级当大型概念确实有益并且更容易掌握时,就可以使用它们。
我们建议不要通过改变 Java 语言的结构来做到这一点——代码仍然包含在方法中,方法包含在类中,类包含在包中,包包含在模块中——而是隐藏这些细节,直到它们在更大的程序。我们提供一个入口匝道,一个逐渐倾斜的斜坡,优雅地融入高速公路。当学生进入更大的项目时,他们不需要放弃他们在早期阶段学到的东西,而是他们会看到这一切如何融入更大的图景。
我们在此提供的更改只是使 Java 语言更易于学习的第一步。他们甚至没有解决_“Hello, World!”_中的所有减速带问题。程序:初学者可能仍然对神秘的System.out.println
咒语感到困惑,即使在第一周的程序中,仍然需要导入基本的实用程序类来实现基本功能。我们可能会在未来的 JEP 中解决这些难题。
描述
首先,我们增强了启动 Java 程序的协议,以允许_实例 main 方法_。这些方法不是static
、不需要public
、也不需要有String[]
参数。然后我们可以简化_Hello, World!_编程为:
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}
其次,我们允许编译单元(即源文件)_隐式声明_一个类:
void main() {
System.out.println("Hello, World!");
}
这是预览语言功能,默认禁用
要在 JDK 22 中尝试以下示例,您必须启用预览功能,如下所示:
-
使用 编译程序
javac --release 22 --enable-preview Main.java
并使用java --enable-preview Main
;运行它或者, -
使用源代码启动器时,运行程序
java --source 22 --enable-preview Main.java
启动协议
新程序员只想编写和运行计算机程序。然而, Java语言规范package
侧重于定义类的核心 Java 单元和基本编译单元,即由声明、后跟一些import
声明、后跟一个或多个声明组成的源文件class
。关于 Java_程序_,它所要说的就是:
Java 虚拟机通过调用某个指定类或接口的方法来开始执行
main
,并向其传递一个字符串数组的参数。
JLS 进一步指出:
向 Java 虚拟机指定初始类或接口的方式超出了本规范的范围,但在使用命令行的主机环境中,通常会指定要指定的类或接口的完全限定名称作为命令行参数,并且以下命令行参数用作要作为方法参数提供的字符串
main
。
main
选择包含该方法的类、以模块路径或类路径(或两者)的形式组装其依赖项、加载该类、初始化它以及使用main
其参数调用该方法的操作构成了_启动协议_。在JDK中,它是由_启动器_(java
即可执行文件)实现的。