什么是静态变量
最初接触main方法,它用static修饰,用static修饰方法叫静态方法,用static修饰变量叫静态变量。
静态变量与成员变量一样都是定义在方法外,但与成员变量有本质的区别。
1、静态变量与对象无关,成员变量与对象有关。
静态变量与类有关,也称为类变量,加载类文件到方法区时在堆中单独开一个静态变量的空间用于存储静态变量。
成员变量与对象有类,创建对象后成员变量在对象内存区开辟内存空间,所以成员变量也叫实例变量。
可以理解为:每个对象有自己的成员变量,每个对象共用一份静态变量。
2、定义静态变量需要在成员变量的基础上添加static关键字。
语法格式如下:
权限修饰 static 数据类型 变量名。
3、访问方式不同。
访问静态变量的方法:
类名.静态变量名
访问成员变量必须通过对象访问。
静态变量的例子
下边通过代码演示静态变量与成员变量的区别。
在com.pbteach.javase.oop.classmember.staticmember包下定义Lion类。
下边代码实现了Lion类id编号的自动生成。
package com.pbteach.javase.oop.classmember.staticmember;
import java.nio.charset.MalformedInputException;
import com.pbteach.javase.oop.classmember.method.Tiger;
/**
*
* 静态变量实现自增编号
*
* @author 攀博课堂
* @version v1.0
*/
public class Lion {
private long id;
private String name;
private int weight;
private int age;
private static long idIndex = 0;
public Lion(String name, int weight, int age) {
this.id = ++idIndex;
this.name = name;
this.weight = weight;
this.age = age;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
Lion lion1 = new Lion("乖乖狮1", 500, 2);
Lion lion2 = new Lion("乖乖狮2", 300, 1);
Lion lion3 = new Lion("乖乖狮3", 200, 1);
System.out.println(lion1.getId());
System.out.println(lion2.getId());
System.out.println(lion3.getId());
}
}
输出:
1
2
3
lion1和lion2两个对象为什么可以操作同一个成员变量?要搞懂需要学习静态变量相关的知识。
Lion类中,idIndex为私有静态变量。
static表示静态,可以修饰成员变量和成员方法,在成员变量前加static叫静态变量,它有什么特点?和非静态成员变量有什么区别?
1)作用域不同,静态变量可被多个对象所共享,它是随着类文件加载在内存,也叫类变量。成员变量是随着对象的创建在内存开辟空间,每个对象中的成员变量互不影响,成员变量也叫实例变量。
见下图,Lion的静态变量区和对象实例区域是分开的。
2)访问方式不同
静态变量被所在类的对象共享,它属于类级别的变量,通过类名即可访问,成员变量只能通过对象来访问。
如下代码:
//通过类名来访问静态变量
System.out.println(Lion.idIndex);
建议在方法中不要使用this来访问静态变量,因为静态变量与对象没有直接关系。
//不建议用this来访问静态变量
//++this.idIndex;
//建议用类名来访问静态变量
++Lion.idIndex++;
所以代码应该idIndex的自增代码应该更改为:
public Lion(String name, int weight, int age) {
this.id = ++Lion.idIndex;
this.name = name;
this.weight = weight;
this.age = age;
}
最后分析下程序的执行步骤:
//在堆中创建新的Lion对象,执行参数构造方法,自增idIndex变量的值为1,将其值赋值给id属性
Lion lion1 = new Lion("乖乖狮1", 500, 2);
//在堆中创建新的Lion对象,执行参数构造方法,自增idIndex变量的值为2,将其值赋值给id属性
Lion lion2 = new Lion("乖乖狮2", 300, 1);
//在堆中创建新的Lion对象,执行参数构造方法,自增idIndex变量的值为3,将其值赋值给id属性
Lion lion3 = new Lion("乖乖狮3", 200, 1);
静态方法与实例方法不同
静态方法用static修饰,实例方法没有static修饰,main就是一个静态方法。
静态方法与实例方法区别的是:
1)可访问的对象不同,静态方法可访问静态变量、静态方法,不能访问成员变量(实例变量)及实例方法;实例方法可以访问静态变量、静态方法、成员变量(实例变量)及实例方法,总结为:静态方法可以访问静态成员(静态变量、静态方法),实例方法可以访问静态成员和实例成员(实例成员和实例方法)。
例子1:
package com.pbteach.javase.oop.classmember.staticmember;
public class Lion {
public static void test1() {
System.out.println("测试1");
}
public static void test2() {
System.out.println("测试2");
}
public void test3() {
System.out.println("测试3");
}
public static void main(String[] args) {
//下边三条语句哪个编译失败
test1();
test2();
test3();
}
}
test3()编译失败,因为test3()是实例方法,静态方法中只能调用静态方法。
例子2:
package com.pbteach.javase.oop.classmember.staticmember;
public class Lion {
//showLionInfo1和showLionInfo2哪个编译失败
public static void showLionInfo1() {
System.out.println(id+" "+name+" "+weight+" "+age);
System.out.println(Lion.idIndex);
}
public void showLionInfo2() {
System.out.println(id+" "+name+" "+weight+" "+age);
System.out.println(Lion.idIndex);
}
}
showLionInfo1方法编译失败,showLionInfo1方法中输出id、name、weight、age的值,由于本方法为静态方法,无法访问实例变量,静态方法只允许访问静态变量。System.out.println(Lion.idIndex);可以正常执行,不论静态方法还是实现 方法都可以通过类访问静态变量。
2)调用方式不同,静态方法通过类名调用,实例方法通过对象调用。
例子:
package com.pbteach.javase.oop.staticmember;
/**
*
* 静态变量实现自增编号
*
* @author 攀博课堂
* @version v1.0
*/
public class Lion {
...
public static void main(String[] args) {
Lion lion1 = new Lion("乖乖狮1", 500, 2);
//静态方法通过类名调用,不推荐使用对象引用调用
Lion.showLionInfo1();
//实现方法只能通过对象引用调用
lion1.showLionInfo2();
}
什么时候用static
通常一些系统配置 参数可以使用静态变量来存储 ,一些工具类的方法使用静态方法实现。