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

时间:2014-07-07 15:35:08

标签: java syntax

我试图从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 in a class definition和其他相关问题。

提前致谢。

5 个答案:

答案 0 :(得分:22)

  

我编译并执行了为Java显示的两个程序片段,它们都有效。谁能解释为什么会这样呢?

这是允许的,因为Java Grammar说它是允许的;请参阅JLS 7.6

  

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

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

JLS解释如下:

  

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


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

答案 1 :(得分:10)

在早期,允许这是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:
    ;

答案 2 :(得分:7)

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

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

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

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

分号被简单地视为一个无效的空声明。

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

  

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

如你所见,这真的只适合像你这样的人:)。

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

class X {
   // Member variables
   private int i;

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   // Constructors
   X(){}

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   // Methods
   void foo(){}    

}

答案 3 :(得分:0)

我认为这是一种继承自C:

的风格
struct A
{ 
    unsigned a;
    unsigned b;
};

或者您可以使用:

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

答案 4 :(得分:-2)

我不熟悉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...
}