目录
一、思考
- 子类为什么不能继承父类static方法?
- ClassPathXmlApplicationContext.java / AbstractXmlApplicationContext.java / AbstractRefreshableConfigApplicationContext.java 三者之间的关系
- 什么叫做静态引用、动态引用?
二、前言
我们用 A.java 和 AB.java 和 C.java 来描述 ClassPathXmlApplicationContext.java / AbstractXmlApplicationContext.java / AbstractRefreshableConfigApplicationContext 三者之间的关系。
三、Demo
1)A.java
import lombok.extern.slf4j.Slf4j;
// public abstract A { // error
@Slf4j
public abstract class A { // error
String sayHello() {
return "hello world";
}
public void a() {
System.out.println("a....");
}
public static void astaic(){
System.out.println("我是 a 的 static 方法");
}
}
2)B.java
public abstract class AB extends A{
@Override
String sayHello() {
return "AB hello world";
}
public void b(){
System.out.println("b.....");
}
}
3)C.java
public class C extends AB {
/**
* 错误报错:com.enjoy.jack.abstracts.C.super' cannot be referenced from a static context
* public static void test() {
* super.a();
* super.b();
* }
**/
void c() {
System.out.println("c...");
}
}
4)测试
package com.enjoy.jack.abstracts;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
/**
* ClassPathXmlApplicationContext ->继承了-> AbstractXmlApplicationContext -> 继承了 -> AbstractRefreshableConfigApplicationContext
* <p>
* 我们用下面最简单的例子来表述之间的关系,表示C.java可以调用A.java和B.java的方法,但是不可以调用其static方法(原则:java 子类不能继承父类的static方法)
* 静态引用、动态引用的区别,反推过来我们自己在写代码的时候可以考虑这种继承关系
* <p>
* AbstractXmlApplicationContext.java 和 AbstractRefreshableConfigApplicationContext.java 类中确实也没有static方法
*/
@Slf4j
public class Demo1 {
@Test
// void test() { // Method test() should be public
public void test() { // Method test() should be public
// -------------------------1.三者之间的关系-------------------------
C c = new C();
c.c();// 本身的方法
c.a();// 最顶层父类-a
c.b();// 中间层父类-b
// c.astaic(); a类的static方法是调用不到的
// -------------------------2.子类不能继承父类的static方法--------------
A child = new C();
child.astaic();// . 是点不出来的,但是可以访问
// -------------------------3.静态引用和动态引用的区别-------------------
// ============= 把AB.java的abstract去掉==============
A ab = new AB();
ab.sayHello1();
// ab.sayHello3(); 飘红 编译期间不通过,静态编译 (A并没有sayHello3()方法,所以他没有通过编译。这个过程我们称为静态绑定,编译阶段绑定)
AB ab1 = (AB)ab;
ab1.sayHello3();// run 运行起来指向具体类型,动态编译
/**
* 输出结果
* c...
* a....
* b.....
*/
}
}
四、问题
这里我们就遇到了一个问题“为什么子类不能继承父类的static方法和static变量?”
对于static修饰的变量,当子类与父类中存在相同的static变量时,也是根据“静态引用”而不是根据“动态引用”来调用相应的变量的。
而在父类和子类中对于非static变量和方法,是根据“动态引用”来调用相应的变量和方法。
然而,接着会有这样的问题存在:java中子类会不会继承父类的static变量和static方法
1)先说static方法:子类会不会继承父类的static方法呢?答案是:不会的,但是是可以访问的(点IDEA是没有提示的),也就是说父类static方法是可以被子类访问的。
2)接着来看父类的static修饰的变量,是否能够被子类继承呢?
答案:也是不可以的。但是也是可以被子类访问的
小结
1)子类是不继承父类的static变量和方法的。因为这是属于类本身的。但是子类是可以访问的。
2)子类和父类中同名的static变量和方法都是相互独立的,并不存在任何的重写的关系。
五、静态引用和动态引用的区别