1,
static修饰类成员变量时,这个类的每个类对象都有这个成员访问的权限,并且每个类对象都可以进行修改和赋值,static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响
static成员变量的初始化顺序按照定义的顺序进行初始化。
2,
static修饰类方法成员时可以直接 类.方法名 调用,对于类自身的静态方法调用时可以省略 类. 的方式直接使用方法名调用,在静态方法中不能访问类的非静态成员变量和非静态成员方法,非静态成员方法中是可以访问静态成员方法/变量
3,
静态不可以直接访问非静态,静态方法不可以使用this关键字
4,静态代码块:
当第一次使用本类创建对象时,静态代码块将执行唯一的一次,并且优先于构造方法之前执行(静态代码块会在类加载到内存时期就执行,类中的静态代码块是按顺序加载的,静态成员或者方法也是按顺序执行,静态属性和静态代码块的执行顺序也是按照在代码中的顺序进行加载的),也就是不管static代码块放置到那个位置都是会被优先执行的,父类中的静态代码块先于子类中的先执行
作用:多用于给类的成员变量进行初始化
类加载的三个阶段
第一个阶段(源代码阶段):
先从java文件按成员变量,构造方法,成员方法通过javac编译成class文件。
第二个阶段(Class类对象阶段):
通过类加载器把class文件中的成员变量,构造方法,成员方法加载到内存中。在进行类加载的阶段时如果发现类有父类将先加载父类后在加载子类
第三个阶段(Runtime运行时阶段):
该阶段就可以创建对象和调用对象里的方法了(将集体对象加载到内存堆中)。执行时调用类的构造器创建对象(new 对象),如果类有父类时会先执行父类中的构造器,在执行子类中的构造方法,在生成对象时会初始化成员变量,父类的成员变量的初始化先于子类、
静态代码块加载时期示例
public class Test {
Person person = new Person("Test");
static{
System.out.println("test static");
}
public Test() {
System.out.println("test constructor");
}
public static void main(String[] args) {
new MyClass();
}
}
class Person{
static{
System.out.println("person static");
}
public Person(String str) {
System.out.println("person "+str);
}
}
class MyClass extends Test {
Person person = new Person("MyClass");
static{
System.out.println("myclass static");
}
public MyClass() {
System.out.println("myclass constructor");
}
}
test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor
解题思路: 类似地,我们还是来想一下这段代码的具体执行过程。首先加载Test类,因此会执行Test类中的static块。接着执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。
部分内容摘抄于这个链接参考链接