zoukankan      html  css  js  c++  java
  • 关于Java中的static关键字

    Java中的 static 关键字,确实是一个关键的字(key word),今天就来总结一下它的用法,说说为什么关键。

    Java中的 static 关键字主要是用来做内存管理的。理解了这句话才能够比较深入地理解static。

    static 可以修饰:

    1. 变量(所谓 class variable)
    2. 方法(所谓 class method)
    3. 代码块(所谓 block)
    4. 内部类(所谓 nested class)

    凡是被 static 修饰的这四种元素,都属于class的元素,即类的,而不是类的实例的。

    1) 静态变量

    在声明变量的时候加上 static ,该变量即是静态变量。

    • 什么时候该用 static 来修饰变量呢?该变量被该类的所有实例所共享。
    • 静态变量在类被加载的时候初始化,且仅分配一次内存。

    这样做的好处就是内存利用率高,看下下面两个demo:

    1 // Understanding problem without static variable
    2 class Student{  
    3      int stuNo;  
    4      String name;  
    5      String college="ITS";  
    6 }  

    假设这个"niubility my brother" 的学校有500000000个学生,那么当每一个学生被创建的时候,都会初始化学号、姓名、学校,每个学生都有自己的学号和姓名,这样做没问题;但是每个学生的college字段都相同,如果每次都声明一遍的话,是比较耗内存的。这里的college变量其实是被该类的所有实例所共享的,因此可以将它声明为 static 的。

     1 //Program of static variable  
     2 class Student8{  
     3    int rollno;  
     4    String name;  
     5    static String college ="ITS";  
     6      
     7    Student8(int r,String n){  
     8    rollno = r;  
     9    name = n;  
    10    }  
    11  void display (){System.out.println(rollno+" "+name+" "+college);}  
    12   
    13  public static void main(String args[]){  
    14  Student8 s1 = new Student8(111,"Karan");  
    15  Student8 s2 = new Student8(222,"Aryan");  
    16    
    17  s1.display();  
    18  s2.display();  
    19  }  
    20 }  
    Output:111 Karan ITS
           222 Aryan ITS

    看下实际内存分配情况:

    静态变量分配在了方法区,堆中该类的所有实例共享方法区中的college。

    再看一下下面这个栗子:Counter 类中声明了一个count变量,在构造函数中对其进行++操作,因为实例变量在对象被创建的时候分配内存,所有每一个对象都有一份自己的count副本,每个对象对各自count的++操作不会反应到其他对象上。

     1 class Counter{  
     2 int count=0;//will get memory when instance is created  
     3   
     4 Counter(){  
     5 count++;  
     6 System.out.println(count);  
     7 }  
     8   
     9 public static void main(String args[]){  
    10   
    11 Counter c1=new Counter();  
    12 Counter c2=new Counter();  
    13 Counter c3=new Counter();  
    14   
    15  }  
    16 }  
    Output:1
           1
           1

    因为静态变量仅仅在类加载的时候分配一次内存,所以如果将count修饰为static,那么该类的所有对象将会共享该变量,每一个对象对count的操作都会反应到其他对象上。

     1 class Counter2{  
     2 static int count=0;//will get memory only once and retain its value  
     3   
     4 Counter2(){  
     5 count++;  
     6 System.out.println(count);  
     7 }  
     8   
     9 public static void main(String args[]){  
    10   
    11 Counter2 c1=new Counter2();  
    12 Counter2 c2=new Counter2();  
    13 Counter2 c3=new Counter2();  
    14   
    15  }  
    16 }
    Output:1
           2
           3

    2)静态方法

    在声明方法的时候加上 static 关键字,即静态方法:

    • 静态方法属于类而不是对象。
    • 静态方法可以直接通过类名调用,而不需要创建类的对象。
    • 静态方法可以修改静态变量,而非静态方法不可以。

    一个静态方法的栗子:

     1 //Program of changing the common property of all objects(static field).  
     2 class Student9{  
     3      int rollno;  
     4      String name;  
     5      static String college = "ITS";  
     6        
     7      static void change(){  
     8      college = "BBDIT";  
     9      }  
    10   
    11      Student9(int r, String n){  
    12      rollno = r;  
    13      name = n;  
    14      }  
    15   
    16      void display (){System.out.println(rollno+" "+name+" "+college);}  
    17   
    18     public static void main(String args[]){  
    19     Student9.change();  
    20   
    21     Student9 s1 = new Student9 (111,"Karan");  
    22     Student9 s2 = new Student9 (222,"Aryan");  
    23     Student9 s3 = new Student9 (333,"Sonoo");  
    24   
    25     s1.display();  
    26     s2.display();  
    27     s3.display();  
    28     }  
    29 }  
    Output:111 Karan BBDIT
           222 Aryan BBDIT
           333 Sonoo BBDIT

    静态方法的第二颗栗子:

     1 //Program to get cube of a given number by static method  
     2 class Calculate{  
     3   static int cube(int x){  
     4   return x*x*x;  
     5   }  
     6   
     7   public static void main(String args[]){  
     8   int result=Calculate.cube(5);  
     9   System.out.println(result);  
    10   }  
    11 }  

    静态方法的两个注意点:

    1. 静态方法不能操作非静态变量,也不能调用非静态方法。(这个可以这样理解:静态方法属于类,直接通过类名就可以调用,而此时可能没有任何实例,更谈不上操作实例变量和调用实例方法了。)
    2. 静态方法中不能使用 thissuper 关键字。(道理同上)
    1 class A{  
    2  int a=40;//non static  
    3    
    4  public static void main(String args[]){  
    5   System.out.println(a);  
    6  }  
    7 }   
    Output:Compile Time Error

    Q)为什么Java的main方法是static的?

    Ans)为了使得在调用main方法之前不需要创建任何实例对象。

    3)静态代码块

    为什么要有这个东西?干嘛用呢?

    • 用来初始化静态变量。
    • 在类加载时,在执行main方法之前执行相关操作。

    栗子:

    1 class A2{  
    2   static{System.out.println("static block is invoked");}  
    3   public static void main(String args[]){  
    4    System.out.println("Hello main");  
    5   }  
    6 }  
    Output:static block is invoked
           Hello main

    Q)没有main方法的程序可以执行吗?

    Ans)可以,在JDK1.7之前执行如下代码是可以的:

    1 class A3{  
    2   static{  
    3   System.out.println("static block is invoked");  
    4   System.exit(0);  
    5   }  
    6 }  
    Output:static block is invoked (if not JDK7)

    但是在JDK1.7会报如下错误:

    Output:Error: Main method not found in class A3, please define the main method as:
    public static void main(String[] args)

    4)静态内部类

    被static修饰的类,并且处于某个类的内部。

    • 它可以访问外部类的静态成员,包括private成员。
    • 它不能访问外部类的非静态成员。(原因前面说过)

    那么为什么要有静态内部类呢?看下面的栗子:

     1 class TestOuter1{  
     2   static int data=30;  
     3   static class Inner{  
     4    void msg(){System.out.println("data is "+data);}  
     5   }  
     6   public static void main(String args[]){  
     7   TestOuter1.Inner obj=new TestOuter1.Inner();  
     8   obj.msg();  
     9   }  
    10 }  
    Output:data is 30

    main方法中创建了一个静态内部类的实例,并且调用了其msg() 方法。但是这里并没有创建外部类的实例,因为这里的Inner类是static的,并且可以访问外围类的static成员。如果把Inner之前的static去掉,那么这里要这样写:

    TestStaticInnerClass.Inner obj=new TestStaticInnerClass().new Inner();

    需要先创建外一个部类实例,然后才能创建内部类实例。静态内部类不仅高效利用内存,而且使得代码简洁。下面是static 内部类编译后的样子:

     1 // Internal class generated by the compiler
     2 import java.io.PrintStream;  
     3 static class TestOuter1$Inner  
     4 {  
     5 TestOuter1$Inner(){}  
     6 void msg(){  
     7 System.out.println((new StringBuilder()).append("data is ")  
     8 .append(TestOuter1.data).toString());  
     9 }    
    10 } 

    上例中,如果msg() 方法也是静态的,那么内部类的实例也不需要创建了:

    1 class TestOuter2{  
    2   static int data=30;  
    3   static class Inner{  
    4    static void msg(){System.out.println("data is "+data);}  
    5   }  
    6   public static void main(String args[]){  
    7   TestOuter2.Inner.msg();//no need to create the instance of static nested class  
    8   }  
    9 }  
    Output:data is 30

    以上是关于Java 中 static 关键字的理解,参考了:http://www.javatpoint.com/

  • 相关阅读:
    图片懒加载原理-实例二
    节流函数(throttle)的原理
    防抖动函数(debounce)的原理
    立即执行函数(immediate)的原理
    图片懒加载原理-实例三
    图片懒加载原理-实例四:首屏加载
    js运算符优先级
    java实现链栈
    java实现栈
    静态链表以及几种表的比较
  • 原文地址:https://www.cnblogs.com/HarrisonHao/p/6102343.html
Copyright © 2011-2022 走看看