本文主要介绍关于static关键字在java语言中的应用,从三个角度什么是static关键字、为什么设置static关键字和怎样用static关键字进行了说明,并补充了一些关于static关键字的练习。
一、static关键字是什么
①static修饰符修饰的代码属于类代码,没有static修饰的属于对象。
②static修饰符修饰的代码存储在方法区的静态常量池中,且属于类的东西是被对象所共享的(变量相当于共享的是内存空间,方法则是被调用(入栈与出栈))
二、Java为什么设置static关键字
1、目的:因为要方便类去使用自己的方法和变量
2、假设我们的方法和变量上面没有static关键字。
如果方法和变量属于非静态,他们只有在对象当中才会被分配内存空间,那么也就是只能有对象才能调用。
3、假设我们的方法和变量上有static关键字
如果方法和变量属于静态,同时方法和变量会被存储在方法区的静态常量池中,并且能够直接被类调用(也能如上图被对象调用,因为对象来源于类,那么对象可以使用类的信息,但是不推荐)。
从上一张图可以看出如果没有static关键字,那么类是不可以调用自己的属性和方法的,只能用对象去调用。
三、static怎样用?
1、static修饰变量
static修饰的变量属于类变量,存储在方法区的静态常量池当中,被所有对象共享。
例1:
代码
运行该代码输出:
分析:
①遇到代码问题首先画出堆栈内存图。
②name是被static修饰的,存储在方法区的静态常量池中,a1与a2存储在栈内存中,此时他们的address都为保定,name为admin。
③通过a1.name和a1.address对值进行修改,此时a1所指向的地址中address的值变为北京,静态常量池中的name值改为张三,然后通过a2.name和a2.address对值进行修改,此时a2所指向的地址中address的值变为上海,静态常量池中的name值改为石家庄。
2、static修饰方法
(1)在static修饰的静态方法中无法调用非静态方法
如何解决以main方法为例:如果一个方法想要被main方法调用,如何做?
①、给非静态方法添加static关键字
②、在main方法中创建对象,通过对象调用该非静态方法
(2)在非静态方法中可以调用静态方法
为什么在非静态方法中可以调用静态方法?
因为hhh被static修饰属于类变量,存储在方法区的静态常量池当中,被所有对象共享。从形成角度来说, fff()方法想要表达的时候就已经创建好了对象,那么静态方法一定是存在的,因为有对象一定是有类的。
3、static修饰代码块
在main方法执行之前运行目的是优化程序。
例1:
代码:
输出:
解释:
首先寻找含有main()函数的类启动程序 然后进行扫描检查该类有没有父类,如果有则继续扫描父类(对父类重复上述操作),本代码发现父类Base没有父类。 接着先通过javac指令将Base.class文件加载到方法区,同时Base当中的static代码块执行。 再将ceshi.class文件加载到方法区,同时ceshi当中的static代码块执行。 最后main()入栈执行new ceshi()创建对象(在创建子类对象之前,应该先创建父类对象),先执行Base()构造器 在执行ceshi()构造器。
四、static关键字练习
例1:
代码:
public class A {
private static int a;
public static void main(String[] args) {
modify(a);
System.out.println(a);
}
public static int modify(int a){
return a++;
}
}
结果:0
解释:
画堆栈运行图,首先在静态常量池中放一个变量a,a的默认值为0,main执行,调用modify(a)方法入栈,注意该方法上的变量是局部变量,只在该方法中起作用。java只进行值传递,此时执行a++,然后出栈,最后输出a的值,注意此时的a是静态常量池中的变量a,值为0。
例2:
代码:
public class Demo {
public Demo(String aa){
System.out.println("===="+aa);
}
static{
System.out.println("11");
}
public static Demo demo=new Demo("+++");
static{
System.out.println("22");
}
}
class Test{
public static void main(String[] args) {
Demo demo=new Demo("----");
}
}
结果:
解释:
① main方法在哪就先扫描哪个类,扫描Test类发现没有父类,也没有static修饰的代码,那么编译Test类,并且将main方法入栈。
②执行new Demo("----"),在执行之前扫描Demo类,发现没有父类,所以编译Demo类
在编译过程中satick代码块按顺序优先执行
③首先输出11
④执行 public static ceshi ce=new ceshi("+++") ,此时会涉及到Demo构造方法,所以输出====+++
⑤输出22
⑥编译完毕 回到main方法中继续执行new Demo("----"),现在可以创建对象了,也就是到了运行阶段
⑦此时通过调用构造器构造对象====----