奇怪的数组返回类型


72

有没有人看到[]像这样在方法签名之后放置的数组?

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 update 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

该代码甚至无法编译。
Roman C

1
@RomanC我看不到一类同时具有toString和的问题static toString(String)。但是,您是对的-没有注意到此调用或发现方法名称可疑。
John Dvorak

1
当我学习Java时,“ javap”默认情况下会这样做。它总是使我困惑为什么(并使读取输出变得更加棘手)。
Owen

Answers:


90

有谁知道为什么甚至允许这样做?

在这种情况下,它是为了与Java本身向后兼容。从JLS 8.4节开始

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

是的,您确实应该将其视为可憎之物,除了震撼其他开发人员之外,没有其他目的。实际上,您可以通过押注它可以编译来对抗从未见过的人们,以此来赢得聚会上的一些钱...

这是有头脑的编码人员期望无效的一种方法:

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

@ nicholas.hauschild我在星期四与一群Java开发人员共进晚餐。这几乎是必须的。;)
Peter Lawrey 2013年

1
@PeterLawrey为什么不(String[]... evil[])呢?
John Dvorak 2013年

3
@PeterLawrey:我尝试将两者混合使用,但得到:“可变数组参数不允许使用传统数组表示法”
Jon Skeet

4
@JanDvorak大多数开发人员都擅长忽略我发现的静态分析和编译器警告。
彼得·劳瑞

1
@PeterLawrey左装订线中的“仅”黄色三角形与整个方法名称上的黑色实线之间存在区别。您不能轻易错过后者。
John Dvorak

19

就像是

  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返回类型是的数组Strings,与声明相同

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

类似于声明变量:

String myStringArray[];

相当于

String[] myStringArray;

4

好问题; 当我实现Java解析器时,我记得此时对JLS语法感到非常困惑。

为了扩展约翰的答案,这是正在发生的事情:

  • 这就是所谓的“混合符号”在规范中
  • 语法符类型声明成两片,其中的每一个可以具有0个或多个[]小号

至少有5个地方很重要:

  • 方法类型签名
  • 局部变量声明
  • 现场申报
  • 形式参数
  • for循环

以下是语法摘录,重点介绍方法声明:

MethodOrFieldDecl:
    Type Identifier MethodOrFieldRest

MethodOrFieldRest:  
    FieldDeclaratorsRest ;
    MethodDeclaratorRest

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

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

(警告:语法很难阅读,因为方括号和大括号有时是文字,有时是元字符。)

这表明[]Type规则既可以在规则下也可以作为MethodDeclaratorRest规则的一部分出现。在两个地方都是可选的。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.