- demo1
/**
* java规定,变量没有初始化不能使用,全局变量也就是类的属性,java会在编译的时候,自动将他们初始化,
* 所以可以不进行变量初始化的操作,☆☆☆☆☆但是(局部)变量必须初始化☆☆☆☆☆
*
* 静态数据的初始化
* 初始化的顺序是:先静态对象,而后是“非静态”对象。
*
* 非静态成员初始化
* 在一个类中,非静态成员的初始化,发生在任何方法(包括构造方法)被调用之前。并且它们定义的顺序,决定了初始化的顺序
* 变量初始化完成之后才厚调用构造函数
*
* 先加载类:执行静态块,静态变量赋值 因为静态部分是依赖于类,而不是依赖于对象存在的,所以静态部分的加载优先于对象存在
*
*
*/
public class Singleton {
//1.
private static int x = 0;
private static int y;
//2.
private static Singleton instance = new Singleton();
/**
* -----------------------------------------------------------------------------------------
* 构造方法是new对象的时候进行调用(此时变量已经初始化完成)
* 如果注释1在上面 注释2在下面 打印结果为 1 1 准备阶段先对静态变量进行x,y进行赋初始值0,0
* 然后new Singleton对象开始调用构造函数的x++,y++所以x,y的值变为1,1
*
* 注意:不可以在构造函数的参数初始化表中对静态成员变量初始化,但是可以在构造函数中修改静态变量的值
* 如果注释2在上面 注释1在下面 打印结果为 0 1
* 先进行++操作 x,y的值变为1,1 后面对x,y进行初始化操作
*
*/
private Singleton(){
x++;
y++;
}
public static void main(String[] args) {
System.out.println(Singleton.x);
System.out.println(Singleton.y);
}
}
- demo2
class ConstroctTest {
//静态变量sta1 未赋予初始值
public static int sta1;
//静态变量sta1 赋予初始值20
public static int sta2 = 20;
private static ConstroctTest test = new ConstroctTest();
//构造方法中对于静态变量赋值
private ConstroctTest() {
System.out.println("123456");
sta1 ++ ;
sta2 ++ ;
}
/**
* 打印结果
* 123456
* 1
* 21
* 1
* 1
*
* 1. 从结果可以看出,Java的静态变量,只是在类第一次加载,初始化的时候执行。
* 2. 类变量不依赖类的实例,类变量只在初始化时候在栈内存中被分配一次空间,无论类的实例被创建几次,都不再为类变量分配空间。
* 3. 可以看出 ,类变量的执行与初始化,与实例对象没有关系。
* @param args
*/
public static void main(String[] args) {
System.out.println(ConstroctTest.sta1);
System.out.println(ConstroctTest.sta2);
System.out.println(ConstroctTest.sta1);
System.out.println(ConstroctTest.sta1);
}
}
- demo3
class Parent{
static String name1 = "hello";
static{
System.out.println("Parent static block");
}
public Parent(){
System.out.println("Parent construct block");
}
}
class Child extends Parent{
static String name2 = "hello";
static{
System.out.println("Child static block");
}
public Child(){
System.out.println("Child construct block");
}
}
class Test{
/**
* 打印结果
* Parent static block
* Child static block
* Parent construct block
* Child construct block
*
* 结果分析:
* 1. 先初始化父类的静态属性在执行子类的静态属性,再是父类的构造方法再是子类的构造方法。
* 2. 实例化 Child 类。第一要初始化类Child ,因为Child拥有父类(会判断父类是否初始化),
* 类的初始化只有一次。初始化类(就是按照顺序加载静态变量与静态方法)。
* 3. 初始化Child后。开始实例化Child ,因为拥有父类,所以调用构造方法之前会调用父类的默认构造方法。
*
* @param args
*/
public static void main(String[] args){
Child ch = new Child();
}
}
- demo4
class Animal {
private static int k;
static{
System.out.println("父类的静态方法");
}
{
System.out.println("执行父类的构造代码块");
}
public Animal(){
System.out.println("执行父类的构造方法");
}
/**
* 执行结果 不会打印构造代码块和构造方法中的代码
* 父类的静态方法
* 0
*
* @param args
*/
public static void main(String[] args) {
System.out.println(Animal.k);
}
}
- demo5
class Animal1 {
private static int k;
{
System.out.println("执行父类的构造代码块");
}
static{
System.out.println("父类的静态方法");
}
public Animal1(){
System.out.println("执行父类的构造方法");
}
/**
*
* 构造代码块先于构造方法执行 静态代码块只会执行一次
*
* 执行结果:
* 父类的静态方法
* 执行父类的构造代码块
* 执行父类的构造方法
* 执行父类的构造代码块
* 执行父类的构造方法
* @param args
*/
public static void main(String[] args) {
Animal1 animal1 = new Animal1();
Animal1 animal2 = new Animal1();
}
}
- demo6
class Cat {
private static int a;
private static int b = 1000;
static{
a = 100;
b = 200;
}
public Cat cat = new Cat();
public Cat(){
a=100000;
b=200000;
}
/**
*
* 静态代码块中的内容,看做是赋值操作
* 如果public Cat cat = new Cat();不带static 那么输出结果100,200
* 如果public static Cat cat = new Cat(); 那么输出结果100000,200000
*
* 执行结果
* 100000
* 200000
*
* @param args
*/
public static void main(String[] args) {
System.out.println(Cat.a);
System.out.println(Cat.b);
}
}
- demo7
class A {
static {
System.out.println("A的静态块");
}
private static String staticStr = getStaticStr();
private String str = getStr();
{
System.out.println("A的实例块");
}
public A() {
System.out.println("A的构造方法");
}
private static String getStaticStr() {
System.out.println("A的静态属性初始化");
return null;
}
private String getStr() {
System.out.println("A的实例属性初始化");
return null;
}
/**
* A的静态块
* A的静态属性初始化
* B的静态属性初始化
* B的静态块
* A的实例属性初始化
* A的实例块
* A的构造方法
* B的实例块
* B的实例属性初始化
* B的构造方法
* A的实例属性初始化
* A的实例块
* A的构造方法
* B的实例块
* B的实例属性初始化
* B的构造方法
*
*
*由此可见,实例化子类的时候,若此类未被加载过,首先加载是父类的类对象,
* 然后加载子类的类对象,接着实例化父类,最后实例化子类,若此类被加载过,不再加载父类和子类的类对象。
*
* 接下来是加载顺序,当加载类对象时,首先初始化静态属性,然后执行静态块;当实例化对象时,
* 首先执行构造块(直接写在类中的代码块),然后执行构造方法。
* 至于各静态块和静态属性初始化哪个些执行,是按代码的先后顺序。属性、构造块(也就是上面的实例块)、
* 构造方法之间的执行顺序(但构造块一定会在构造方法前执行),也是按代码的先后顺序。
* @param args
*/
public static void main(String[] args) {
new B();
new B();
}
}
class B extends A{
private static String staticStr = getStaticStr();
static {
System.out.println("B的静态块");
}
{
System.out.println("B的实例块");
}
public B() {
System.out.println("B的构造方法");
}
private String str = getStr();
private static String getStaticStr() {
System.out.println("B的静态属性初始化");
return null;
}
private String getStr() {
System.out.println("B的实例属性初始化");
return null;
}
}