是否在Java中继承了静态方法?

时间:2012-04-24 05:00:31

标签: java inheritance static

我正在阅读程序员指南 Khalid Mughal的Java™SCJP认证

在继承章节中,它解释了

  

成员的继承与其声明密切相关   可访问性。如果超类成员可通过其简单名称访问   在子类中(不使用任何额外的语法,如super),那   成员被认为是继承的

它还提到静态方法不会被继承。但是下面的代码非常好:

class A
{
    public static void display()
    {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A
{
    public void show()
    {
        // This works - accessing display() by its simple name -
        // meaning it is inherited according to the book.
        display();
    }
}

如何在课程display()中直接使用B?更重要的是,B.display()也有效。

本书的解释是否仅适用于实例方法?

14 个答案:

答案 0 :(得分:163)

所有可访问的方法都由子类继承。

来自Sun Java Tutorials

  

子类继承其父级的所有公共成员和受保护成员,无论子类在哪个包中。如果子类与其父类在同一个包中,它还继承父类的包私有成员。您可以按原样使用继承的成员,替换它们,隐藏它们,或用新成员补充它们

继承的静态(类)方法和继承的非静态(实例)方法的唯一区别在于,当您使用相同的签名编写新的静态方法时,旧的静态方法只是隐藏,而不是被覆盖。

page上覆盖和隐藏的区别。

  

隐藏和覆盖之间的区别具有重要意义。被调用的重写方法的版本是子类中的版本。被调用的隐藏方法的版本取决于它是从超类还是从子类调用

答案 1 :(得分:14)

如果这就是这本书的真实内容,那就错了。[1]

Java Language Specification #8.4.8州:

  

8.4.8继承,覆盖和隐藏

     

C类从其直接超类继承超类的所有具体方法m(静态和实例),其中所有以下都是真的:

     
      
  • m是C的直接超类的成员。

  •   
  • m在与C相同的包中公开,受保护或声明包访问。

  •   
  • 在C中声明的任何方法都没有签名,该签名是m签名的子签名(§8.4.2)。

  •   

[1]在我的副本中,2000年第1版没有说明。

答案 2 :(得分:8)

您可以体验以下代码的不同之处,这会略微修改代码。

class A {
    public static void display() {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A {
    public void show() {
        display();
    }

    public static void display() {
        System.out.println("Inside static method of this class");
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // prints: Inside static method of this class
        b.display();

        A a = new B();
        // prints: Inside static method of superclass
        a.display();
    }
}

这是由于静态方法是类方法。

A.display()和B.display()将调用各自类的方法。

答案 3 :(得分:5)

B.display()有效,因为静态声明使方法/成员属于类,而不是任何特定的类实例(又称Object)。您可以阅读更多相关信息here

另外需要注意的是,您不能覆盖静态方法,您可以让子类声明具有相同签名的静态方法,但其行为可能与您期望的不同。这可能是它不被认为是遗传的原因。您可以查看有问题的方案和解释here

答案 4 :(得分:2)

这个概念并不像看起来那么容易。我们可以访问没有继承的静态成员,即HasA-relation。我们也可以通过扩展父类来访问静态成员。这并不意味着它是一个ISA关系(继承)。实际上,静态成员属于该类,而static不是访问修饰符。只要访问修饰符允许访问静态成员,我们就可以在其他类中使用它们。就像它是公共的一样,它可以在同一个包中访问,也可以在包外。对于私人我们不能在任何地方使用它。默认情况下,我们只能在包中使用它。但是对于受保护,我们必须扩展超类。因此将静态方法引入其他类并不依赖于静态。它取决于Access修饰符。因此,在我看来,如果访问修饰符允许,静态成员可以访问。否则,我们可以像Hasa-relation一样使用它们。并且有一种关系不是继承。我们再次无法覆盖静态方法。如果我们可以使用其他方法但不能覆盖它,则它是HasA关系。如果我们不能覆盖它们就不会继承。所以作者是100%正确的。

答案 5 :(得分:0)

静态方法在Java中继承,但它们不参与多态。如果我们尝试覆盖静态方法,它们只会隐藏超类静态方法而不是覆盖它们。

答案 6 :(得分:0)

所有公共成员和受保护成员都可以从任何类继承,而默认或包成员也可以从与超类相同的包中的类继承。它不取决于它是静态成员还是非静态成员。

但静态成员函数也不参与动态绑定。如果父类和子类中的静态方法的签名相同,则应用Shadowing的概念,而不是多态。

答案 7 :(得分:0)

静态方法在子类中继承,但它不是多态。在编写静态方法的实现时,父类的方法被隐藏,而不是被覆盖。想想,如果没有继承,那么如何在没有classname.staticMethodname();的情况下访问?

答案 8 :(得分:0)

您可以覆盖静态方法,但如果您尝试使用多态,那么它们会根据类范围工作(与我们通常期望的相反)。

public class A {

    public static void display(){
        System.out.println("in static method of A");
    }
}

public class B extends A {

    void show(){
        display();
    }

     public static void display(){
        System.out.println("in static method of B");
    }

}
public class Test {

    public static void main(String[] args){
        B obj =new B();
        obj.show();

        A a_obj=new B();
        a_obj.display();


    }


}

在第一种情况下,o / p是“B的静态方法”#reccess override 在第二种情况下,o / p是“静态方法的A”#静态方法 - 不会考虑多态性

答案 9 :(得分:0)

Java中的静态方法是继承的,但不能被覆盖。如果在子类中声明相同的方法,则隐藏超类方法而不是覆盖它。静态方法不是多态的。在编译时,静态方法将被静态链接。

示例:

public class Writer {
    public static void write() {
        System.out.println("Writing");
    }
}

public class Author extends Writer {
    public static void write() {
        System.out.println("Writing book");
    }
}

public class Programmer extends Writer {

    public static void write() {
        System.out.println("Writing code");
    }

    public static void main(String[] args) {
        Writer w = new Programmer();
        w.write();

        Writer secondWriter = new Author();
        secondWriter.write();

        Writer thirdWriter = null;
        thirdWriter.write();

        Author firstAuthor = new Author();
        firstAuthor.write();
    }
}

您将获得以下信息:

Writing
Writing
Writing
Writing book

答案 10 :(得分:-1)

我们可以在子类中声明具有相同签名的静态方法,但是它不会被认为是覆盖,因为不存在任何运行时多态性。因为类的所有静态成员都是在类加载时加载的,所以它在编译时决定(在运行时覆盖)因此答案是'否'。

答案 11 :(得分:-1)

许多人用语言表达了他们的回答。这是代码中的扩展说明:

public class A {
    public static void test() {
        System.out.println("A");
    }
    public static void test2() {
        System.out.println("Test");
    }
}

public class B extends A {
    public static void test() {
        System.out.println("B");
    }
}

// Called statically
A.test();
B.test();
System.out.println();

// Called statically, testing static inheritance
A.test2();
B.test2();
System.out.println();

// Called via instance object
A a = new A();
B b = new B();
a.test();
b.test();
System.out.println();

// Testing inheritance via instance call
a.test2();
b.test2();
System.out.println();

// Testing whether calling static method via instance object is dependent on compile or runtime type
((A) b).hi();
System.out.println();

// Testing whether null instance works
A nullObj = null;
nullObj.hi();

结果:

A
B

Test
Test

A
B

Test
Test

A

A

因此,这是结论:

  1. 当我们通过。以静态方式调用static时,它将查找该类中定义的静态,或者最接近继承链中的类。这证明了静态方法是继承的。
  2. 从实例调用静态方法时,它调用编译时类型中定义的静态方法。
  3. 可以从null实例调用静态方法。我的猜测是编译器将使用变量类型在编译期间查找类,并将其转换为适当的静态方法调用。

答案 12 :(得分:-2)

静态成员是通用成员。它们可以从任何地方访问。

答案 13 :(得分:-2)

静态成员不会继承到子类,因为继承仅适用于非静态成员。 静态成员将通过类加载器加载到静态池中。继承仅适用于在对象

中加载的成员