美文网首页
Static的使用场景

Static的使用场景

作者: lbcBoy | 来源:发表于2020-05-14 13:48 被阅读0次

在java中static可以用来修饰:
内部类、变量、代码块、方法

1.修饰内部类

1、用static修饰的内部类,称为静态内部类,完全属于**外部类**本身,不属于外部类某一个对象
2、static关键字的作用是把修饰的成员变成**类相关**,而不是实例相关
3、静态内部类可以包含静态成员,也可以包含非静态成员,但是在非静态内部类中不可以声明静态成员。
4、静态类内部不可以访问外部类的实例成员,只能访问外部类的类成员,
   即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员
5、外部类不可以定义为静态类,Java中静态类只有一种,那就是静态内部类,顶级类不能用static 修饰
6、外部类如何调用静态内部类中的属性和方法
    1)外部类可以通过**创建静态内部类实例**的方法来调用静态内部类的非静态属性和方法               
    2)外部类可以直接通过“ 外部类.内部类.属性(方法)” 的方式直接调用静态内部类中的静态属性和方法
7、如何创建静态内部类实例
     1)在非外部类中:外部类名.内部类名 name = new 外部类名.内部类名();
     2)在外部类中:内部类名 name = new 内部类名();

代码例子参考:[https://www.cnblogs.com/bichen-01/p/11198753.html](https://www.cnblogs.com/bichen-01/p/11198753.html)

2.修饰变量

static 可用于修饰成员变量,被static修饰的 成员变量 称 静态变量,也称类变量。

功能:类变量在内存中只存一份,作为该类所有对象的共享变量。
在程序运行时,系统只为类变量分配一次内存,只进行一次的初始化,在加载类的过程中完成类变量的内存分配。

用法:类变量可直接通过类名称进行访问,也可通过类的实例化对象直接方法(安全性考虑,不建议这么做)。

未使用static修饰时:未使用static修饰的 成员变量,又叫做实例变量,实例变量在创建类的对象时,才会分配一次内存,
                   实例变量在内存中有多个拷贝,分别属于不同对象,他们之间互不影响。

3.修饰方法

static 可用于修饰方法,被static修饰的方法称静态方法,也称类方法。

功能和用法:通过静态修饰的方法,可直接由类名进行调用,无需实例化对象,
           可以方便外界在不创建对象的情况下直接调用方法,执行功能,多应用于工具类。

工具类的编写步骤:
  a. 构造方法私有
  b. 所有成员方法添加 static 关键字

4.修饰代码块

static 修饰的代码块,也称静态代码块,

功能和用法:静态代码块无论创建多少个对象,都是优于构造方法和构造代码块之前执行,并且只执行一次。
           在类加载的时候执行,类中的成员第一次使用的时候开始类加载。
特点:类的加载而执行,只执行一次,并优先于主函数。具体说,静态代码块是由类调用的。
    类调用时,先执行静态代码块,然后才执行主函数的,总的来说,静态代码块是和类一起的,优先级最高,
    类加载的同时,静态代码块同时也执行,但只执行一次,所以作用一般是用来加载一些配置代码,或者加载某些文件配置。

与静态代码块对应的,有 构造代码块、 局部代码块 、 同步代码块。

*构造代码块* 的作用同样是给对象进行初始化。对象一建立就运行构造代码块了,而且优先于构造函数执行。
这里要强调一下,有对象建立,才会运行构造代码块,类不能调用构造代码块的,而且构造代码块与构造函数的执行顺序是前者先于后者执行。

*构造函数* 的作用是用于给对象进行初始化,对象一建立,就会调用与之相应的构造函数,也就是说,不建立对象,构造函数时不会运行的。

构造代码块与构造函数的区别是:
  构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化,
  因为构造函数是可以多个的,运行哪个构造函数就会建立什么样的对象,但无论建立哪个对象,都会先执行相同的构造代码块。
  也就是说,*构造代码块中定义的是不同对象共性的初始化内容*。

局部代码块:
  在局部位置,用于限定变量的生命周期。

同步代码块:
    后面再说

5.代码的加载顺序

父类静态变量
父类静态代码块
子类静态变量
子类静态代码块

父类普通变量
父类普通代码块(构造代码块)
父类构造函数
子类普通变量
子类普通代码块(构造代码块)
子类构造函数

面试题:

//父类
public class B {
    public static B t1 = new B();
    public static B t2 = new B();
    public B(){
        super();
        System.out.println("B类构造块");
    }
    static {
        System.out.println("B类静态块");
    }
}
//子类
public class A extends B {
    public static A t1 = new A();
    public static A t2 = new A();
    public A(){
        super();
        System.out.println("A类构造块");
    }
    static {
        System.out.println("A类静态块");
    }
    public static void main(String[] args) {
        A t = new A();
    }
}

运行结果:
B类构造块 //①
B类构造块 //②
B类静态块 //③
B类构造块 //④
A类构造块 //⑤
B类构造块 //⑥
A类构造块 //⑦
A类静态块 //⑧
B类构造块 //⑨
A类构造块 //⑩

 分析:
1.上文中提到了加载顺序
2.A extends B,
    先加载B,B中实例化t1、t2,立即执行构造块,故①、②,然后继续执行静态代码块,故③,此时B类已经加载完毕,
    然后加载A,A中实例化t1、t2,先实例化B,故④、⑤,⑥、⑦,然后继续执行A中静态代码块,故⑧,然后执行主方法,故⑨、⑩。
3.  编辑器收集的顺序是由语句在源文件中的顺序所决定的,所以t1,t2会最先被初始化,会调用到构造函数。

相关文章

网友评论

      本文标题:Static的使用场景

      本文链接:https://www.haomeiwen.com/subject/rrronhtx.html