static静态关键字

转载自大佬:https://www.cnblogs.com/xrq730/p/4820992.html

静态资源和静态方法

首先,静态的资源和方法等会随着类的加载而进入内存被初始化,而非静态的资源和方法会随着new的动作被初始化。即,静态先,非静态后。

由于这种特性,我们可以理解static的基本用法:

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

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

被static所修饰的变量是唯一的静态资源,是各个对象实例化后所共享的资源,则静态资源被改变后,所有实例中的该资源都会改变。

下面来理解一个问题:静态方法能不能调用非静态资源?以下面代码为例

public class A
{
    private int i = 1;
    
    public static void main(String[] args)
    {
        i = 1;
    }
}

main方法是静态方法,i是非静态资源。在类加载进入内存时,main方法初始化,方法中的所有资源都要被加载进内存。而由于i是非静态资源,要通过new来初始化,所以i并不能进入内存。

所以我们可以得到以下结论:

  1,静态方法不能调用非静态资源

  2,静态方法可以调用静态资源

  3,非静态方法可以调用静态资源

静态代码块

  静态块的语法如下

static{
    statments;
    ........  
}

静态块是用于初始化一个类的时候同时进行一些操作的。静态块中的代码只在初始化类的时候执行一次。

public class A
{
    private static int a = B();
    
    static
    {
        System.out.println("Enter A.static block");
    }
    
    public static void main(String[] args)
    {
        new A();
    }
    
    public static int B()
    {
        System.out.println("Enter A.B()");
        return 1;
    }
}

打印结果:

Enter A.B()
Enter A.static block

我们看到,在main方法中,首先new了对象A,按顺序加载a=B(),调用方法B,打印Enter A.B(); 然后打印静态块中的内容。

可以得到结论:静态资源的加载顺序是严格按照静态资源的定义顺序来加载的

再看一个例子:

复制代码
 1 public class A
 2 {
 3     static
 4     {
 5         c = 3;
 6         System.out.println(c);
 7     }
 8     
 9     private static int c;
10 }
复制代码

这段代码的第6行是有错误的“Cannot reference a field before it is defined”。从这个例子得出第二个结论:静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问

最后一个小例子:

复制代码
 1 public class A
 2 {
 3     static
 4     {
 5         System.out.println("A.static block");
 6     }
 7     
 8     public A()
 9     {
10         System.out.println("A.constructor()");
11     }
12 }
复制代码
复制代码
 1 public class B extends A
 2 {
 3     static 
 4     {
 5         System.out.println("B.static block");
 6     }
 7     
 8     public B()
 9     {
10         System.out.println("B.constructor()");
11     }
12     
13     public static void main(String[] args)
14     {
15         new B();
16         new B();
17     }
18 }
复制代码

结果是

A.static block
B.static block
A.constructor()
B.constructor()
A.constructor()
B.constructor()

这个例子得出第三个结论:静态代码块是严格按照父类静态代码块->子类静态代码块的顺序加载的,且只加载一次

static修饰类

这个用得相对比前面的用法少多了,static一般情况下来说是不可以修饰类的,如果static要修饰一个类,说明这个类是一个静态内部类(注意static只能修饰一个内部类),也就是匿名内部类。像线程池ThreadPoolExecutor中的四种拒绝机制CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy就是静态内部类。静态内部类相关内容会在写内部类的时候专门讲到。    待补充

import static

这个比较冷门,基本很少看见有地方用,使用JUnit可能会用到,写assert的时候会方便些。import static是JDK1.5之后的新特性,这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名.资源名,可以直接使用资源名。注意一下,import static必须这么写,而不能写成static import。举个例子来看一下:

package chapter3Demos;

import static java.lang.System.out;

import static java.lang.Math.*;

public class Demo3_3_2 {

    public static void main(String[] args)  {
        out.println(sin(2.2));
    }
}

第一个import static表示直接指定导入out这个静态资源,可以省略写System,但是不能使用其他System类中的静态方法。

第二个import static表示导入了Math类中所有的静态方法,不仅sin可以不写Math,其他数学函数也可以省略不写

这种写法减少了代码量,简化了一些操作,但是降低了代码的可读性。

除了在一些特定场合用到之外,建议不要使用。

猜你喜欢

转载自www.cnblogs.com/Joey777210/p/11752144.html