本文最后更新于:1 年前

static 关键字

static类型,又叫类类型。

修饰目标 (成员数据/方法/成员内部类/代码块)属于类的

静态类 静态块 静态方法 静态变量
static 成员内部类 static 代码块 static 成员方法 static 成员变量
直接通过类就可以访问。所有对象共享该类 只能出现在类中不能出现方法体中,类加载后初始化时被执行一次注意:区分构造代码块,每次构造都被执行 直接通过就可以调用。不用等创建了实例后 类加载时在Java方法区分配空间,所有对象共享

区别:无static关键字成员属于具体的对象实例: 实例变量、实例方法(只能通过对象调用)、实例成员内部类(只能通过对象引用)

静态的特点

  1. 随着类的加载而加载
    也就是,说静态会随着类的消失而消失,说明静态的生命周期最长。
  2. 优先于对象的存在
    明确一点:静态是先存在的,对象是后存在的。
  3. 被所有对象共享。
  4. 可以直接被类名多调用。

static 成员的访问格式

一般要通过 *“ 类名. ” * 的形式来访问

静态变量 静态方法 静态成员内部类
类名.静态变量 类名.静态方法 类名.静态成员内部类

注意事项

🔺 static成员方法/代码块:静态方法 只能 使用静态成员变量(或内部类)或调用静态方法。(任课老师称: 静者恒静

🔺非静态方法可以访问静态、也可以访问非静态。

🔺 static成员方法/代码块:方法体中不能出现this(当前对象)或super(基类对象)。因为静态优先于对象存在,所以静态方法中不可以出现this、super关键字。

实例变量和类变量的区别

  1. 存放位置
    类变量随着类的加载存在于方法区中,实例变量随着对象的对象的建立存在于堆内存里
  2. 生命周期
    类变量生命周期最长,随着“类”的加载而加载,随着类的消失而消失
    实例变量随着“对象”的消失而消失

静态的利弊

  • 利: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:“对象.”形式调用

综上

  1. 什么时候使用静态?
    因为静态修饰的内容有成员变量和方法。
  2. 什么时候定义静态变量(类变量)呢?
    当对象中出现共享数据时,该数据被静态所修饰,对象中的特有数据要定义成非静态存在于堆内存中。
  3. 什么时候定义静态函数?
    当功能内部没有访问到非静态数据(或者称为对象的特有数据)
    那么该功能可以定义成静态的。

注:前面的几篇Java笔记中也有提到static,后来上课老师再小结static关键词,结合前面的笔记食用效果更佳。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

Java用最有效率的方法计算2乘以8 上一篇
Java笔记—this关键字 下一篇

 目录