一、前言引入
static关键字主要有两种作用:第一,为特定数据类型或对象分配单一的存储空间,而与创建对象个数无关。第二,实现某个方法或属性与类而不是对象关联在一起,也就是,在不创建对象的情况下就可以通过类来直接调用方法或使用类的属性。具体而言,static主要有四种使用情况:成员变量、成员方法、代码块和内部类。
- static成员变量
- static成员方法
- static代码块
- static内部类
二、具体内容
在《Java编程思想》有这样一段话:
- “static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”
这段话虽然只是说明了static方法的特殊之处,但是可以看出static关键字的基本作用,简而言之,一句话来描述就是:
方便在没有创建对象的情况下来进行调用(方法/变量)。
2.1 static成员变量
Java语言中没有全局的概念,但可以通过static关键字来达到全局的效果。Java类提供了两种类型的变量:用static关键字修饰的静态变量和不用static关键字修饰的实例变量。静态变量属于类,在内存中只有一个复制(所有实例都指向同一个内存地址),只要静态变量所在的类加载,这个静态变量就会被分配空间,然后就可以使用了。
对静态变量的引用有两种方式,分别为
- 类.静态变量
- 对象.静态变量
实例变量属于对象只有对象被创建后,实例变量才会被分配空间,才能使用,它在内存中存在多个复制。只能用“对象.实例变量”的方式来引用。
示例代码
public class Test {
public static int staticInt = 0;
public int noStaticInt = 0;
public static void main(String[] args) {
Test test = new Test();
System.out.println("test.staticInt " + test.staticInt); // 对象调用
System.out.println("test.staticInt " + Test.staticInt); // 类调用
System.out.println("test.staticInt " + test.noStaticInt);
System.out.println("-----------------------------------------");
System.out.println("对静态变量和实例变量分别 +1");
test.staticInt ++;
test.noStaticInt ++;
Test test1 = new Test();
System.out.println("test.staticInt " + test1.staticInt); // 对象调用
System.out.println("test.staticInt " + Test.staticInt); // 类调用
System.out.println("test.staticInt " + test1.noStaticInt);
}
}
从上例可以看出,静态变量只有一个,被类拥有,所有对象都共享这个静态变量,而实例对象与具体对象相关的。
2.2 static成员方法
与变量差不多,Java类库同时提供了 static 方法与非 static 方法。而static方式是类方法,不需要创建对象就可以调用,而非static 方法是对象的方法,只有对象被创建出来后才可以被使用
static 方法中不能使用 this 关键字和 super 关键字,不能调用非 static 方法,只能访问 所属类的静态成员变量和成员方法,因为 static 方法被调用时,这个类的对象还没有被创建,即使创建了,也无法确定调用那个类的方法。同理,static 方法也不能访问非 static 类型的变量 。
- static一个很重要的用途就是实现单例模式。单例模式的特点是该来只能有一个实例,为了实现这一功能,即把构造函数声明为private,并提供了一个创建对象的静态方法,由于构造函数被声明为private,外界无法直接创建这个类型的对象,只能通过该类提供的方法来获取类的对象要达到这样的目的只能把创建对象的方法声明为static
示例代码
class Singleton {
private static Singleton instance = null;
private Singleton() { } // 无参构造
public static Singleton getInstance() {
if(null == instance) {
instance = new Singleton();
}
return instance;
}
}
- 用 public 修饰的 static 变量和方法本质上都是全局的,若在 static 变量前用 private
修饰,则表示这个变量可以在类的静态代码块或者类的其他静态成员方法中使用,但是不能在其他类中通过类名直接引用。
2.3 static 代码块
static
代码块在类中是独立于成员变量和成员函数的代码块,它不在任何一个方法体内,JVM在加载类时会执行static代码,如果有多个static代码块,JVM将会按顺序执行。static代码块经常被用来初始化常量。需要注意的是,这些static代码块只会执行一次。
示例代码
public calss Test {
private static int a;
static {
Test.a = 4;
System.out.println(a);
System.out.println("static block is called");
}
public static void main(String[] args) {
}
}
2.4 staitc 内部类
static 内部类是指被声明为static 的内部类,它可以不依赖与外部类实例对象而被实例化,而通常的内部类需要在外部类实例化后才能实例化。静态内部类不能与外部类有相同的名字,不能访问外部类的普通成员变量,只能访问外部类中的静态成员和静态方法(包含私有类型)
示例代码:
public class Outer {
static int n = 5;
static class Inner {
void accessAttrFromOuter() {
System.out.println("Inner:Outer.n=" + n);
}
}
public static void main(String[] args) {
Outer.Inner nest = new Outer.Inner();
nest.accessAttrFromOuter();
}
}
2.5 static关键字与final关键字结合使用
static关键字与final关键字结合使用。用来修饰成员变量与成员方法,有点类似于C/C++中的“全局变量”,若使用static
final修饰,则表示一旦赋值,,就不可修改,并且通过类名可以访问,若修饰方法则表示该方法不可覆盖,并且可以类名直接访问。
示例代码:(项目中的代码示例)
public interface HeadLineService {
public static final String HLLISTKEY = "headlinelist";
/**
* 根据传入的条件返回指定的头条列表
*
* @param headLineCondition
* @return
* @throws IOException
*/
List<HeadLine> getHeadLineList(HeadLine headLineCondition);
}
书籍:java程序员面试宝典