是“继承”正确的术语来解释超类的静态方法可以通过子类访问吗?

时间:2011-08-16 16:43:43

标签: java inheritance static polymorphism static-methods

澄清:这个问题不是关于访问修饰符

确认B.m()和b.m()语句都适用于以下代码:

class A {
  static void m() { //some code }
}

class B extends A {
}

class Example {
  public static void main (String [] args) {
    B.m(); // running A's m() static method
  }

  public void try() {
    B b = new B();
    b.m(); // running A's m() static method
  }
}

我的问题是我们可以说“静态方法是继承的吗?”

如果“inherited”是正确的术语,如果我们向B类添加一个方法,我们将使用相同的静态类签名:

class A {
  static void m() { //some code }
}

class B extends A {
  static void m() { //some code }
}

class Example {
  public static void main (String [] args) {
    B.m(); // running B's m() static method
  }

  public void try() {
    B b = new B();
    b.m(); // running B's m() static method

    A a = new B();
    a.m(); // running A's m() static method, no polymorphism
  }
}

在这种情况下,请注意我们没有多态,是否正确的术语表示“静态方法是继承但未重写,子类静态方法隐藏超类静态方法”?

最后怀疑,对于这两个术语,“继承”和“覆盖”,哪一个与术语“多态”直接相关?

4 个答案:

答案 0 :(得分:28)

是的,我认为“继承”在这里是正确的术语,即使它不像它那样具有描述性。来自section 8.4.8 of the Java Language Specification

  

C类继承自其直接超类,并且直接超级接口超类的所有非私有方法(无论是否为抽象)以及在与C相同的包中使用默认访问权限进行公共,保护或声明的超级接口,并且都不会被覆盖(§8.4.8.1)也没有通过集体声明隐藏(§8.4.8.2)。

那没有指定实例方法,但对允许隐藏或覆盖什么的具体限制,如果静态方法不继承。

实际上,我只是简单地将静态方法视为“无需资格即可访问”而不是其他任何东西,因为它们不参与多态等等。我认为值得非常清楚 - 例如,一个静态方法可以隐藏继承的方法,但它不能覆盖它。

换句话说,虽然我认为“继承”在技术上是正确的,但我会尽量避免使用它而不做任何进一步的解释。

对于你的第二个问题,我会说基于上面的内容,覆盖与多态性有关,但继承并不一定。

(我还强烈建议你不要在“via”变量中调用静态方法,并且在任何你指定名称的地方使用声明静态方法的类的名称.I知道这不是问题的一部分,但我想我还是要添加它......)

答案 1 :(得分:4)

我认为尝试将“继承”和“覆盖”等词语应用于此类事物并不富有成效。这是误导性的,因为它给人的印象是有一些与虚拟实例方法相似的东西,你指出没有。

(但正如Jon Skeet指出的那样,Java语言规范与我不一致,它将这些内容组合在一起。)

答案 2 :(得分:1)

伙计我想与所有java爱好者分享我在java中的知识!

首先让我告诉你静态成员是那些可以直接访问而不创建该特定类的对象的成员,当某个类的静态成员用于某个其他类时,应该通过指定它来使用它class name。(dot)静态成员的名称(例如以下示例中的Ai),以及任何子类类是否从具有静态成员的超类继承而且如果子类和超类都在同一个包中那么静态可以从基类访问成员,甚至不使用超类的类名。请仔细阅读 示例:

package myProg; 
class A 
{ 
static int i = 10; 
A() 
{ 
System.out.println("Inside A()"); 
} 
} 

class B extends A 
{ 
public static void main(String[] args) 
{ 
System.out.println("i = " + i); //accessing 'i' form superclass without specifying class name 
System.out.println("A.i = " + A.i); //again accessing 'i' with the class name .(dot) static member 'i' 

/* 
we can also use the super class' object in order to access the static member compiler 
will not show any error but it is not the exact way of using static members. static members are created 
so that it could be used without creating the class object. see below the usage of object to use the 
static member i. 
*/ 
A obj = new A(); //creating class A object and A() also gets called 
obj.i = 20; 
System.out.println("obj.i = " + obj.i); 
} 
} 

/* 
This program was to show the usage of static member. Now, lets discuss on the topic of static member inheritance. 
SO GUYS I WOULD LIKE TO TELL YOU THAT STATIC MEMBERS ARE NOT INHERITED. This undermentioned program is 
to show the inheritance of static members. 
*/ 
class A 
{ 
static int i = 10; //initially the value of i is 10 
static int j = 20; //lets use one more static member int j, just to see the value of it through class A, and B 
static 
{ 
/* 
This is static initialization block(SIB) of class A, 
SIB gets executed first in the order of top to bottom only one time 
when the class is loaded. 
*/ 

System.out.println("A-SIB"); 
} 
} 
class B extends A 
{ 
static 
{ 
i = 12;//trying to modify the i's value to 12 
System.out.println("B-SIB"); 
} 
} 
class D extends A 
{ 
static int k = 15; 
static 
{ 
System.out.println("D-SIB"); 
} 
} 
class C 
{ 
public static void main(String [] arhs) 
{ 
System.out.println("D.k: " + D.k); 
/*here we are trying to access the static member k from class D, 
it will try to search this class and then that class 
will be loaded first i.e. SIB of class D will be loaded and SOP 
statement of class D will be printed first. When the class loading 
is done then the compiler will search for the static int k in class 
D and if found SOP statement will be executed with the value of k. 
*/ 
/* 
ONE GROUND RULE: as soon as the compiler see this statement the compiler will load 
class D into the memory, loading of class into memory is nothing but 
storing all the static members (i.e. static constant & SIBs) into the 
memory. 
*/ 


System.out.println("B.i: " + B.i); 
/*Now, this is what we are talking about... we think that static int i's 
value is there in class B and when we write B.i it compiles and executes 
successfully BUT... there compiler is playing a major role at this statement... 
Try to understand now... we know that class B is the subclass of class A 
BUT when the compiler sees this statement it will first try to search 
the static int i inside class B and it is not found there, then since it is 
the subclass of A, the compiler will search in class A and it is found 
there. NOW, WHEN STATIC INT I IS FOUND IN CLASS A THE COMPILER WILL CHANGE 
THIS STATEMENT B.i TO A.i and the class B WILL NOT AT ALL BE LOADED INTO 
THE MEMORY BECAUSE STATIC I IS ONLY PRESENT IN CLASS A. But in the previous 
statement static int k is present inside class D so when we try to access k's value 
the class D will be loaded into memory i.e. SIB will be executed and then 
the SOP statement of the value of k. USING B.i IS NOT WRONG BUT COMPILER 
ASSUMES THAT THE PROGRAMMER HAS MADE A MISTAKE AND IT REPLACES THE CLASS NAME 
B.i TO A.i. Thus this show that static members are not inherited to the subclass.And 
therefore the vaue of i will NOT BE CHANGE TO 12 AS YOU CAN SEE IN THE SIB OF 
CLASS B, it will be 10 only.. 
*/ 



System.out.println("A.j: " + A.j);//this statement will be executed as it is, compiler will not make 
System.out.println("A.i: " + A.i);//any modifications to these statements.  


System.out.println("B.j: " + B.j);//again compiler will modify this statement from B.j to A.j 

} 
} 

如果您仍有任何疑惑,请通过此电子邮件地址向我发送电子邮件: pradeep_y2k@yahoo.co.in

此致 Pradeep Kumar Tiwari

答案 3 :(得分:0)

Ok静态方法不能被覆盖,但可以重新定义,换句话说就是它的隐藏方法 检查这个http://www.coderanch.com/how-to/java/OverridingVsHiding他们解释得很好