Java/C#中声明的顺序是否重要?

7

在C++中,如果我在调用方法之后声明该方法,则不能使用该方法。

在其他语言中,如Java或C#,这个顺序是否重要?


1
请分别发布Java和C#的问题。以目前的形式,您的查询对于Stack Overflow来说过于宽泛。 - Cœur
12个回答

32

在C#或Java中,方法的声明顺序永远不重要。同样,无论您在变量之前或之后声明一个方法,都没有关系。

然而,当变量初始化相互依赖时(例如在C#中),变量的声明顺序可能会有所影响:

using System;

class Test
{
    static int x = 5;
    static int y = x;

    static void Main()
    {
        // Prints x=5 y=5
        Console.WriteLine("x={0} y={1}", x, y);
    }
}

但是:

using System;

class Test
{
    static int y = x;
    static int x = 5;

    static void Main()
    {
        // Prints x=5 y=0
        Console.WriteLine("x={0} y={1}", x, y);
    }
}

Java防止了这个确切的情况,但模仿起来很容易:

public class Test
{
    static int y = getInitialValue();
    static int x = 5;

    public static void main(String args[])
    {
        System.out.println("x=" + x + " y=" + y);
    }

    static int getInitialValue()
    {
        return x;
    }
}

当你涉及到部分类(partial classes)时,C#中的事情变得更加混乱。在C#中,初始化按照文本顺序进行,但是当多个文件为同一个类做出贡献时,这个顺序并没有被完全定义。

不用说,尽可能避免使用部分类!


27
没有。

5
简短而简洁,别有一番风味。 - David Christiansen
2
不用了,只是简单的 Yes/No 问题而已,没必要那么多。 - chrissie1
3
句号前面的空格是不必要的,并且会让答案看起来凌乱。我建议去掉它,避免给人带来不必要的疑惑。 - William Brendel
2
我正在努力去除那个空白。修剪后的最小响应长度为10(可能有很好的原因)。我的答案实际上是No_______。我正在考虑发布一个StackOverflow问题,看看是否有人可以帮助我。 - Dan Fish
3
如果其他人发表了相反的观点,没有解释,这个回答可能会变得无用。例如,如果有人发表了像“是的”的主张,这个回答将如何帮助读者选择两种对立的观点?考虑修改它,使其更符合答案指南。 - gnat
显示剩余2条评论

5
不,编译器进行了两次扫描。

2
在Java和C#中,没有单独的方法声明。方法的声明与其实现一起完成。只要它们在同一个命名空间中,您也不需要跟踪文件包含情况,以便类知道彼此。

1
对于Java来说,权威答案隐藏在Java语言规范(“JLS”,第3版,在线免费查看)的第1章(介绍)中:
声明顺序仅对局部变量、局部类以及类或接口中字段初始化器的顺序有意义。

0

在某些边角情况下,Java中方法/构造函数的顺序确实很重要:

class Callee {
    private static void bar(int i) { } // compilation error if first
    public static void bar(String s) { } // ok if this method is first
}

class Caller {
    private void foo() { Callee.bar(bar()); }
    private <T> T bar() { return null; }
}

0
这些答案存在冲突,使事情难以理解。最佳实践是按照常识的时间顺序声明你的方法、变量等,这样就不会混淆,并且这适用于所有编程语言。你的main总是第一个,所以它可以在开头或结尾,但仍然应该从main开始,当你在main中调用一个方法时,它应该紧接着main之后,依此类推。至少对我来说,这是最有意义的,也使代码最易读(注释也很有帮助,因为让我们面对现实,代码真的很难懂)。虽然我不是编码专家,但我知道任何算法的最佳实践是将其拆分为尽可能简单的步骤(请加上注释)。这没有意义:
   final List<int[]> intArrays = Arrays.stream(testarray).collect(Collectors.toList());
   final List<Integer> integers = intArrays.stream().flatMap(z -> 
                  Arrays.stream(z).boxed()).collect(Collectors.toList());

unless you add comments like:
final List<int[]> intArrays = Arrays.stream(testarray).collect(Collectors.toList());
// this makes a List (of ints) variable type that cannot be changed based on the stream of 
//(the testarray in this case) and uses the Collector method to add the ints
//to intArrays (our variable name)
final List<Integer> integers = intArrays.stream().flatMap(z -> 
                  Arrays.stream(z).boxed()).collect(Collectors.toList());
// I would have to look this up, because I honestly have no clue what it does exactly. 

就像我说的,代码基本上是胡言乱语。不管用什么编程语言,帮助自己和其他可能查看你代码的人,按照逻辑顺序编写代码(并且,请使用注释!你以后会感谢我的)。

0

有一种棘手的情况,即在词法上要调用的函数可以在调用点之后声明,但在语义上不行。这是因为类被认为在类成员函数的主体中完全定义。

$9.2.2 - “在类说明符的结束}处,类被视为完全定义的对象类型(3.9)(或完整类型)。在类成员说明中,在函数体、默认参数和构造函数ctor-initializers(包括嵌套类中的这些内容)中,类被视为完整的。否则,在其自己的类成员说明中,它被视为不完整。”

struct A{
    void f(){g();}    // OK to call 'g' even if the compiler has not seen 'g' as yet
    void g(){};
};

int main(){
    A a;
    a.f();
}

0

我不确定C#,但是在Java中你可以。


0

这不是C#语言。


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