【问题标题】:Why is the semicolon not required but allowed at the end of a class definition?为什么在类定义的末尾不需要分号但允许使用分号?
【发布时间】:2014-07-07 15:35:08
【问题描述】:

我正在尝试从 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 显示的程序 sn-ps,它们都可以工作。谁能解释为什么会这样? Java中类定义末尾的分号代表什么?

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

嗯,我已经看过Semicolons in a class definition 和其他相关问题。

提前致谢。

【问题讨论】:

标签: java syntax


【解决方案1】:

我已经编译并执行了两个针对 Java 显示的程序 sn-ps,它们都可以工作。谁能解释一下为什么会这样?

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

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

什么都没有。它是可选的“句法噪音”。

JLS 解释如下:

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


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

【讨论】:

  • +1 表示明确的基本原理,似乎已在 JLS 8 中添加。
【解决方案2】:

在早期,允许这是 C/C++ 程序员更熟悉 Java 的方式之一。这种熟悉程度对于采用 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 个答案?好答案的伙伴,谢谢。 +1。
【解决方案3】:

Java 仅为像您这样从 C++ 转换而来的人添加了此功能!

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

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

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

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

这是规范第 7.6 段的引述:

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

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

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

class X {
   // Member variables
   private int i;

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

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

}

【讨论】:

  • 您介意提供 JLS 语法相关部分的参考吗?
  • 我觉得有趣的是,它实际上除了切换语言之外没有其他用途。
  • @NPE:添加,规范确实使用从 C++ 转换为分号的原因。
  • @chris:你是对的。这是添加语言功能的一个非常尴尬的原因。
  • @gexicide,我想 Java 也差不多,但我们一直在告诉人们“这不是 Java”。然后这种语法伴随着使语言感觉更接近 C++ 的基本原理。确实很奇怪。
【解决方案4】:

我认为这是一种继承自 C 的跟随风格:

struct A
{ 
    unsigned a;
    unsigned b;
};

或者你可以使用:

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

【讨论】:

    【解决方案5】:

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

    【讨论】:

    • 你有这方面的参考吗?
    • 感谢您抽出宝贵的时间,感谢您的努力。 +1。
    • @VedantTerkar 你不在乎答案是对是错吗?
    • @juanchopanza,我很在乎。但是用户仍然试图回答我的问题,他花费了宝贵的时间来满足我的查询。这就是 +1 的原因。
    猜你喜欢
    • 2013-02-05
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 2017-03-20
    • 2010-10-13
    • 2018-06-09
    相关资源
    最近更新 更多