下面说明static的三种用法:
1、static修饰的变量叫做“静态变量”。
示例代码:
class Animal {
// field 成员变量,一个对象一份
// 成员变量在创建对象的时候初始化,并且存储在堆中的每一个对象中。
String name;
int age;
// 静态变量,存储在方法区,所有的对象共享这一份,所有静态变量是
// 类级别的,使用“类名.”调用。
static String type = "陆生";
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
// 关于代码的顺序
// 编译通过
// static int i = 100;
// static {
// System.out.println(i);
// }
// 编译不通过,提示:非法向前引用
// static {
// System.out.println(j);
// }
// static int j = 100;
}
2、static修饰的方法叫做“静态方法”。
示例代码:
public class StaticTest2 {
// 成员方法
public void function1() {
}
// 静态方法。
// 静态方法中,不能直接访问非静态数据。静态方法中不能使用this
public static void function2() {
System.out.println("静态方法执行");
}
// 为什么main方法定义为static?方便java虚拟机调用
public static void main(String[] args) {
StaticTest2 st = new StaticTest2();
// 成员方法必须使用“引用.”调用
st.function1();
// 静态方法使用“类名.”方式调用。即使用的是“引用.”调用,底层还是使用“类名.”方式调用。
StaticTest2.function2();
function2();
/*
* 编译阶段检查出st是StaticTest2类型,编译通过,
* 执行时,仍然使用“StaticTest2.”的方式访问。
* function2执行不需要对象。
*/
st.function2();
// 空的对象去访问成员的时候会出现空指针异常,
// function2方法不是“成员”而是静态的,所以
// 即便引用是空,也不会报空指针异常。表面上
// 看是使用“引用.”调用,底层还是使用“类名.”方式调用。
StaticTest2 s = null;
s.function2();
}
}
输出结果:
静态方法执行
静态方法执行
静态方法执行
静态方法执行
3、static还可以定义静态语句块。static定义的语句块,在类加载阶段执行,并且只执行一次,并且是至上而下的顺序执行。
示例代码:
public class StaticTest {
{
// 每一次对象创建之前执行,也是至上而下的顺序执行。
System.out.println("实例语句块1");
}
{
System.out.println("实例语句块2");
}
static {
System.out.println("1");
}
static {
System.out.println("2");
}
public StaticTest() {
System.out.println("无参构造方法执行");
}
public static void main(String[] args) {
new StaticTest();
new StaticTest();
System.out.println("main方法被执行");
}
}
输出结果:
1
2
实例语句块1
实例语句块2
无参构造方法执行
实例语句块1
实例语句块2
无参构造方法执行
main方法被执行
4.static关键字还可以修饰类,普通类是不允许声明为静态的,只有内部类才可以。被static修饰的类称为静态内部类,静态内部类可以直接作为一个普通类来使用,体现了Java封装的特性。
在一个类内部定义一个静态内部类:
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法,示例代码:
class Outer{
static class Inner{}
}
class Test {
public static void main(String[] args){
Outer.Inner n = new Outer.Inner();
}
}