1、static关键字基本概念
方便在没有创建对象的情况下来进行调用。
即被static关键字修饰的不需要创建对象去调用,直接根据类名就可以去访问。
static关键字修饰类(内部类)
java里面static一般用来修饰成员变量或函数。但有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。
public class StaticClass {
public static class InnerClass{
InnerClass(){
System.out.println("=========静态内部类===========");
}
public void InnerMethod(){
System.out.println("=========静态内部方法===========");
}
}
public static void main(String[] args){
// 直接通过StaticTest类名访问静态内部类InnerClass
InnerClass inner=new StaticClass.InnerClass();
inner.InnerMethod();
}
}
如果没有用static修饰InterClass,则只能new 一个外部类实例。
再通过外部实例创建内部类。
public class StaticClass {
public class InnerClass{
InnerClass(){
System.out.println("=========静态内部类===========");
}
public void InnerMethod(){
System.out.println("=========静态内部方法===========");
}
}
public static void main(String[] args){
// new 一个外部类实例。再通过外部实例创建内部类。
StaticClass classInner=new StaticClass();
StaticClass.InnerClass inner=classInner.new InnerClass();
inner.InnerMethod();
}
}
static关键字修饰方法
修饰方法的时候,其实跟类一样,可以直接通过类名来进行调用:
public class StaticMethod {
public static void test(){
System.out.println("======静态方法======");
}
public static void main(String [] args){
// 方式一:直接通过类名
// StaticMethod.test();
// 方式二:
StaticMethod fdd=new StaticMethod();
fdd.test();
}
}
static关键字修饰变量
被static修饰的成员变量叫做静态变量,也叫做类变量,说明这个变量是属于这个类的,而不是属于是对象,没有被static修饰的成员变量叫做实例变量,说明这个变量是属于某个具体的对象的。
static关键字修饰代码块
父类静态变量--父类静态代码块--子类静态变量--子类静态代码块--父类普通变量--父类普通代码块--父类构造函数--子类普通变量--子类普通代码块--子类构造函数
public class Father {
static{
System.out.println("Father static");
}
public Father(){
System.out.println("Father Constructor");
}
}
public class Son extends Father{
static{
System.out.println("Son static");
}
public Son(){
System.out.println("Son Constructor");
}
public static void main(String [] args){
new Son();
}
}
// 输出:
Father static
Son static
Father Constructor
Son Constructor
静态对象的执行级别是一样的,因此会从最靠上的静态对象开始执行,而且每个静态方法只会在类生命的时候初始化一次。
类的初始化
静态代码块或者静态变量是对象加载的时候进行,且只加载一次。而成员变量或者普通代码块 每次实例的时候都会执行一次,而且都优先于构造方法。
public class ParentClass {
// 父类静态成员
static int num = 0;// 1
String name = "qqqqqq";//4
static String name2 = "wwwwwwwwwww";//2
{
System.out.println("name1:" + name);//5
System.out.println("这里是块1============");
}
ParentClass(){
System.out.println("这里是构造函数*************");//6
}
static {
num += 1;
System.out.println("name2:" + name2);
System.out.println("这里是静态初始化块*************" + num);
}
static ParentClass parentClass = new ParentClass();//每次实例化一个对象,都需要进行类的初始化
}
public class TestClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
ParentClass pa = new ParentClass();
}
}
输出:
name2:wwwwwwwwwww
这里是静态初始化块*************1
name1:qqqqqq
这里是块1============
这里是构造函数*************
name1:qqqqqq
这里是块1============
这里是构造函数*************
2.基于上例,理解下类的初始化
1)类的加载:
JVM: Java Virtual Machine(Java虚拟机)
引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
代表jvm将java文件编译成class文件后,以二进制流的方式存放到运行时数据的方法区中,并在java的堆中创建一个java.lang.Class对象,用来指向存放在方法堆中的数据结构。
2) 类的初始化:
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。其中验证、准备、解析3个部分统称为连接。类加载的过程包括了加载、验证、准备、解析、初始化五个阶段。
3) 类加载有三种方式:
1、命令行启动应用时候由JVM初始化加载
2、通过Class.forName()方法动态加载
3、通过ClassLoader.loadClass()方法动态加载