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

问题描述 投票:14回答:5

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

提前致谢。

java syntax
5个回答
22
投票

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

这是允许的,因为Java Grammar说它是允许的;见JLS 7.6

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

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

JLS解释如下:

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


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


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:
    ;

7
投票

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

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

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

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

分号被简单地视为一个不做任何事情的空声明。

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

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

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

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

class X {
   // Member variables
   private int i;

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

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

}

0
投票

我认为这是继承自C的后续风格:

struct A
{ 
    unsigned a;
    unsigned b;
};

或者您可以使用:

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

-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...
}
© www.soinside.com 2019 - 2024. All rights reserved.