1 静态变量
1.1 成员变量
作为类的成员,在类体中声明的变量称为成员变量,成员变量有三种:
- 一种是实例变量:是属于每个对象属性,每个对象中都有一份
- 一种是静态变量:是属于类的变量,只有一份,全体对象共享的同一份变量
- 一种是常量:是不变的常数
成员变量示例如下:
1.2 静态变量
使用static修饰类的成员变量,称为静态变量。静态变量只有一份,是可以被全体对象共享的一份变量,这点与实例变量有着巨大的差异。实例变量是每个对象实例都有一份的变量。而静态变量是无论用类创建多少对象,都始终唯一的变量。
静态变量和类的信息一起存储在方法区,是属于类的变量。
可以用静态变量存储程序中只有一个就够的数据,比如:办公软件项目中的公司名称和公司LOGO,地图应用中的各类图标,只需要加载一份就可以了。多份相同的数据反而会浪费大量的时间和存储空间。
1.3 静态变量的访问
因为静态变量是属于类的变量,所以使用“类名.变量名”访问,在类的内部可以省略类名。
静态变量关键点:
- 静态变量只有一份,可以被全体对象共享
- 软件中只有一份的数据应该使用static修饰
查看如下示例:
类Foo定义了静态变量 b,使用 Foo.b 访问。
在类中定义静态变量,并编写代码测试其特点。
案例示意代码如下:
public class StaticDemo1 {
public static void main(String[] args) {
Soo s1 = new Soo();
Soo s2 = new Soo();
s1.a = 8;
s2.a = 10;
Soo.b = 11; //使用类名访问静态变量
System.out.println(s1.a + "," + s1.b); //8,11
System.out.println(s2.a + "," + s2.b); //10,11
System.out.println(Soo.b); //11 读取静态变量
}
}
class Soo{
int a; //实例变量、对象属性
static int b; //静态变量
}
1.4 静态变量工作原理
在面试中经常有问起静态变量工作原理的。简单的说就是静态变量在类加载期间在方法区中分配,静态变量是属于类的变量。
静态变量的具体工作原理是:
1、Java源文件经过编译得到字节码文件,每个类编译为一个class文件
2、当执行Java程序时候,每用到一个类Java就会自动将对应的字节码加载到方法区
- 创建对象时候会自动加载类
- 访问类的静态属性时候会自动加载类
- 执行类中的静态方法时候会自动加载类
- 字节码文件只加载一次
3、如果类中有静态变量,Java就会在加载类期间将其在方法区中分配出来,静态变量也初始化一次,只有一份
4、创建对象时候按照类中声明的实例变量分配对象的属性,每创建一个对象,就会分配一组对象属性。
工作原理如下图所示:
1.5 static final
Java中同时使用static final关键字声明“常量”,常量用于声明不会变化的量。比如:数学中的圆周率PI、自然常数e,物理学中的光速C,都是常量。在软件开发中也会将固定不变的数值声明为常量。比如程序中给用户的提示信息,一般是固定值,就可以声明为常量。 如下所示:
public class Message {
public static final String MSG_LOGINFAILED = “用户名或密码错误”;
public static final String MSG_LOGINSUCC = “登录成功”;
}
1.6 常量的细节
软件中不能改变的数据,应该都定义为常量 :同时使用static final修饰,两个关键字的顺序可以调换。
常量必须初始化,其命名建议都是大写字母,多个单词使用下划线隔开,比如 MAX_VALUE。
Java API中提供了很多常量:
- Math.PI、 Math.E
- Integer.MAX_VALUE、Integer.MIN_VALUE
- Long.MAX_VALUE、Long.MIN_VALUE
2 静态方法
2.1 静态方法
所谓的静态方法就是在方法声明时候添加static关键字。添加了静态关键字的方法称为静态方法,静态方法是属于类的方法。属于类的方法就可以直接使用类名直接引用方法。比如:Math.random()就是一个静态方法。
查看如下示例:
对于 Person 类的 add() 方法,它没有用到当前的属性,则可以定义为静态方法。在使用时,使用类名.方法名() 的方式调用。
2.2 静态方法的细节
当一个方法其方法体中没有用到任何当前对象的属性时候,则此方法就可以定义为静态方法。相反如果方法用到了当前对象的数据,就不能定义为静态方法。这也是是否在方法前面添加static关键字的原则。由于静态方法与对象数据无关,所以静态方法可以使用类名直接访问。
静态方法和对象方法还有一个区别就是,静态方法没有隐含的局部变量this。而对象方法中是保护隐含局部变量this,对象方法就是通过这个this引用访问了当前对象的属性和方法。由于这个差别,就有一个现象:静态方法不能访问实例变量和对象方法。
因为main方法也是静态方法,所以main方法也不能访问当前类型的实例变量和对象方法。
2.3 静态方法示例
在类中定义静态方法,并编写代码测试其特点。
案例示意代码如下:
public class StaticDemo2 {
public static void main(String[] args) {
Person.add(7, 8); //用类名调用静态方法
Person tom = new Person("Tom");
tom.whoru(); //用对象引用调用对象的方法
}
}
class Person{
String name;
public Person(String name) {
this.name = name;
}
public void whoru() {
//对象方法中包含隐含局部变量this
System.out.println("我是"+this.name);
}
//如果方法中没有用到当前对象的属性/方法就声明为static
public static void add(int a, int b) {
//静态方法中没有隐含局部变量this
System.out.println(a+b);
}
}
3 static 其他用法
3.1 代码块
在类中可以使用{}定义代码块,代码块在创建对象时候按照顺序执行,其功能与构造器类似,可以用于初始化对象属性。代码示意如下:
class Cell{
int a;
{
//代码块,在创建对象时候执行
a = (int)(Math.random()*8);
}
}
大多情况下优先使用构造器初始化对象属性,代码块很少被使用,了解即可。
3.2 静态代码块
类中使用static修饰的代码块称为静态代码块。
静态代码块在类加载期间执行,因为Java类只加载一次,所以静态代码块也只执行一次。就是因为这个特性,经常用静态代码块初始化类中的静态属性。如:将图片资源定义为静态属性,然后利用静态代码块加载图片文件,初始化静态图片属性。
静态代码块的使用示例如下:
定义并测试静态代码块,案例示意代码如下:
public class StaticDemo3 {
public static void main(String[] args) {
//Java会在创建对象之前自动加载类Circle
Circle c1 = new Circle();
Circle c2 = new Circle();
System.out.println(Circle.angle);
}
}
class Circle{
static double angle; //角
static {//静态代码块,在类加载期间执行,只执行一次
System.out.println("初始化angle");
angle = Math.PI * 2;
}
}
3.3 静态导入
Java 8 提供了静态导入语法,用于简化静态资源的编码,其语法为:import static。例如:
import static java.lang.Math.PI;
import static java.lang.Math.sin;
import static java.lang.Math.*;
使用示例如下: