java:面向对象-static关键字

一、静态概念                                                                                                                     点击此处返回总目录

二、static的内存图 

三、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 修饰。

 

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

 

 

 


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值