首页 文章

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

提问于
浏览
117

我正在阅读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();
    }
}

我怎么能在课程 B 中直接使用 display() ?更重要的是, B.display() 也有效 .

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

14 回答

  • 0

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

    来自Sun Java Tutorials

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

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

    page上覆盖和隐藏的区别 .

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

  • 0

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

    Java Language Specification #8.4.8州:

    8.4.8继承,覆盖和隐藏类C从其直接超类继承超类的所有具体方法m(静态和实例),以下所有条件都为真:m是C的直接超类的成员.m在与C相同的包中是公共的,受保护的或声明的包访问 . 在C中声明的方法具有签名,该签名是m的签名的子签名(第8.4.2节) .

    [1]它并没有在我的副本中,第1版,2000年 .

  • 11

    您可以体验以下代码中的差异,这稍微修改了您的代码 .

    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();
            b.display();
    
            A a = new B();
            a.display();
        }
    }
    

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

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

  • 0

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

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

  • -2

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

  • -1

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

  • 8

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

  • 0

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

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

  • -1

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

    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”#成功覆盖在第二种情况下,o / p是“静态方法A”#静态方法 - 不会考虑多态性

  • -2

    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
    
  • 0

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

  • 2

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

    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
    

    因此,这是结论:

    • 当我们通过 . 以静态方式调用静态时,它将查找该类中定义的静态,或者最接近继承链中的类 . 这证明了静态方法是继承的 .

    • 从实例调用静态方法时,它调用编译时类型中定义的静态方法 .

    • 可以从 null 实例调用静态方法 . 我的猜测是编译器将使用变量类型在编译期间查找类,并将其转换为适当的静态方法调用 .

  • 152

    静态成员是普遍成员 . 他们可以从任何地方访问 .

  • 5

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

相关问题