因为概述较为抽象,这里建议大家先看使用和总结,再看概述
概述
static又叫静态修饰符,大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在。这样做有什么意义呢?在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是用static修饰的成员可以通过类名加“.”进行直接访问。
static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。
被static修饰的成员变量和成员方法独立于该类的任何对象,它们将与类一起加载到内存中。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象市,不生成static变量的副本,而是类的所有实例共享同一个static变量。
static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用--废话),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,static表示不要实例化就可以使用,这样就容易理解多了。static前面加上其它访问权限关键字的效果也以此类推。
static使用
static的定义和访问
定义
只需要在访问修饰符后添加static即可,如我们的mian方法为例
public static void main(String[] args) {}
public就是我们的服务修饰符后面添加static即可
访问
static修饰的成员变量和成员方法习惯上称为静态变量和静态方法,可以直接通过类名来访问,访问语法为:
类名.静态方法名(参数列表...)
类名.静态变量名
static变量
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
static方法
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。
static代码块
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。例如:
public class Test5 {
private static int a;
private int b;
static {
Test5.a = 3;
System.out.println(a);
Test5 t = new Test5();
t.f();
t.b = 1000;
System.out.println(t.b);
}
static {
Test5.a = 4;
System.out.println(a);
}
public static void main(String[] args) {
// TODO 自动生成方法存根
}
static {
Test5.a = 5;
System.out.println(a);
}
public void f() {
System.out.println("hhahhahah");
}
}
运行结果:
3
hhahhahah
1000
4
5
静态代码块使用场景
当一个类需要在被载入时就执行一段程序,这样可以使用静态程序块,利用静态代码块可以对一些static变量进行赋值,最后再看一眼这些例子,都一个static的main方法,这样JVM在运行main方法的时候可以直接调用而不用创建实例。
总结
有时你希望定义一个类成员,使它的使用完全独立于该类的任何对象。通常情况下,类成员必须通过它的类的对象访问,但是可以创建这样一个成员,它能够被它自己使用,而不必引用特定的实例。在成员的声明前面加上关键字static(静态的)就能创建这样的成员。如果一个成员被声明为static,它就能够在它的类的任何对象创建之前被访问,而不必引用任何对象。你可以将方法和变量都声明为static。static 成员的最常见的例子是main( ) 。因为在程序开始执行时必须调用main() ,所以它被声明为static。
static的特点:
1.随着类的加载而被加载;
2.优先于对象存在;
3.被所有对象共享;
5.被static修饰的变量成为静态变量(类变量)或者实例变量;
存放位置
1.静态变量随着类的加载而存在于date内存区;
2.实例变量随着对象的建立而存在于堆内存;
生命周期:
1.类变量周期生命最长,随着类的消失而消失;
2.实例变量生命周期比类变量短,它是随着对象的消失而消失;
访问特点
非静态成员方法内部
1.能够访问静态的成员变量;
2.能够访问非静态的成员变量;
3.能够访问静态的成员方法;
4.能够访问非静态的成员方法;
静态的成员方法内部
1.能够访问静态成员变量,但是不能够直接访问成员变量
2.能够访问静态的成员方法,但是不能够直接访问成员方法
static访问总结
声明为static的变量实质上就是全局变量。当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例变量共用同一个static变量。声明为static的方法有以下几条限制:
• 它们仅能调用其他的static方法。
• 它们只能访问static数据。
• 它们不能以任何方式引用this或super(关键字“this”用作对实例的引用。由于静态方法没有(属于)任何实例,因此不能在静态方法中使用“this”引用。如果还是这样,请尝试这样做,这样会生成编译时错误。而且main方法是静态的,因此,您不能在main方法中使用“this”引用)。
static使用场景
static和final(最终态)一块用表示:
static final用来修饰成员变量和成员方法,可简单理解为“全局常量”!(一般用于需要全局范围切不允许修改的地方 如:状态码,错误提示等等)
对于常量,表示一旦给值就不可修改(如果是引用类型则内存地址不可以改变,但是引用内存中的值是可以改变的),并且通过类名可以访问。
对于方法,表示不可覆盖,并且可以通过类名直接访问。
什么时候使用static修饰成员:
当属于同一个类的所有对象出现共享数据时,就需要将存储这个共享数据的成员用static修饰;
什么时候使用static修饰方法:
当功能内部没有访问到非静态的成员时(对象特有的数据)那么该功能可以定义成静态的;