Java中关于static关键字解析

Java中的static关键字,初学者使用感受方便的同时相信也犯过各种的错误。下面将从以下几个方面对static关键字进行一个解析。


一:静态属性

二:静态方法

三:静态代码块

四:关于static的一个经典例子。


静态属性

首先应该记住:

静态属性归类所有,而不是归单个对象所有,而一般的属性归单个对象所有。

即静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当类初次被加载的时候初始化。而非静态变量是单个对象所拥有的的,在创建对象的时候被初始化,在内存中存在多个副本。

public class TestStatic {
	private static int x;
	private static int y;
	private int z;
	public TestStatic(int x,int y,int z){
		this.x=x;
		this.y=y;
		this.z=z;
	}
	public static void main(String[]args){
	    TestStatic t1=new TestStatic(1,1,1);
	    TestStatic t2=new TestStatic(2,2,2);
	    TestStatic t3=new TestStatic(3,3,3);
	    TestStatic t4=new TestStatic(4,4,4);
	    System.out.println(t1.x+"--"+t1.y+"--"+t1.z);
	    System.out.println(t2.x+"--"+t2.y+"--"+t2.z);
	    System.out.println(t3.x+"--"+t3.y+"--"+t3.z);
	    System.out.println(t4.x+"--"+t4.y+"--"+t4.z);
	 }
}

x,y为静态的,z为一般的属性。

在创建对象t1的时候,x为1,y为1,z为1

在创建对象t2的时候,因为x,y为静态的,所以即使是一个新的对象,这时候操作的x,y还是以前的那个x,y,此时x,y分别为2,2,而此时z是归t2对象所有,此时t2.z==2;

同理在以下创建对象的时候,则x,y在不停的覆盖,最后

x为4,y为4.

t1.z为1

t2.z为2

t3.z为3

t4.z为4


静态方法

这里应该先指明的是:静态方法中只能调用静态的方法以及属性,而非静态的方法既可以调用普通属性和方法,又可以调用静态的属性和方法。

看下面这段代码:



public class TestStatic02 {
	 public static int Id;
	 public static String Name;
	 public int ClassNumber;
	 
	 public void print01(){
		 System.out.println(TestStatic02.Id);
		 System.out.println(TestStatic02.Name); 
		 System.out.println(this.ClassNumber);
		 print03();
	 }
	 
	 public static void print02(){
		 System.out.println(TestStatic02.Id);
		 System.out.println(TestStatic02.Name); 
                //下面两行代码编译器会报错,而报错的提示是将属性ClassNumber,以及方法print01改为静态static
                //这即使上面所说的静态方法中只能调用静态的方法以及属性
                System.out.println(TestStatic02.ClassNumber);
		print01(); 
                print03();
          } 
         public static void print03(){ 
         }
         public static void main(String[]args){}}

 

静态代码块

使用静态的代码块减少程序的开销以及运行的速度

某一个属性只需要创建依次而被重用多次可以使用静态代码块

看下面代码,观察代码执行的顺序

public class TestStatic03 {
   static{
       System.out.println("TestStatic03_static_01");
    }

  public static void main(String[]args){
        System.out.println("main");
   }
    static{
       System.out.println("TestStatic03_static_02");
    }
   static{
       System.out.println("TestStatic03_static_03");
   }
 }
执行的结果为:
TestStatic03_static_01
TestStatic03_static_02
TestStatic03_static_03
main

关于中间是怎么执行的,在最后一个经典例子中会说到。


经典例子

先看一下代码,分析代码执行后的结果:

public class TestStatic06 extends A{

       public TestStatic06(){
		System.out.println("TestStatic06_constructor");
	}
	
	static {
		System.out.println("TestStatic06_static01");
	}
	
	public static void main(String[] args){
		new TestStatic06();
	}
	
	static {
		System.out.println("TestStatic06_static02");
	}

}
 class A{
	 
	 public A(){
		 System.out.println("A_constructor");
	 }
	 
	 static {
		  System.out.println("A_static");
	 }
	 
}
一眼看出似乎有点混乱,又是代码块,又是构造函数,还有继承关系。

关于执行的顺序,自己也稍微总结了一下:

1:加载static代码块-(父类static代码块-->子类static代码块)
           |
2: 加载主函数(main方法)
           |
3: 按顺序执行相应的代码顺序

即程序会找到有主函数的那个类,如果主函数有static代码块,则会先加载静态代码块,在加载静态代码块的时候,如果有继承关系,在应该加载父类中的静态代码块(当然这里父类中静态代码块,如果没有当然就不加载),然后在加载自身的静态代码块,加载完之后程序会找到main方法执行相应的操作。

这里应该注意的就是关于构造函数的执行,简单的说来就是在哪里创建新的对象时候,构造函数调用的时候,先执行父类的,然后在执行子类的。关于这里,之前的一篇有关super的关键字的博客中说到过。

而对于这题,可以看到,在有main方法中的TestStatic06的类中,因为其继承类A,则先加载类A中的静态代码块,打印

A_static
然后加载自身的静态代码块,打印

TestStatic06_static01
TestStatic06_static02
然后加载main方法,创建对象,调用父类构造函数以及自身的构造函数打印

A_constructor
TestStatic06_constructor




































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值