本文最后更新于:1 年前
static 关键字
static类型,又叫类类型。
修饰目标 (成员数据/方法/成员内部类/代码块)属于类的
静态类 | 静态块 | 静态方法 | 静态变量 |
---|---|---|---|
static 成员内部类 | static 代码块 | static 成员方法 | static 成员变量 |
直接通过类就可以访问。所有对象共享该类 | 只能出现在类中不能出现方法体中,类加载后初始化时被执行一次。注意:区分构造代码块,每次构造都被执行 | 直接通过类就可以调用。不用等创建了实例后 | 类加载时在Java方法区分配空间,所有对象共享 |
区别:无static关键字成员属于具体的对象实例: 实例变量、实例方法(只能通过对象调用)、实例成员内部类(只能通过对象引用)
静态的特点
- 随着类的加载而加载
也就是,说静态会随着类的消失而消失,说明静态的生命周期最长。 - 优先于对象的存在
明确一点:静态是先存在的,对象是后存在的。 - 被所有对象共享。
- 可以直接被类名多调用。
static 成员的访问格式
一般要通过 *“ 类名. ” * 的形式来访问
静态变量 | 静态方法 | 静态成员内部类 |
---|---|---|
类名.静态变量 | 类名.静态方法 | 类名.静态成员内部类 |
注意事项
🔺 static成员方法/代码块:静态方法 只能 使用静态成员变量(或内部类)或调用静态方法。(任课老师称: 静者恒静)
🔺非静态方法可以访问静态、也可以访问非静态。
🔺 static成员方法/代码块:方法体中不能出现this(当前对象)或super(基类对象)。因为静态优先于对象存在,所以静态方法中不可以出现this、super关键字。
实例变量和类变量的区别
- 存放位置
类变量随着类的加载存在于方法区中,实例变量随着对象的对象的建立存在于堆内存里 - 生命周期
类变量生命周期最长,随着“类”的加载而加载,随着类的消失而消失
实例变量随着“对象”的消失而消失
静态的利弊
- 利:1、对对象的共享数据进行单独空间的存储,节省空间,没有必要没一个对象中都存储一份。2、可以直接被类名所调用。
- 弊:生命周期过长,访问出现局限性(只能访问静态)
Demo:类内使用
import static java.lang.System.*; //静态导入静态方法或对象
public class StaticDemo1 {
static int a = 3, b, i = 0; // 静态变量
char ch = 'Y'; // 实例变量
static void meth(int x) { // 静态方法
out.println("x = " + x);
//out.println("ch = " + ch);//【1】Error!
}
static { // 静态代码块-类加载时只执行1次
out.println("静态块初始化:仅1次");
b = a * 4;
//out.println("ch = " + ch);//【1】Error!
}
public static void main(String[] args) {
meth(42); //静态方法调用静态方法
new StaticDemo1(); //创建匿名对象1
new StaticDemo1(); //创建匿名对象2 }
{
out.println("ch = " + ch);//【2】OK!
out.printf("构造代码块:第%d次构造第%1$d次执行\n", (++i));
}
}
}
注意:
🔺特别注意:类的静态代码块仅在类在加载后初始化时被执行1次
🔺第一次new一个类时才加载该类
🔺静态方法、静态块不能访问非静态的成员(即,静者恒静)。如上述代码中的注释【1】
🔺静态块初始化:仅1次
Demo:类外使用和静态块执行时机
import static java.lang.System.out;
class MyD{
private static int m;
public static int n;
static{ // 静态代码块【2】
m = n = 0;
out.println("仅1次");
}
public static void callMe(){
out.printf("m=%d,n=%d", m, n);
}
}
public class StaticDemo2 {
public static void main(String[] args) {
MyD d; //【0】MyD被加载,但未主动使用
d = new MyD(); //【1】这里才【主动使用】MyD,于是执行其静态代码块【2】
MyD.n++; //最佳:类名.静态变量
MyD.callMe(); //最佳:类名.静态方法
}
}
特别留意:
🔺用一个类声明一个类对象变量,至多会加载该类,但还未主动使用
🔺老师说:【主动使用】,是一个比较高级的专题,暂不深入
DEMO:静态方法的声明
class Person{
String name; //定义name属性
private static String nation = "中国"; //定义静态属性nation
int age; //定义age属性
public Person(String name, int age){//声明一个有参的构造方法
this.name = name;
this.age = age;
}
public String talk(){ //声明了一个talk()方法
return "我是:" + this.name + ",今年:" + this.age + "岁,来自:" + nation;
}
public static void setNation(String nat){//声明一个静态方法,给静态变量赋值
nation = nat;
}
}
public class StaticMethod{
public static void main(String[] args){
Person p1 = new Person("张三", 25);
Person p2 = new Person("李四", 30);
Person p3 = new Person("王五", 35);
System.out.println("修改之前信息:" + p1.talk());
System.out.println("修改之前信息:" + p2.talk());
System.out.println("修改之前信息:" + p3.talk());
System.out.println(" ***********修改之后信息***********");
// 修改后的信息
Person.setNation("美国");
System.out.println("修改之后信息:" + p1.talk());
System.out.println("修改之后信息:" + p2.talk());
System.out.println("修改之后信息:" + p3.talk());
}
}
DEMO:调用外部类定义的方法(有static+无static)
首先定义方法
public class Dy {
public int Add(int x,int y) { //定义Add(),该方法没有被static修饰
return x+y;
}
public static int Sub(int x,int y) {//定义Sub(),该方法被static修饰
return x-y;
}
}
调用方法
public class Test {
public static void main(String[] args){
int a=5;
int b=4;
int result=0;
//通过实例化调用外部类的Add方法
Dy dy=new Dy();
result=dy.Add(a, b);
System.out.println(result);
//直接调用外部类的Sub方法
result=Dy.Sub(a, b);
System.out.println(result);
}
}
🔺static main方法调用外部方法/成员变量:
- 有static:“类名.”形式调用
- 无static:“对象.”形式调用
综上
- 什么时候使用静态?
因为静态修饰的内容有成员变量和方法。 - 什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰,对象中的特有数据要定义成非静态存在于堆内存中。 - 什么时候定义静态函数?
当功能内部没有访问到非静态数据(或者称为对象的特有数据)
那么该功能可以定义成静态的。
注:前面的几篇Java笔记中也有提到static,后来上课老师再小结static关键词,结合前面的笔记食用效果更佳。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!