一、什么是 Static?
Static 关键字:表明一个成员变量或者是成员方法可以在没有所属的类的实例的情况下直接被访问
当成员被静态修饰后,就多了一个调用方式,除了可被对象调用外还可以直接被类名调用 --- 类名.静态成员。
声明为 static 的方法有以下几条限制:
- 仅能调用其他的 static 方法
- 只能访问 static 变量.
- 不能以任何方式引用 this 或 super(因为静态优先于对象存在)
- 不能被覆盖(因为方法覆盖是基于运行时动态绑定的, 而 static 方法是编译时静态绑定的.)
特点(利:可以节省内存空间 弊:有局限性):
- 随着类的加载而加载
- 优先于对象存在
- 可以被类直接调用
- 被所有对象所共享
- 随着类的加载而加载
声明为 static 的变量:实质上就是全局变量. (+ final 就是全局常量).
当声明一个对象时, 并不产生 static 变量的拷贝, 而是该类所有的实例变量共用同一个 static 变量.
对于静态类,只能用于嵌套类内部类中。
二、什么是静态变量、静态方法、静态块和静态类?
静态变量:我们可以将类级别的变量声明为static。静态变量是属于类的,而不是属于类创建的对象或实例。因为静态变量被类的所有实例共用,所以非线程安全的。通常静态变量还和关键字final一起用,作为所有对象共用的资源或常量。如果静态变量不是私有的,那么可以通过ClassName.variableName来访问它。
静态方法:类似于静态变量,静态方法也属于类,不属于实例的。静态类只能访问类的静态变量,或调用类的静态方法。通常静态方法作为工具方法,被其它类使用,而不需要创建类的实例。譬如集合类、Wrapper类(String, Integer等)和工具类(java.util中的类)都有很多静态方法。
静态块:静态块就是类加载器加载对象时,要执行的一组语句。它用于初始化静态变量。通常用于类加载的时候创建静态资源。我们在静态块中不能访问非静态变量。我们可以在一个类中有多个静态块,尽管这么做没什么意义。静态块只会在类加载到内存中的时候执行一次。
静态类:我们对嵌套类使用static关键字。static不能用于最外层的类。静态的嵌套类和其它外层的类别无二致,嵌套只是为了方便打包。
三、Static 相关问题?
1.是否可以 override 一个 static 的方法?
答:不能被覆盖. 因为方法覆盖是基于运行时动态绑定的, 而 static 方法是编译时静态绑定的.
2.是否可以 一个 static 方法内部调用非 static 方法?
答:不可以. 因为非 static 方法是要与对象关联在一起的, 须创建一个对象的实例后, 才可以在该对象上进行方法调用, 而static方法调用时不需要创建对象, 可以直接调用. 也就是说, 当一个 static 方法被调用时, 可能还没有创建任何实例对象, 如果从一个 static 方法中发出对非 static 方法的调用, 那个非 static 方法是关联到哪个对象上的呢? 这个逻辑无法成立, 所以, 一个 static 方法内部发出对非 static 方法的调用.
3.静态变量和实例变量的区别?
答:在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加;
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象(比如 new 一个),才会被分配空间,即才可以使用. 而静态变量是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,,静态变量就会被分配空间,就可以使用了.
总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用.
/** * 测试代码 */ public class StaticTest{ public static int staticVar = 0; public int instanceVar = 0; public StaticTest(){ staticVar++; instanceVar++; System.out.println(“staticVar=” + staticVar + ”,instanceVar=”+ instanceVar); } }