为什么分号不是必需的,但在类定义结束时允许使用分号?

我正试图从C ++转向Java。

我想知道,在C ++中,在类定义之后,需要使用分号( ; ),但在Java中则不是。

也就是说,在C ++中:

 class Person { public: string name; int number; }; // Note this semicolon 

但在Java中:

 class Person { public String name; public int number; } // Semicolon is not required 

那很好,我理解。

但是, 我的问题是

当我在类定义结束时添加分号时,Java也可以工作,如:

 class Person { public String name; public int number; }; // Now this semicolon is confusing me! 

我编译并执行了为Java显示的程序片段,它们都有效。 任何人都可以解释为什么会这样吗? Java中类定义结尾的分号代表什么?

如果这个问题质量低,我很抱歉,但我真的需要澄清一下。 我希望Java专家能帮助我。

好吧,我已经在课堂定义和其他相关问题中看到过Semicolons 。

提前致谢。

我编译并执行了为Java显示的程序片段,它们都有效。 任何人都可以解释为什么会这样吗?

这是允许的,因为Java语法说它是允许的; 见JLS 7.6 。

Java中类定义结尾的分号代表什么?

没有。 它是可选的“语法噪音”。

JLS解释如下:

额外的“;” 出现在编译单元中类型声明级别的标记对编译单元的含义没有影响。 Java编程语言中允许使用杂散分号,仅作为对习惯于放置“;”的C ++程序员的让步。 在课堂宣言之后。 它们不应该用在新的Java代码中。


(请注意,这不是一个“空语句”。空语句( JLS 14.6 )出现在允许语句的语法上下文中。空语句的存在可以改变代码的含义;例如if (a == b) ; c();if (a == b) c();

在早期,允许这是Java使C / C ++程序员更熟悉的方式之一。 这种熟悉程度对于采用Java非常重要。

这是它在语法上的工作原理。

根据JLS 7.3 , 在顶级类之后,它起作用,因为编译单元包含此序列:

 CompilationUnit: PackageDeclaration(opt) ImportDeclarations(opt) TypeDeclarations(opt) 

根据JLS 7.6 ,类型声明是以下任何一种:

 TypeDeclaration: ClassDeclaration InterfaceDeclaration ; 

在一个成员类之后,嵌套在其他类中,它起作用,因为分号可以是类成员声明,​​根据JLS 8.1.6 :

 ClassMemberDeclaration: FieldDeclaration MethodDeclaration ClassDeclaration InterfaceDeclaration ; 

在一个本地类之后,在一个方法中,它起作用,因为分号可以是一个空语句,根据JLS 14.6 :

 EmptyStatement: ; 

Java只为那些从C ++切换的人添加了这个!

在Java中,单个分号是一个几乎可以在任何地方编写的声明。 它的唯一目的是简化这些语言的过渡。

例如,Java中的以下内容也是正确的:

 ;;;;;;;;;; class X{ ;;;;;;;;;;;;;; } ;;;;;;;;;;;;;;; 

分号被简单地视为空的声明,什么都不做。

以下是规范第7.6段的引用:

额外的“;” 出现在编译单元中类型声明级别的标记对编译单元的含义没有影响。 Java编程语言中允许使用杂散分号, 仅作为 对习惯于放置“;”的C ++程序员 让步。 课堂宣言之后。 它们不应该用在新的Java代码中。

所以你看,这真的只适合像你这样的人:)。

你甚至可以使用一行分号作为一个很好的视觉分离。 但是,我强烈建议不要这样做。 但它可能有利于吹牛的目的。 例如:

 class X { // Member variables private int i; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; // Constructors X(){} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; // Methods void foo(){} } 

我认为这是从Cinheritance的跟随风格:

 struct A { unsigned a; unsigned b; }; 

或者您可以使用:

 struct A { unsigned a; unsigned b; }A1,A2; 

我不熟悉Java,但是需要额外分号的原因是因为你可以在函数内部定义一个匿名类。 例如:

 void routine(const int x, const int y) { class { public: int x; int y; } my_instance; my_instance.x = x; my_instance.y = y; // ... etc } 

你通常会看到结构比使用类更多,以捕获大类的一些重要变量。

 void f(const BigClass& big_class) { struct { std::string str; int i; } props; props.str = big_class.GetFilename(); props.i = big_class.GetID(); // etc... }