Static关键字

来源:互联网 发布:餐厅收银软件 免费 编辑:程序博客网 时间:2024/06/07 01:44

    • 前言
    • 定义
    • 基本使用
    • 基础知识
    • 静态变量
    • 静态方法
    • 静态代码块
    • 静态内部类

前言

Static关键字的重要性,对于Java开发者都知道,不用多说,但是Static关键字的知识点比较多,不容易记住,或者说很容易忘,楼主也是前后学习了好几次Static关键字的用法,每次学完都很清晰,但是时间长了遇到Static还是感觉有点蒙,索性今天就好好在研究一番,并且记录下来供大家一起学习.

定义

static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。

Static关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例的情况下直接被访问。static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。

简单说就是;方便在没有创建对象的情况下来进行调用(方法、变量)。

基本使用

  • 1、被static修饰的变量属于类变量,可以通过类名.变量名直接引用,而不需要new出一个类来
  • 2、被static修饰的方法属于类方法,可以通过类名.方法名直接引用,而不需要new出一个类来

被Static修饰的变量和方法,都属性类级别的静态资源。在类实例之间共享,可以说一处变,处处变。

基础知识

  • static修饰的变量叫做”静态变量”

  • static修饰的方法叫做”静态方法”

  • static还可以定义静态语句块

  • 静态成员变量只有一份

  • 静态变量可以用类名+.调用

  • 所有的对象使用的静态变量的值都是同一份

  • 静态变量不是对象层次的变量,而是类层次的变量

  • 一个静态变量不属于某个对象,而是属于这个类

    被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。

            用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象市,不生成static变量的副本,而是类的所有实例共享同一个static变量。

            static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用–废话),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,static表示不要实例化就可以使用,这样就容易理解多了。static前面加上其它访问权限关键字的效果也以此类推。

静态变量

静态变量存储在方法区,所有java对象共享这一份.所有静态变量是类级别的,使用”类名.”的方式访问.

按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是:

  • 对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
  • 对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。

静态方法

在静态函数当中不能使用this .

静态函数中不能使用非静态的成员变量

静态方法中不能直接访问非静态数据.

一般工具类中的方法大部分都是静态方法.
静态方法不用创建对象也能直接访问该方法.
可以使用”类名.”方式调用.也可以用”引用.”,即使用的是”引用.”,底层还是用的” 类名.”.

静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!
        因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。

静态代码块

静态代码块在类装载之前执行

静态代码块用来为静态变量附初始值

类加载阶段执行static语句块,并且只执行一次.并且是自上而下的顺序执行而实例语句块:每一次调用构造方法之前会执行一次,自上而下执行。

 static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。例如:

public class Test {     private static int a;     private int b;          static {                 Test.a = 3;                 System.out.println(a);                 Test t = new Test();                 t.f();                 t.b = 1000;                 System.out.println(t.b);         }          static {                 Test.a = 4;                 System.out.println(a);         }          public static void main(String[] args) {                  // TODO 自动生成方法存根         }          static {                 Test.a = 5;                 System.out.println(a);         }          public void f() {                 System.out.println( "hhahhahah");         } }

运行结果:
3
hhahhahah
1000
4
5

  利用静态代码块可以对一些static变量进行赋值,最后再看一眼这个例子,都一个static的main方法,这样JVM在运行main方法的时候可以直接调用而不用创建实例。

静态内部类

静态内部类可以创建静态的成员,而非静态的内部类不可以,静态内部类只可以访问外部类中的静态成员变量与成员方法,而非静态的内部类即可以访问所有的外部类成员方法与成员变量。

public class MainInStaticClass {    static class Main{        static void main(){//将主方法写到静态内部类中,从而不必为每个源文件都这种一个类似的主方法        new MainInStaticClass().print();        }    }    public static void main(String[] args){        new MainInStaticClass().print();    }    public void print(){        System.out.println("main in static inner class");    }}public class TestMain {    public static void main(String[] args) {// TODOAuto-generated method stub//new MainInStaticClass().print();    MainInStaticClass.Main.main();    new MainInStaticClass.Main();    }}

静态内部类的使用上有三点需要特别注意:

  • 一是静态成员(包括静态变量与静态成员)的定义。一般情况下,如果一个内部类不是被定义成静态内部类,那么在定义成员变量或者成员方法的时候,是不能够被定义成静态成员变量与静态成员方法的。也就是说,在非静态内部类中不可以声明静态成员。如现在在一个student类中定义了一个内部类age,如果没有将这个类利用static关键字修饰,即没有定义为静态类,那么在这个内部类中如果要利用static关键字来修饰某个成员方法或者成员变量是不允许的。在编译的时候就通不过。故程序开发人员需要注意,只有将某个内部类修饰为静态类,然后才能够在这个类中定义静态的成员变量与成员方法。这是静态内部类都有的一个特性。也正是因为这个原因,有时候少了这个静态的内部类,很多工作就无法完成。或者说要绕一个大圈才能够实现某个用户的需求。这也是静态的内部类之所以要存在的一个重要原因。(非静态内部类也可以定义静态成员但需要同时有final关键词修饰,静态方法鉴于无法用final修饰,仍必须是在静态内部类或者非内部类中定义。)

  • 二是在成员的引用上,有比较大的限制。一般的非静态内部类,可以随意的访问外部类中的成员变量与成员方法。即使这些成员方法被修饰为private(私有的成员变量或者方法),其非静态内部类都可以随意的访问。则是非静态内部类的特权。因为在其他类中是无法访问被定义为私有的成员变量或则方法。但是如果一个内部类被定义为静态的,那么在银用外部类的成员方法或则成员变量的时候,就会有诸多的限制。如不能够从静态内部类的对象中访问外部类的非静态成员(包括成员变量与成员方法)。这是什么意思呢?如果在外部类中定义了两个变量,一个是非静态的变量,一个是静态的变量。那么在静态内部类中,无论在成员方法内部还是在其他地方,都只能够引用外部类中的静态的变量,而不能够访问非静态的变量。在静态内部类中,可以定义静态的方法(也只有在静态的内部类中可以定义静态的方法),在静态方法中引用外部类的成员。但是无论在内部类的什么地方引用,有一个共同点,即都只能够引用外部类中的静态成员方法或者成员变量。对于那些非静态的成员变量与成员方法,在静态内部类中是无法访问的。这就是静态内部类的最大使用限制。在普通的非静态内部类中是没有这个限制的。也正是这个原因,决定了静态内部类只应用在一些特定的场合。其应用范围远远没有像非静态的内部类那样广泛。

  • 三是在创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上。

    通常情况下,在一个类中创建成员内部类的时候,有一个强制性的规定,即内部类的实例一定要绑定在外部类的实例中。也就是说,在创建内部类之前要先在外部类中要利用new关键字来创建这个内部类的对象。如此的话如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。也就是说,普通非静态内部类的对象是依附在外部类对象之中的。但是,如果成员开发人员创建的时静态内部类,那么这就又另当别论了。通常情况下,程序员在定义静态内部类的时候,是不需要定义绑定在外部类的实例上的。也就是说,要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。即在创建静态类内部对象时,不需要其外部类的对象。

原创粉丝点击