static关键字
# 前言
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new
关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。
我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
private double getArea() {
return Math.PI * this.radius * this.radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
创建两个对象:
Circle c1 = new Circle(2.0);
Circle c2 = new Circle(3.0);
2
Circle类中的变量radius是一个实例变量(instance variable)
,它属于类的每一个对象,不能被同一个类的不同对象所共享。
两个对象存储在不同的空间,相互独立,不受影响。
# 类属性、类方法的设计思想
类属性作为该类各个对象之间共享的变量。在设计类时,分析哪些属性不因对象的不同而改变,将这些属性设置为类属性。相应的方法设置为类方法。
如果方法与调用者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用。
使用范围:
在Java类中,可用static修饰属性、方法、代码块、内部类。
被修饰后的成员具备以下特点:
- 随着类的加载而加载
- 优先于对象存在
- 修饰的成员,被所有对象所共享
- 访问权限允许时,可不创建对象,直接被类调用
# 静态属性
在一个类中,类的属性是可以用static
来修饰,如果使用了static
修饰,那么此类变量称为静态属性(或类变量),没有使用static
的属性称为非静态属性(实例变量)。
**实例变量:**就是以前我们写类的属性,随着对象的实例而创建,每个对象的属性都独立存储在独立的堆空间中。每个对象的属性都是独立的,不会影响其他对象的属性。
**静态属性:****随着类的加载而加载。**多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,其他对象再去访问此静态变量时,发现已经是修改过的。静态属性可以称为类变量。
其他说明:
- 静态属性和实例变量的访问方式并无区别。可以通过"
类名.静态属性名
" - 静态属性随着类的加载而加载。
- 由于类只会加载一次,则静态变量在内存中也只会存一份,存在方法区的静态域中。
类变量(类属性)由该类的所有实例共享
public class Person {
public static int total = 0;
private int id;
public Person() {
total++;
id = total;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Test
public void test1() {
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1);
System.out.println(p2);
}
2
3
4
5
6
7
Person{id=1}
Person{id=2}
2
# 内存解析
其中name是string类型,实际上也是在常量池中,不过还没讲到,这个可以暂时忽略。
# 静态方法
使用了static
关键字修饰的方法就叫静态方法。
- 静态方法跟静态属性一样,都是随着类的加载而加载。
- 直接
类名.静态方法名
调用或者对象.静态方法名
- 在
static
方法内部只能访问类的static
修饰的属性或方法,不能访问类的非static
的结构。- 非静态方法既可以调用非静态方法或者属性,也可以调用静态的方法或者属性。
- 在静态方法内不能使用
this
和super
关键字,因为这两个关键字都基于有对象之后才能使用。
类内部调用静态属性,其实已经省略了类名
public class Person {
public static int total = 0;
private int id;
public Person() {
total++;
id = total;
//id = Person.total;
}
}
2
3
4
5
6
7
8
9
10
11
12
# 判断使用场景
开发中,如何确定一个属性是否要声明为
static
?
属性是可以被多个对象共享的,不会随着对象不同而不同的。
开发中,如何确定一个方法是否要声明为
static
?
- 操作静态属性的方法通常设计为静态方法。
- 工具类中的方法,习惯上声明为
static
,比如Math
、Arrays
、Collections