static主要有以下五个作用:
- 静态变量
- 静态方法
- 静态代码块
- 静态内部类
- 静态导包
下面一一介绍。
静态变量
static修饰变量,使其成为静态变量。我们通常将static修饰的变量成为类变量,这主要是相对于属于对象的普通变量来说的,静态变量可以直接通过类名.变量使用。当然静态变量也是可以通过对象获取的,但是阿里巴巴Java开发手册建议直接通过类名访问,减少解析与内存成本。
public class StaticClass {
public static String staticStr;
}
public class Main {
public static void main(String[] args) {
String str = StaticClass.staticStr;
}
}
静态变量与非静态变量区别:
- 静态变量属于类,被此类的所有对象共享,在内存中只有一份副本,在类初次加载时初始化
- 非静态变量属于对象,在创建对象时初始化,在内存中存在多份副本,各个对象之间互不影响
具体的类的初始化过程可以看此篇博文:类的初始化过程
静态方法
static修饰方法,使其成为静态方法。同样的,我们经常将静态方法叫做类方法,静态方法也可以通过类名.方法名来访问。静态方法也可以通过对象获取,但是依然不建议这么做,理由同上。
public class StaticClass {
public static String getStaticStr(){
return "static string";
}
}
public class Main {
public static void main(String[] args) {
String str = StaticClass.getStaticStr();
}
}
静态方法注意事项:
- 静态方法不能访问非静态方法与非静态变量,但非静态方法可以访问静态方法与静态变量
- 静态方法中不能使用this,因为静态方法属于类,不依附于任何对象
静态代码块
静态代码块主要用于累的初始化操作,静态代码块中同样不能访问非静态方法与非静态变量。
静态代码块的主要作用是提升程序性能。
public class Student {
private Integer age;
public Student(Integer age){
this.age = age;
}
public Boolean isBetween(){
Integer startAge = new Integer(10);
Integer endAge = new Integer(20);
return this.age.compareTo(startAge) >= 0 && this.age.compareTo(endAge) <= 0;
}
}
isBetween()的作用是判断Student的年龄是否处于10-20岁,可以看到,每次进行判断时,都会生成startAge与endAge两个对象,造成内存浪费。若代码用静态代码块,如下所示。startAge与endAge都只会被初始化一次。所以很多时候会将只初始化一次的操作放到静态代码块中执行。
public class Student {
private Integer age;
private static Integer startAge;
private static Integer endAge;
static {
Integer startAge = new Integer(10);
Integer endAge = new Integer(20);
}
public Student(Integer age){
this.age = age;
}
public Boolean isBetween(){
return this.age.compareTo(startAge) >= 0 && this.age.compareTo(endAge) <= 0;
}
}
静态内部类
静态内部类属于内部类的一种。详细内容请看此篇博文,此处不再赘述。Java内部类
这里主要讨论下静态内部类的作用。
为什么要有内部类?
- 方便将存在一定逻辑关系的类组织在一起,同时又能对外部隐藏。
- 如果涉及一个类B只是为了给类A使用,那么就可以将类B设计为内部类,防止其与其他类发生依赖关系。
再说一下为什么要有静态内部类。
- 静态内部类英文名叫做"static nested calss",即静态嵌套类。嵌套可以理解为我只是借用你的外壳,静态内部类和你外部类不是强依赖关系,没有外部类对象一样可以创建静态内部类实例;而且我也不需要访问你外部类的非静态变量和非静态方法,那么就可以把此内部类设计为静态内部类。
- 那么不符合上述要求的内部类,就应该设计为普通内部类。我作为内部类需要你外部类的对象才可以创建,或者我需要访问外部类的所有静态非静态的成员与方法。
静态导包
静态导包就是java包的静态导入。
一般我们导入一个类时
import com.xxx.....ClassName;
静态导入的话,如下所示。
import static com.xxx.....ClassName.*; // 导入此类中的所有静态方法
import static com.xxx.....ClassName.staticMethod; // 将*替换为静态方法名,只导入此静态方法
静态导入后,就可以在这个直接用方法名调用静态方法,而不必使用类名.静态方法名的方法。
举个例子,静态导包前:
public class Main {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
}
}
静态导包后:
import static java.lang.System.*;
import static java.lang.Integer.*;
public class Main {
public static void main(String[] args) {
out.println(MAX_VALUE);
out.println(MIN_VALUE);
}
}
静态导入需要注意几个点:
- 是import static,注意不要搞错顺序
- 当多个静态导入的类中有相同的静态成员或是静态方法时,会产生歧义;当然,正常导入的包也可能会有这个问题。
现在编译器都可以直接帮你导入所需要的的包,静态导入了解即可。