static表示“静态”、“全局”的意思,用来修饰成员变量和成员方法的,也可以用来形成静态代码块。
我们来看看static的两个比较重要的使用方式:修改成员变量、修饰成员方法
(1)使用static修改成员变量
使用static修饰的属性叫做全局属性,也叫静态属性。那么全局属性有什么用呢?我们先来观察代码:
我们先定义一个类Person,类中定义属性,为了观察方便,暂时不用private进行封装。
定义属性姓名、年龄及所在城市,城市的初始值为“A城”
定义构造方法,用来初始化姓名、年龄
定义一个输出方法,用了输出这个Person对象的信息
public class Person {
String name;
int age;
String country = "A城";
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void info(){
System.out.println("姓名:"+this.name+",年龄:"+this.age+",城市:"+country);
}
}
创建Person对象,打印信息:
public static void main(String[] args) {
Person p1 = new Person(“张三”, 60);
Person p2 = new Person(“李四”, 50);
Person p3 = new Person(“王五”, 55);
p1.info();
p2.info();
p3.info();
}
运行结果:
姓名:张三,年龄:60,城市:A城
姓名:李四,年龄:50,城市:A城
姓名:王五,年龄:55,城市:A城
现在,城市改名叫“B城”,我们是不是应该这么修改:
public static void main(String[] args) {
Person p1 = new Person("张三", 60);
Person p2 = new Person("李四", 50);
Person p3 = new Person("王五", 55);
p1.country = "B城";
p2.country = "B城";
p3.country = "B城";
p1.info();
p2.info();
p3.info();
}
如果有5000个Person对象,那么不是要修改5000次?用这样的方式修改肯定是不行的。那么该如何解决这个问题呢?最好的做法是只修改一次,就可以把所有的城市信息都修改了。所以,我们可以用static来修饰城市的属性。
public class Person {
String name;
int age;
static String country = "A城";
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void info(){
System.out.println("姓名:"+this.name+",年龄:"+this.age+",城市:"+country);
}
}
通过对象调用country修改country的值:
public static void main(String[] args) {
Person p1 = new Person("张三", 60);
Person p2 = new Person("李四", 50);
Person p3 = new Person("王五", 55);
System.out.println("修改之前...");
p1.info();
p2.info();
p3.info();
System.out.println("修改之后...");
p1.country = "B城";
p1.info();
p2.info();
p3.info();
}
运行结果:
修改之前…
姓名:张三,年龄:60,城市:A城
姓名:李四,年龄:50,城市:A城
姓名:王五,年龄:55,城市:A城
修改之后…
姓名:张三,年龄:60,城市:B城
姓名:李四,年龄:50,城市:B城
姓名:王五,年龄:55,城市:B城
我们使用p1对象调用属性country 修改了country的值,所有对象的country值都跟着修改了,也就是说,static修改的属性被所有的对象共享,只要进行了一次修改,其它的country都会跟着修改。
静态属性,最好是通过类名调用,因为用户不知道一个类到底产生了多少对象。所以static声明的属性也叫类属性。上述城市的修改最好改成:Person.country = “B城”;
(2)使用static修改成员方法
static可以在声明属性时使用,也可以在声明方法时使用,用static声明的方法也被称为类方法。
将上述Person的属性用private 进行封装,要想设置属性,就必须使用setter方法,这里的setter方法是使用static声明的:
public class Person {
private String name;
private int age;
private static String country = "A城";
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void info(){
System.out.println("姓名:"+this.name+",年龄:"+this.age+",城市:"+country);
}
public static void setCountry(String c){
country = c;
}
public static String getCountry(){
return country;
}
}
调用,因为这里的setter方法是使用static声明的,所以调用的时候可以用类名调用:
public static void main(String[] args) {
Person p1 = new Person("张三", 60);
Person p2 = new Person("李四", 50);
Person p3 = new Person("王五", 55);
System.out.println("修改之前...");
p1.info();
p2.info();
p3.info();
System.out.println("修改之后...");
//Person.country = "B城";
Person.setCountry("B城");
p1.info();
p2.info();
p3.info();
}
结果:
修改之前…
姓名:张三,年龄:60,城市:A城
姓名:李四,年龄:50,城市:A城
姓名:王五,年龄:55,城市:A城
修改之后…
姓名:张三,年龄:60,城市:B城
姓名:李四,年龄:50,城市:B城
姓名:王五,年龄:55,城市:B城
这里需要注意的是,非static方法里可以调用static属性或static方法,但是static方法中不能调用非static属性或非static方法。
我们在info方法中直接调用static属性country是可以的,调用getCountry方法也是可以的。
public void info(){
System.out.println("姓名:"+this.name+",年龄:"+this.age+",城市:"+country);
System.out.println("姓名:"+this.name+",年龄:"+this.age+",城市:"+getCountry());
}
这两种使用方法都是可以的。
但是,我们在setCountry中使用非static的属性name、和非static方法info,则编译不通过:
public static void setCountry(String c){
System.out.println(name);//编译不通过
country = c;
}
public static void setCountry(String c){
info();//编译不通过
country = c;
}
(3)静态代码块
static{}的代码就是静态代码块。它在对象创建之前执行,并且只执行一次。