static修饰的变量习惯称为静态变量,static修饰的方法称为静态方法,static修饰的代码块叫做静态代码块。

 “static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”   --《java编程思想》

 静态,以static关键字修饰的,包括类,方法,块,字段。非静态,指没有用static 修饰的。

特点:

1.全局唯一,任何一次的修改都是全局性的影响

2.只加载一次,优先于非静态

3.使用方式上不依赖于实例对象。

4.生命周期属于类级别,从JVM 加载开始到JVM卸载结束。

1)static变量

  static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

 static成员变量的初始化顺序按照定义的顺序进行初始化。

public   static String sr ="woshidashabi";

静态变量跟实例变量的区别:

1.静态变量:由static修饰,在JVM中,静态变量的加载顺序在对象之前,因此静态变量不依附于对象存在,可以在不实例化类的情况下直接使用静态变量,如下代码所示。

public class StaticTest {
    static int a = 13;
    int b = 14;
  public static voidmain(String[] args) {
       int c = StaticTest.a;
        System.out.println(c);
    }
}

静态变量属于类,不属于类中任何一个对象,因此静态变量又叫做类变量,一个类不管创建多少个对象(对象是类的一个实例),静态变量在内存中有且仅有一个。

2.实例变量:必须依附于对象存在,只有实例化类后才可以使用此类中的实例变量。

public class StaticTest {
    static int a = 13;
    int b = 14; 
    public static voidmain(String[] args) {
        int d = new StaticTest().b;
        System.out.println(d);
    }
}

2)static方法

  static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。

public static void f(){......};

静态方法跟实例方法的区别:

1.静态方法:方法用static关键字修饰,静态方法与静态成员变量一样,属于类本身,在类装载的时候被装载到内存,不自动进行销毁,会一直存在于内存中,直到JVM关闭。使用时也是不需要实例化类,能够直接使用。静态方法无法被重写。

public class StaticTest {
    public static void MyStatic(){
        System.out.println("这是StaticTest的一个静态方法");
    }
    public static voidmain(String[] args) {
        StaticTest.MyStatic();
    }
}

需要注意的是:在静态方法中只能访问类中的静态成员跟静态方法,不能直接访问类中的实例变量跟实例方法,原因是静态方法在JVM中的加载顺序也在对象之前,直接使用实例变量跟实例方法的话,可能实例变量跟实例方法所依附的对象并没有被创建,会导致无法找到所使用的实例变量跟实例方法。

要想使用实例变量跟实例方法可以采用如下方法:在静态方法中创建实例变量和实例方法所在的对象,通过这个对象来使用实例变量跟实例方法。如代码所示:

public class StaticTest {
    int b = 14;
    public void MyMethod(){
        System.out.println("这是StaticTest的一个实例方法");
    }
    public static void MyStatic(){
        StaticTest st = newStaticTest();
        int e = st.b;
        st.MyMethod();
    }
}

2.实例化方法:属于实例对象,实例化后才会分配内存,必须通过类的实例来引用。不会常驻内存,当实例对象被JVM 回收之后,也跟着消失。

public class StaticTest {
    public void MyMethod(){
        System.out.println("这是StaticTest的一个实例方法");
    }
    public static voidmain(String[] args) {
        newStaticTest().MyMethod();
    }
}

3)static代码块

static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。在静态方法里面只能直接调用同类中其他的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。因为对于非静态的方法和变量,需要先创建类的实例对象后方可使用,而静态方法在使用前不用创建任何对象。

声明方式:

static{
         startDate = Date.valueOf("1946");
         endDate = Date.valueOf("1964");
    }

非静态代码块的执行顺序在构造方法执行之前,类每new一次都会执行。声明方式:不加任何修饰符

{
        startDate =Date.valueOf("1946");
        endDate = Date.valueOf("1964");
     }

4)static类

静态内部类(嵌套类)和非静态内部类的区别

(1)内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。

(2)非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。他只能访问外部类的静态成员。

(3)一个非静态内部类不能脱离外部类实体被创建,一个非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面。

class OuterClass{
  private static String msg = "GeeksForGeeks";
  // 静态内部类
  public static class NestedStaticClass{
    // 静态内部类只能访问外部类的静态成员
    public void printMessage() {
     // 试着将msg改成非静态的,这将导致编译错误 
     System.out.println("Message from nested static class: " + msg); 
    }
  }
  // 非静态内部类
  public class InnerClass{
    // 不管是静态方法还是非静态方法都可以在非静态内部类中访问
    public void display(){
     System.out.println("Message from non-static nested class: "+ msg);
    }
  }
} 
class Main
{
  // 怎么创建静态内部类和非静态内部类的实例
  public static void main(String args[]){
    // 创建静态内部类的实例
    OuterClass.NestedStaticClass printer = new OuterClass.NestedStaticClass();
    // 创建静态内部类的非静态方法
    printer.printMessage();  
    // 为了创建非静态内部类,我们需要外部类的实例
    OuterClass outer = new OuterClass();    
    OuterClass.InnerClass inner = outer.new InnerClass();//这样new出来的
    // 调用非静态内部类的非静态方法
    inner.display();
    // 我们也可以结合以上步骤,一步创建的内部类实例
    OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
    // 同样我们现在可以调用内部类方法
    innerObject.display();
  }
}

附加:

1.线程安全:静态方法是共享代码段,静态变量是共享数据段。既然是“共享”就有并发的问题。非静态方法是针对确定的一个对象的,所以不会存在线程安全的问题。

2.如果静态方法在系统中定义太多,会占用大量的资源,最后造成内存溢出,所以静态方法不能滥用。