【Java】static关键字

前言

static关键字算是Java中比较复杂的关键字之一,它能够修饰变量、方法、类以及代码块。下面将介绍static的具体使用。而且扩展介绍关于程序入口函数public static void main(String[] args)的一些知识。html

引入static的目的

在《Java编程思想》中对static的描述有这样的一句话:java

static方法就是没有this的方法。在static的方法内部不能调用非静态方法,反过来到是能够的。并且能够在没有建立任何对象的前提下,仅仅经过类自己来调用static方法。编程

这最后一句即是引入static主要的用途,免去建立类对象的开销就能够调用类中的方法,能够说是十分诱人。函数

static的做用

Static修饰变量

private static int num;

变量num能够称为静态变量也能够称为类变量。 static修饰属性只能修饰类属性,不能够修饰局部变量,如方法中的定义的属性。Java中规定如此。 Java中的static和C++中的static含义是不同的,C++中的static修饰的变量是全局变量,而Java中没有全局变量的概念,在Java中使用static修饰的类属性是存放在方法区的,为该类<b>全部对象共享的变量,与具体某个对象没有关系</b>。this

<b>static属性和非static属性的区别</b>主要有两点:①在内存区域的保存位置不一样,static属性存放在方法区,非static属性存放在堆栈区。②static属性是属于类对象的公共属性,能够在没有实例化对象的前提下使用类名.静态属性名的方式访问;而非static属性则须要使用对象进行访问。<br>spa

<b>关于何时该使用static属性?</b><br> 须要进行描述共享信息的属性而且该属性不须要重复开辟内存空间并且便于修改,则使用static进行修饰该变量。其他状况,不建议使用static修饰变量。命令行

static修饰方法

public static void printNumberOfStudent(){
  ...
}

被static修饰的方法叫作静态方法。静态方法同静态变量同样能够直接使用类名称.静态方法名调用。如果<u>使用类名调用静态方法须要知足该方法不是private</u>。在非静态方法中是可使用this访问静态变量。<br>code

在使用静态方法时须要注意两点:<br>htm

  • <u>静态方法中是不存在this的。</u>由于this是指向当前对象的,静态方法是与类相关的,与对象无关,不存在对象调用问题。通常直接使用类名.静态方法名 进行访问对象

  • <u>静态方法内部只能直接调用静态方法和静态成员。</u>调用普通方法会报错,在普通方法中能够调用静态方法。 由于普通方法通常会将对象做为隐藏实参传入并用this指向,在没有建立对象时,普通方法中就不存在this,调用包含普通方法的静态方法就会报错!

static修饰代码块

在程序编写中能够直接使用{...}定义一段语句块,这个语句块就是代码块,使用static修饰的语句块就叫作静态代码块。<br> 观察下面程序的结果,分析静态块在程序中的执行顺序

public class A {
    A(){
        System.out.println("A constructor");
    }
    static {
        System.out.println("A's static block");
    }
}
public class B extends A{
    B(){
        System.out.println("B constructor");
    }
    static {
        System.out.println("B's static block");
    }
}

public class StaticBlock {
    public static void main(String[] args) {
        B objb = new B();
    }
}

/*output
A's static block
B's static block
A constructor
B constructor
*/

能够看出<b>静态代码块的执行顺序优先于构造函数</b>,在程序执行时,会先找到main入口,而后准备加载类B,发现B有父类A,因而先去加载A,静态代码块就是在类加载的时候执行的。在静态块执行完后,就会去执行构造函数。<br>

静态块由于在构造函数以前执行,因此<b>经常使用来初始化静态变量</b>。

public  class Student {
    private static int numOfStu;
    private String name;
    private int age;

    static {
        numOfStu = 0;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        numOfStu++;
    }
}

<b>静态代码块能够在类的任意位置定义</b>(方法中不能够),不会影响其优先于构造函数执行的顺序。可是多个静态块的执行顺序会依据其声明的先后执行。<br>

public  class Student {
    private static int numOfStu;
    private String name;
    private int age;

    static {
        numOfStu = 0;
        System.out.println("first sttaic block");
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        numOfStu++;
    }

    static {
        System.out.println("second sttaic block");
    }

    public static void main(String[] args) {
        Student stu1 = new Student("sakura",20);
    }
}
/*
output:
first sttaic block
second sttaic block
*/

static修饰内部类

内部类顾名思义就是定义在一个类中的类。使用static定义的属性或者方法是不受类实例化对象的控制的,因此,若是内部类被static修饰,是不会受到外部类实例化对象控制。此时,<b>内部类就相等于变成了一个外部类,而且只能访问外部类中的static属性或者方法</b>。关于内部类,后面会详细介绍。

public static void main(String[] args)

class Test{
  ...
  public static void main(String[] args){
  ...
  }
}

public static void main(String[] args)做为Java程序的入口方法,Java虚拟机在运行程序时,会首先查找main()方法。该方法中各个修饰符的做用以下:

  • 【public】: public 做为权限修饰符,代表任何类或者对象均可以访问这个方法。主方法是程序的开始,因此这个方法对任何操做都应该是可见。
  • 【static】: static代表main()方法是一个静态方法,即方法中的代码是存储在静态存储区的,当类被加载后,就能够直接使用类名来调用(在命令行使用java Test是调用Test.main主方法)。如此看被static修饰的主函数,这样的好处可能就是:不用建立当前类的对象就能够调用,节省空间。
  • 【void】: 主方法是一切执行的开始点,既然是起点,那么就没有回到其余方法中的返回值
  • 【String[] args】: 传递给程序的参数。输入的参数以空格隔开,如果输入的参数本省有空格,则使用双引号将该参数括起来。字符串参数args为开发人员在命令行状态下与程序交互提供了一种手段。

扩展一: main()方法是否还有其余可用的定义格式?

  1. 因为public和static没有前后顺序关系,因此下面的定义也是合理的

    static public void main(String[] args)
  2. 也能够将main()方法定义为final的

    public static  final void main(String[] args)
  3. 也可使用synchronized关键字来修饰

    static public synchronized void main(String[] args)

可是无论使用哪一种方式定义,都须要保证main()方法的返回值为void,而且有static和public关键字修饰。由于main()方法做为程序的入口,所以不能使用abstract关键字来修饰

扩展二: 同一个.java文件中是否能够有多个main()方法?

虽然每一个类中均可以定义main()方法,可是只有与文件名相同的用public修饰的类中的main()方法才能做为整个程序的入口方法。以下所示:建立一个名为Test.java的文件

class T{
    public static void main(String[] args){
        System.out.println("T main");
    }
}
public class Test{
    // 程序入口函数
    public static void main(String[] args){
        System.out.println("Test main");
    }
}
/*
output:
Test main
*/

小结

介绍了Java中static关键字的基础应用:修饰变量、方法等。Java中还能够利用static关键字实现单例模式,这些后面介绍。

参考:《Java编程思想》第四版

原文出处:https://www.cnblogs.com/myworld7/p/10052245.html

相关文章
相关标签/搜索