java:面向对象-static关键字

一、静态概念 
1 被静态修饰的数据,不再是对象特有的内容,而是所有对象的共享内容。


如上图所示,student类中,每个同学都有自己的姓名和年龄,但是所有同学的学校名都是“itcast”。如果当作普通变量的话,在创建对象时,每个对象都会创建这个变量,造成浪费。
因此把schoolName对象拿出来,让大家共享。这样节约空间。

2 被static修饰的成员,可以通过类名直接调用。

例1:
//Person.java
package cn.itcast.demo01;

public class Person{
      String name;
       static String className;
}

//Test.java
package cn.itcast.demo01;

public class Test{
      public static void main(String[] args){
             System.out.println(Person.className);      //null。 说明在内存中,对象还没创建,但是静态变量已经存在了。

             Person p1 = new Person();
             Person p2 = new Person();
           
             p1.name = "haha";
             p1.className = "aaa";
 
             System.out.println(p1.name);                     //haha
             System.out.println(p1.className);             //aaa
             System.out.println(p2.name);                     //null。特有数据。
             System.out.println(p2.className);             //aaa。 说明static修饰的变量是共享的。
      
             System.out.println(Person.className);       //aaa    说明静态变量可以通过类名直接调用。
      }
}

二、static的内存图 

左边是栈,右边是堆,下方是方法区(方法区很广,其中右边一部分是静态区)。
步骤1: class文件进入到方法区,首先要加载自己的静态成员。
           step1.1:Test.class进入到方法区,加载静态成员main到静态区(类名Test也一起过来)。
           step1.2:Person.class进入到方法区,加载静态成员className到静态去(所属Person也加载过来),并赋默认值null。
步骤2:程序开始执行,运行main方法。JVM到静态区将main方法复制出来一份,压栈执行。
步骤3:执行main的第一句:System.out.println(Person.className);,JVM到静态区找属于Person类的静态属性className,输出null。
            此时还没创建对象呢。 说明在内存中,静态是优于非静态存在的。
步骤4:在堆中创建对象。

                   

三、static的注意事项 
在静态中不能调用非静态。 因为静态先存在,非静态才存在。静态是先人,非静态是后人。静态方法中既不能写this,也不能写super。

//Person.java
package cn.itcast.demo01;

public class Person{
      private String name;
      private static int age;
 
      public static void fun(){
              //System.out.println(name);            //错误。 因为静态存在的时候,非静态还不存在呢。
              System.out.println(age);                 //正确。因为都是静态的。生命周期相同。
      }

      public void fun2(){
              System.out.println(age);                 //正确。非静态的可以调用静态的。后人可以调用前人。
      }
}

四、静态修饰什么时候使用?应用场景是什么?
static是成员修饰符。可以修饰成员方法,也可以修饰成员变量。不能修饰局部变量。
成员变量什么时候加static,要具体分析:当定义事物的时候,要看多个事物有没有共性。如,每个人的学校名称。可以定义为static
成员方法什么时候加static:跟着变量走。如果方法调用的都是静态变量,那么就把这个方法定义为static。如果方法调用了非静态的                                               变量,那么只能定义为非静态方法了。
                                             记住 :用到了非静态成员变量,就只能非静态。没用到非静态成员变量,就用静态。能静态就静态。

//Person.java
package cn.itcast.demo01;

public class Person{
      private String name;
      private static int age;
 
      public  static void fun(){                           //应该定义成静态的方法。因为用到的成员变量都是static的。
              System.out.println(age);                 
      }

      public void fun2(){                                  //必须定义成非静态的方法。因为用到了非静态的成员变量。
              System.out.println(name);             
      }

      public static int sum(int a, int b){             //应该定义为静态方法。因为根本没有用到任何成员变量。仅需要类名就能调用了。
                                                                    //调用这个方法根本不用对象。
              return a+b;
      }
}


五、多态中的静态调用 
静态和对象没有什么关系。

1.静态成员变量:

//Fu.java   
package cn.itcast.demo01;

public class Fu{
      int a = 1;
      static int b = 1;
}

//Zi.java 
package cn.itcast.demo01;

public class Zi{
      int a = 2;
      static int b = 2;
}

//Zi.java 
package cn.itcast.demo01;

public class Test{
      public static void main(String[] args){
            Fu f = new Zi();
            System.out.println(f.a);    //1。
            System.out.println(f.b);    //1。
      }
}



//Fu.java  
package cn.itcast.demo01;

public class Fu{


}
 
//Zi.java 
package cn.itcast.demo01;

public class Zi{
      int a = 2;
      static int b = 2;
}

//Zi.java 
package cn.itcast.demo01;

public class Test{
      public static void main(String[] args){
            Fu f = new Zi();
            System.out.println(f.a);  
            System.out.println(f.b);  
      }
}

//运行结果:
程序报错。    //编译看父类。父类没有,则编译失败。

//Fu.java   
package cn.itcast.demo01;

public class Fu{
      int a = 1;
      static int b = 1;
}

//Zi.java 
package cn.itcast.demo01;

public class Zi{
     
      
}

//Zi.java 
package cn.itcast.demo01;

public class Test{
      public static void main(String[] args){
            Fu f = new Zi();
            System.out.println(f.a);    //1。
            System.out.println(f.b);    //1。
      }
}


2.静态成员函数

//Fu.java   
package cn.itcast.demo01;

public class Fu{
      public static void show(){
            System.out.println("fu...");
      }
}

//Zi.java 
package cn.itcast.demo01;

public class Zi{
      public static void show(){
            System.out.println("zi...");
      }
}

//Zi.java 
package cn.itcast.demo01;

public class Test{
      public static void main(String[] args){
            Fu f = new Zi();
            f.show();             //fu... 
      }
}
//因为静态跟对象无关。静态属于类,不属于对象。f毕竟是父类的引用。
//Fu.java  
package cn.itcast.demo01;

public class Fu{
     
            
     
}

//Zi.java
package cn.itcast.demo01;

public class Zi{
      public static void show(){
            System.out.println("zi...");
      }
}

//Zi.java
package cn.itcast.demo01;

public class Test{
      public static void main(String[] args){
            Fu f = new Zi();
            f.show();           
      }
}
//运行结果:
编译失败。       //编译看父类。

总结:
在多态的方法调用中:
编译:都是看父类,父类有则编译成功;父类没有则编译失败。
运行:静态方法:运行的是父类中的静态方法。                         //因为静态跟对象无关。
           非静态方法:运行的是子类的重写方法。

多态的成员变量:
编译运行全部看父类。

六、定义静态常量 

public static final String COMPANY_NAME = "传智播客";      //java中,常量的名字要求全大写,两个词之间以下划线相连。

注意:
接口中的每个成员变量都默认使用public static final 修饰。

所有接口中的成员变量已经是静态常量,由于接口没有构造方法,所以必须显示赋值。可以直接用接口名访问。











猜你喜欢

转载自blog.csdn.net/pengchengliu/article/details/80556775