static静态关键字和代码块

static静态关键字

1.静态特点

A: 被static修饰的成员变量属于类,不属于这个类的某个对象。(即多个对象共享同一个static成员变量)

B: 被static修饰的成员可以通过类名直接访问

访问静态成员的格式:

1
2
3
类名.静态成员变量名

类名.静态成员方法名(参数)

C: 静态的加载优先于对象,随着类的加载而加载

2.静态注意事项

A:静态成员只能直接访问静态成员

B:非静态成员既可以访问非静态成员也可以访问静态成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/*
* static的注意事项:
* 静态方法:
* 可以调用静态的成员变量
* 可以调用静态的成员方法
* 不可以调用非静态成员变量
* 不可以调用非静态成员方法
* 静态方法只能调用静态的成员
* 非静态方法:
* 可以调用静态的成员变量
* 可以调用静态的成员方法
* 可以调用非静态的成员变量
* 可以调用非静态的成员方法
*
* 静态的方法中是否有this这个对象?没有
*/
public class StaticDemo2 {
public static void main(String[] args) {
Student.graduateFrom = "传智学院";
Student.study();
}
}

class Student {
String name;
int age;
static String graduateFrom;//毕业院校

public static void study() {
///System.out.println(graduateFrom);
//sleep();

//System.out.println(name);

//eat();

}

public static void sleep() {
System.out.println("sleep");

}

public void eat() {
System.out.println("eat");

System.out.println(graduateFrom);
sleep();
}

}

3. 静态变量

  • 静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份。
  • 实例变量:每创建一个实例就会产生一个实例变量,它与该实例同生共死。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
* static:是一个关键字,用于修饰成员变量和成员方法
* static的特点:
* 被所有的对象所共享
* 可以使用类名调用
* 静态的加载优先于对象
* 随着类的加载而加载
*
*/
public class StaticDemo {
public static void main(String[] args) {
Person.graduateFrom = "传智学院";

Person p = new Person();
p.name = "小苍同学";
p.age = 18;
//p.graduateFrom = "传智学院";
p.speak();

Person p2 = new Person();
p2.name = "小波同学";
p2.age = 20;
//p2.graduateFrom = "传智学院";
p2.speak();
}
}

class Person {
String name;
int age;
static String graduateFrom;//毕业院校
public void speak() {
System.out.println(name + "---" + graduateFrom);
}
}

4. 静态方法

静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法。

1
2
3
4
5
public abstract class A {
public static void func1(){
}
// public abstract static void func2(); // 静态方法不能是抽象方法
}

只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字。

1
2
3
4
5
6
7
8
9
10
11
public class A {

private static int x;
private int y;

public static void func1(){
int a = x;
// int b = y; // 没有创建对象,无法使用成员变量
// int b = this.y; // 静态变量不能使用this
}
}

5. 静态代码块

静态语句块在类初始化时运行一次。

1
2
3
4
5
6
7
8
9
10
public class A {
static {
System.out.println("123");
}

public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
}
} // 输出123

6. 静态内部类

非静态内部类依赖于外部类的实例,而静态内部类不需要。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class OuterClass {

class InnerClass {
}

static class StaticInnerClass {
}

public static void main(String[] args) {
// InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
OuterClass outerClass = new OuterClass();
InnerClass innerClass = outerClass.new InnerClass();
StaticInnerClass staticInnerClass = new StaticInnerClass();
}
}

静态内部类不能访问外部类的非静态的变量和方法。

7. 静态导包

在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低。

1
import static com.xxx.ClassName.*

8.静态的优缺点

A:静态优点:

对对象的共享数据提供单独空间的存储,节省空间,没有必要每一个对象都存储一份

可以直接被类名调用,不用在堆内存创建对象

静态成员可以通过类名直接访问,相对创建对象访问成员方便

B:静态弊端:

访问出现局限性。(静态虽好,但只能访问静态)

9.初始化顺序

静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。

1
public static String staticField = "静态变量";
1
2
3
static {
System.out.println("静态语句块");
}
1
public String field = "实例变量";
1
2
3
{
System.out.println("普通语句块");
}

最后才是构造函数的初始化。

1
2
3
public InitialOrderTest() {
System.out.println("构造函数");
}

存在继承的情况下,初始化顺序为:

  • 父类(静态变量、静态语句块)
  • 子类(静态变量、静态语句块)
  • 父类(实例变量、普通语句块)
  • 父类(构造函数)
  • 子类(实例变量、普通语句块)
  • 子类(构造函数)
0%