static的详细讲解

来源:互联网 发布:三菱伺服调试软件 编辑:程序博客网 时间:2024/05/16 14:38

以前自己对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());}};