java类锁和对象锁(1)—先搞清楚静态的含义

首先我们来搞清楚java中的静态属性和静态方法。

有关静态常见的问题

这里我问几个问题,供大家思考一下,看看自己是否可以秒答。

  • 1.静态属性可以被继承吗?
  • 2.静态方法可以访问非静态属性吗?
  • 3.非静态方法可以访问静态属性吗?
  • 4.静态方法中可以使用this/super关键字吗?
  • 5.为什么静态方法不能调用非静态方法或者变量呢?
  • 6.静态属性、非静态属性、静态代码块、非静态代码块、构造函数在初始化时的执行顺序是怎样的?

先说答案:

  • 1.可以,继承跟是否静态无关,只跟作用域有关(private public protected)
  • 2.不可以,同4
  • 3.可以,因为静态变量是存储在静态内存单元内,可以直接用类进行调用,也可以用实例化的对象对其引用。所以非静态方法是可以引用静态变量的
  • 4.不可以,this指代当前对象的引用,super指代父类对象的引用,静态方法属于类,不属于某一个对象,当静态方法加载的时候,对象还不一定存在。如果静态方法中有this和super那么当静态方法被加载到内存中,其中的this和super也被加载到内存中,但是对象还没创建this和super还没被初始化,所以加载时会报错。
  • 5.静态方法是属于类的,不需要实例化,不是属于对象的,而非静态变量是属于对象的,需要先实例化。在一个类的静态方法中访问非静态成员,之所以出错是因为,在类的非静态成员不存在的时候,类的静态属性已经存在了,访问一个内存中不存在的东西当然会报错。
  • 6.不考虑继承关系的话,静态属性和代码块(按照代码出现的顺序)>非静态属性和非静态代码块>构造函数

马上来验证一下

public class StaticDemo {

    public String b = "非静态属性";
    public static String a = "静态属性";
	
    static {
    	 System.out.println(a);  
         System.out.println("静态代码块"); 
	}

    {
    	 System.out.println(b);  
         System.out.println("非静态代码块"); 
    }
    
    public StaticDemo() {
    	System.out.println("构造函数");
    }
    
    public static void main(String[] args) {
	StaticDemo demo = new StaticDemo();
    }
}

复制代码

打印结果:

静态属性
静态代码块
非静态属性
非静态代码块
构造函数
复制代码

在有继承关系的情况下

父类的静态属性和静态代码块>子类的静态属性和静态代码块>父类的非静态属性>父类的构造函数>子类的非静态函数>子类的构造函数

再来验证一下

class ParentClass{
	public static String pA = "父类-静态属性";
	public String pB = "父类-非静态属性";

    static {
    	 System.out.println(pA);  
         System.out.println("父类-静态代码块"); 
    }
    {
   	System.out.println(pB);  
        System.out.println("父类-非静态代码块"); 
    }
    
    public ParentClass() {
    	System.out.println("父类-构造函数");
    }
}

public class StaticDemo extends ParentClass{

	public String b = "非静态属性";
	public static String a = "静态属性";
	
    static {
    	 System.out.println(a);  
         System.out.println("静态代码块"); 
    }

    {
    	 System.out.println(b);  
         System.out.println("非静态代码块"); 
    }
    
    public StaticDemo() {
    	System.out.println("构造函数");
    }
    
    public static void main(String[] args) {
        StaticDemo demo = new StaticDemo();
    }
}
复制代码

执行结果:

父类-静态属性
父类-静态代码块
静态属性
静态代码块
父类-非静态属性
父类-非静态代码块
父类-构造函数
非静态属性
非静态代码块
构造函数
复制代码

这几个问题我们知道答案了,但是为什么会产生这样的结果呢?

类是如何加载的

我们看一下类的加载过程:

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享