static关键词
static 静态的
static 可以修饰内部类(这里不讨论)
static 可以修饰属性 ====>> 静态变量
static 可以修饰方法 ====>> 静态方法
static 可以修饰代码块 ====>>静态代码块
-
static 修饰属性 ====>> 静态变量
static可以修饰成员变量,不能修饰局部变量
public class Student {
String stuID;
String name;
static String clsName; //static 修饰成员变量
}
public class TestStudent {
public static void main(String[] args) {
Student s1 = new Student();
s1.stuID="sg1524163";
s1.name="刘备";
s1.clsName="蜀国一班";//一处设置处处设置,一处修改处处修改!
Student s2 = new Student();
s2.stuID="sg16556163";
s2.name="关羽";
//s2.clsName="蜀国一班";
Student s3 = new Student();
s3.stuID="sg16657463";
s3.name="张飞";
//s3.clsName="蜀国一班";
//当遇到很多对象都有同一个属性的值时,可用static修饰这个属性来减少赋值
System.out.println(s1.name+"\t"+s1.clsName);
System.out.println(s2.name+"\t"+s2.clsName);
System.out.println(s3.name+"\t"+s3.clsName);
}
}
输出结果:
刘备 蜀国一班
关羽 蜀国一班
张飞 蜀国一班
需注意的问题
上面的例子中,是用对象(s1、s2、s3) 去调用静态属性(clsName) 的。--> clsName
但是,建议用类去调用。--> Student.clsName
当成员变量声明时使用了 static 关键字,那么这种变量称为静态变量,没有使用 static 关键字称为实例变量。
实例变量必须先创建对象,通过“引用”去访问,而静态变量访问时不需要创建对象,直接通过“类名”访问。
public class Phone {
int memory;
static String name;
}
//测试类
package test;
public class TestPhone {
public static void main(String[] args) {
Phone p1 = new Phone();
p1.memory = 128; //通过”引用“访问
//p1.name = "红米";
Phone.name = "红米"; //通过”类名“访问
System.out.println("内存:"+p1.memory);
System.out.println("品牌:"+Phone.name);
}
}
输出结果:
内存:128
品牌:红米
静态变量总结:
所有实例相关的,包括实例变量和实例方法,必须先创建对象,然后通过“引用”的方式去访问,如果空引用访问实例相关的成员,必然会出现空指针异常。所有静态相关的,包括静态变量和静态方法,直接使用“类名”去访问。虽然静态相关的成员也能使用“引用”去访问,但这种方式并不被主张。
-
static修饰方法 ====>> 静态方法
被static关键字所修饰的方法就是静态方法。
比如我们import的util包,全是工具类!工具类所有的方法都是静态方法!
使用方法:类名 . 静态方法
下面,我们自定义一个工具类(所有方法用 static 修饰)
package cn.bjpowernode.javase01.day11.static02;
public class PrintUtil {
//打印长方形
public static void rect(int a,int b){
for(int i=1;i<=a;i++){
for(int j=1;j<=b;j++){
System.out.print("* ");
}
System.out.println();
}
}
//打印等腰三角形
public static void triangle(int a){
for(int i=1;i<=a;i++){
for(int j=1;j<=(a-i);j++){
System.out.print(" ");
}
for(int z=1;z<=(2*i-1);z++){
System.out.print("*");
}
System.out.println();
}
}
}
创建测试类去调用上面的工具类(类名 . 静态方法)
package cn.bjpowernode.javase01.day11.static02; public class Test { public static void main(String[] args) { PrintUtil.rect(5,10); PrintUtil.triangle(5); } }
//结果如下:
-
static 可以修饰代码块 ====>>静态代码块
先看格式:
在 { } 内,除了明显的死循环,其他内容都可以写,跟方法体没什么区别
但是,静态代码块儿只能调用静态的成员,非静态代码块什么都能调用!
package test;
public class Student {
String name;
static String clsName; //静态变量
public static void fun1(){ //静态方法
System.out.println("fun1...");
}
public void fun2(){ System.out.println("fun2..."); }
public Student() { System.out.println("Student的构造函数..."); }
static{ System.out.println("Student的静态代码块。。。"); }
{ System.out.println("Student的非静态代码块..."); }
}
创建测试类
package test;
public class TestStudent {
public static void main(String[] args) {
System.out.println("main....");
Student s1 = new Student();
Student s2 = new Student();
System.out.println("姓名:"+s1.name);
System.out.println("班级:"+Student.clsName); //类.静态变量
Student.fun1(); //类.静态方法
s1.fun2();
}
static{ System.out.println("TestStudent的静态代码块。。。"); }
{ System.out.println("TestStudent的非静态代码块..."); }
}
1 执行结果: 2 TestStudent的静态代码块。。。 3 main.... 4 Student的静态代码块。。。 5 Student的非静态代码块... 6 Student的构造函数.... 7 Student的非静态代码块... 8 Student的构造函数.... 9 姓名:null 10 班级:null 11 fun1... 12 fun2...
输出结果的解释如下:
一个类中有静态代码块、非静态代码块、构造函数时,如果创建对象,执行顺序:静态代码块 ==> 非静态代码块 ==> 构造函数
如下图:方法区中有个静态区,用来存放静态代码块、静态的变量、方法;而堆区就存放非静态的。
当运行TestStudent 类时,
第一步:编译把 *.java 文件变成 *.class 文件
第二步:类加载( ClassLoader ),把代码片段加载到 jvm 虚拟机的方法区!
类加载如果遇到静态代码块,直接执行!所以输出行2(仅一次)
当创建了对象s1,就会加载Student类,在堆中开辟0x112位置,所以输出行4(仅一次)、5、6
当创建了对象s2,在堆中开辟0x234位置,所以输出行7(同5)、8(同6)
即,如果多次创建对象,非静态代码块和构造函数执行多次,静态代码块只执行一次!
静态代码块只在类加载时执行,而类加载只会加载一次!
第三步:执行程序
jvm打开,执行程序,jvm关闭!