奇怪的数组返回类型

73

有没有人看过这样在方法签名后面放置的数组[]

public static String mySplit(String s)[] {
    return s.split(",");
}

public static void main(String... args) {
    String[] words = mySplit("a,b,c,d,e");
    System.out.println(Arrays.toString(words));
}

打印

[a, b, c, d, e]

过去,一些奇怪的符号可能是为了与"C"兼容,但我也不想象有人会用C语言编写这个。

有人知道为什么允许这样做吗?

我正在使用Java 7更新10,如果有影响请告诉我。

在Java 6中也可以实现相同的功能。http://ideone.com/91rZV1


顺便说一句,这段代码没有编译通过,我也不指望它能编译通过。

public static <T> List mySplit(String s)<T> {
    return Collections.emptyList();
}

3
我可以想象一个C程序员写下这个可怕的代码。C++因其类型语法而闻名,特别是数组类型,尤其是与函数指针类型结合使用时更为奇怪。 - John Dvorak
1
请注意,“inx x [10]”与此问题完全相同,只是不太夸张。 - John Dvorak
1
@RomanC 我认为一个类既拥有 toString 方法又拥有 static toString(String) 方法没有问题。但是,你是正确的 - 我没有注意到这个调用或者觉得方法名有问题。 - John Dvorak
我仍在运行JDK 1.6.0_32,不知道为什么。 - Roman C
1
当我学习Java时,“javap”默认会这样做。它总是让我感到困惑(并且使输出的阅读更加棘手)。 - Owen
显示剩余10条评论
6个回答

90

有人知道为什么允许这样做吗?

在这种情况下,这是为了与Java本身的向后兼容性而允许的。参见JLS第8.4节

为了与Java SE平台旧版本兼容,声明返回数组的方法被允许在形式参数列表之后放置(全部或部分)形成数组类型的空括号对。这受到以下过时产生式的支持,但不应在新代码中使用。

是的,你确实应该把它看作是一种败笔,除了惊吓其他开发人员外,没有任何好处。实际上,你可以在聚会上打赌它能编译通过,与从未见过这种语法的人竞猜......

这里是正常程序员认为无效的方法的示例:

public String[] mwahahaha(String[] evil[])[] {
    return evil;
}

1
@PeterLawrey 为什么不用(String[]... evil[])呢? - John Dvorak
3
@PeterLawrey 说:“我尝试混合两种方式,但遇到了错误信息:"variable-arity parameter 上不允许使用传统的数组符号"。” - Jon Skeet
@PeterLawrey 我反对白名单/黑名单特定代码的整个想法。好像在IDE中简单地覆盖不足以解决问题... - John Dvorak
4
大多数开发者都很擅长忽略静态分析和编译器警告,据我观察。 - Peter Lawrey
1
@PeterLawrey 在左侧装订线上只有一个“简单”的黄色三角形和整个方法名称上的实心黑线之间存在差异。你不容易错过后者。 - John Dvorak
显示剩余11条评论

20

就像这样

  String[] a; 

相同。

  String a[];

方法返回类型的语法同样适用

  public static String mySplit(String s)[] {

等同于

  public static String[] mySplit(String s) {

但是我认为我从未在实际代码中看到你提到的那个版本。


2
我也从未见过它;如果需要,我会发布到TDWTF。 - John Dvorak

6

我认为以下变量声明等价的原因是相同的

String[] array
String array[]

这是C开发人员经常做的一件事情,因此它被包含在内以帮助他们。


2
这是C开发人员经常做的事情,因此它被包含在内以帮助他们。如果您有关于这个特定点的文献资料,我想要指针,这可能是一篇有趣的阅读!(尤其是因为我之前确实做过C,但一开始就无法理解Java符号) - fge

4

我认为这只是告诉Java返回类型是一个字符串数组,与声明相同。

static String[] mySplit(String s) {...

类似于声明变量:

String myStringArray[];

等同于

String[] myStringArray;

4

好问题;当我实现一个Java解析器时,我记得在这一点上被JLS语法搞得很困惑。

为了扩展John的答案,以下是正在发生的事情:

这至少涉及到5个地方:

  • 方法类型签名
  • 局部变量声明
  • 字段声明
  • 形式参数
  • for循环

以下是从语法中摘录的关于方法声明的一节:

MethodOrFieldDecl:
    Type Identifier MethodOrFieldRest

MethodOrFieldRest:  
    FieldDeclaratorsRest ;
    MethodDeclaratorRest

MethodDeclaratorRest:
    FormalParameters {[]} [throws QualifiedIdentifierList] (Block | ;)

Type:
    BasicType {[]}
    ReferenceType  {[]}

这表明[]既可以出现在Type规则下,也可以作为MethodDeclaratorRest规则的一部分。在两个位置上都是可选的。(警告:由于方括号和花括号有时是字面意义,有时是元字符,因此语法很难阅读。)

1

是的,这是允许的,

原因相同:

String[] myArray;

等同于

String myArray[];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接