以前自己对static这个关键字了解的一直不是很透彻,通过查阅资料,自己才更深刻的理解,今与众位分享:
static关键字在类中可以声明属性或方法。声明的属性将称为全局属性,声明的方法将成为类方法。
1、声明属性
通过两个例子进行比较
代码1:
class Person {
private String name;
private int age;
String country = "A 城";
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getInfo() {
return "姓名:" + this.name + ",年龄:" + this.age + ",城市:" + country;
}
};
public class StaticDemo01 {
public static void main(String args[]) {
Person per1 = new Person("张三", 20);
Person per2 = new Person("李四", 21);
Person per3 = new Person("王五", 22);
System.out.println(per1.getInfo());
System.out.println(per2.getInfo());
System.out.println(per3.getInfo());
}
};
但是以上的程序存在了一个问题,现在的所有人的城市都是在A城,但是后来这个城市的名字修改成了X城,那么如果现在已经产生了500000个Person对象,肯定现在要修改50000次对象中的country属性,因为按照内存的分配来讲,每一个对象都单独占着各自的country的属性。
现在以上的设计根本就无法满足,因为对于country属性而言,肯定是所有对象都是一样的,而且如果按照以上的设计,每个对象占用每个对象自己的country属性的话,则肯定会造成内存空间的浪费,那么就可以将country属性设置成一个公共属性,那么公共属性就可以使用static进行操作。
代码2:class Person {
private String name;
private int age;
static String country = "A城";
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getInfo() {
return "姓名:" + this.name + ",年龄:" + this.age + ",城市:" + country;
}
};
public class StaticDemo02 {
public static void main(String args[]) {
Person per1 = new Person("张三", 20);
Person per2 = new Person("李四", 21);
Person per3 = new Person("王五", 22);
System.out.println(per1.getInfo());
System.out.println(per2.getInfo());
System.out.println(per3.getInfo());
System.out.println("---------------------");
per1.country = "B城";
System.out.println(per1.getInfo());
System.out.println(per2.getInfo());
System.out.println(per3.getInfo());
}
}
现在发现修改了一个对象中的country属性之后,所有对象的country属性都发生了变化,那么country属性肯定就成为了公共属性,所有的对象可以同时拥有,但是一般而言这些公共属性虽然可以使用普通的对象调用,可一般不这样操作,而是通过所有对象的最大级 —— 类,完成调用。
由于全局属性拥有可以通过类名称直接访问的特点,所以这种属性又称为类属性。
2、声明方法:
对于属性而言,不管是何种属性都要考虑封装,对于全局属性也不例外,那么既然全局属性可以通过类名称访问,那么也可以使用static定义一个“类方法”,很明显此方法也可以通过类名称直接访问。
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 static void setCountry(String c) {
country = c;
}
public String getInfo() {
return "姓名:" + this.name + ",年龄:" + this.age + ",城市:" + country;
}
};
public class StaticDemo03 {
public static void main(String args[]) {
Person per1 = new Person("张三", 20);
Person per2 = new Person("李四", 21);
Person per3 = new Person("王五", 22);
System.out.println(per1.getInfo());
System.out.println(per2.getInfo());
System.out.println(per3.getInfo());
System.out.println("---------------------");
Person.setCountry("B城");
System.out.println(per1.getInfo());
System.out.println(per2.getInfo());
System.out.println(per3.getInfo());
}
};
3、static的使用注意
static本身声明方法或声明属性,但是在方法的访问上本身也存在着问题。
1、 使用static声明的方法,不能访问非static的操作(属性或方法)
2、 非static声明的方法,可以访问static声明的属性或方法
代码3:
class Person {
static String country = "A城";
private String name;
public static void setCountry(String c) {
print();
System.out.println(name);
}
public void print() { // 非static方法
}
};
此代码就会报错。
代码4:
class Person {
static String country = "A城";
private String name;
public static void setCountry(String c) {
}
public void print() { // 非static方法
setCountry("");
System.out.println(country);
}
};
此代码不会报错。
那么,为什么呢?
1、 如果说现在一个类中的属性或方法都是非static类型的,肯定是要有实例化对象才可以调用。
2、 static声明的属性或方法可以通过类名称访问,可以在没有实例化对象的情况下调用。
当一个实例化对象产生之后,可以调用所有的非static的操作,那么肯定也就可以调用所有的static操作。
代码5:
public class StaticDemo05 {
public static void main(String args[]) {
new StaticDemo05().printInfo();
}
public void printInfo() {
System.out.println("Hello World!!!");
}
};
此代码没有任何问题。
在静态方法中若新建一个对象,用这个对象是可以调用非静态方法 的。
4、扩展
既然static的属性是所有对象所共同拥有的,那么就可以利用此特点完成一个自动命名的功能。
代码6:
class Book {
private String name;
private static int count = 0;
public Book() {
this.name = "无名字 - " + ++count;
}
public Book(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
public class StaticDemo06 {
public static void main(String args[]) {
System.out.println(new Book("JAVA基础").getName());
System.out.println(new Book().getName());
System.out.println(new Book().getName());
System.out.println(new Book().getName());
System.out.println(new Book("Oracle").getName());
}
};