代码之家  ›  专栏  ›  技术社区  ›  Toad

为什么不能通过实例名访问静态成员?

  •  6
  • Toad  · 技术社区  · 14 年前

    假设我有:

     class Test
     {
          public static int Hello = 5;
     }
    

    这显然有效:

     int j = Test.Hello;
    

    但这为什么不起作用呢?

     Test test = new Test();
     int j = test.Hello;
    

    实例不能有一个同名的成员,所以我看不出对于编译器来说,这可能是不明确的或不可解析的。

    有人知道这是为什么吗?

    编辑: 除了语言设计人员出于可读性/清晰性/美观性等考虑而选择这一点之外,还有其他技术原因吗?

    5 回复  |  直到 14 年前
        1
  •  14
  •   AakashM    14 年前

    另一个角度:

    假设这个 可能的。然后,当通过实例变量访问静态成员时,您希望结果是什么 null ?您想要一个空引用异常吗(但为什么,因为不需要实例来获取静态成员)?或者您希望它能够工作(在这种情况下,您会遇到一些奇怪的情况,一些对这个实例变量的调用可以工作,但有些没有工作)?不管怎样都有问题。

        2
  •  11
  •   stakx - no longer contributing Saravana Kumar    14 年前

    记住静态方法(或属性或字段)是什么:它们属于一个类,而不是该类的任何特定实例。因此,它们在所有实例之间共享。

    因此,必须通过类名而不是通过对象来访问静态成员是合乎逻辑的。很好,C语言在这方面的设计是完全不同的……但事实并非如此。

        3
  •  1
  •   D'Arcy Rittich    14 年前

    我认为它是一种防御语言设计:如果你错误地将一个属性声明为静态,然后在假定它是实例属性时从不同的实例设置/获取它,那么你可以得到各种各样的邪恶副作用,而不必有任何明显的错误迹象。

    通过要求开发人员使用类名访问静态属性,可以清楚地表明它不是实例属性,并且要求开发人员在编码时明确表示他们确实希望将其作为静态属性访问。

        4
  •  1
  •   heisenberg    14 年前

    “除了语言设计师出于可读性/清晰性/美观性等考虑而选择它之外,还有其他技术原因吗?”

    我能想到的另一个原因是它会为编译器创建额外的循环来跳过(而不是这是一个很大的问题)。如果实例可以访问静态方法调用,则实例必须存储所有静态偏移量,否则编译器必须执行额外的步骤,当无法在实例上找到非静态方法时,编译器将在类上查找具有相同签名的静态方法。

        5
  •  0
  •   Richard McGuire    14 年前

    您可以阅读 static keyword on MSDN 但我想这句话最好解释一下

    虽然类的实例包含类的所有实例字段的单独副本,但每个静态字段只有一个副本。

    我相信这可能是在编译器使用的内存地址和偏移量中路由的。根据我在学校编译器课程中的记忆,实例变量的位置将存储为与存储对象的第一个内存位置的偏移量。因为静态字段只有一个副本,所以访问静态字段值时,它永远不会是固定偏移量。

    对于名称的模糊性,这可能与符号表等内容中的名称冲突一样简单。然而,很容易有更深层次的技术考虑。