Java---类加载机制,构造方法,静态变量,父类,变量加载顺序

直接上代码:

代码1:

public class ConstroctTest {
    private static ConstroctTest test = new ConstroctTest();
    //静态变量sta1    未赋予初始值
    public static int sta1;
    //静态变量sta1    赋予初始值20
    public static int sta2 = 20;
    //构造方法中对于静态变量赋值
    private ConstroctTest() {
        sta1 ++ ;
        sta2 ++ ;
    }
    public static void main(String[] args) {
        System.out.println(ConstroctTest.sta1);
        System.out.println(ConstroctTest.sta2);
    }
}

结果:

1
20

代码2:

public class ConstroctTest {
    //静态变量sta1    未赋予初始值
    public static int sta1;
    //静态变量sta1    赋予初始值20
    public static int sta2 = 20;
    private static ConstroctTest test = new ConstroctTest();
    //构造方法中对于静态变量赋值
    private ConstroctTest() {
        sta1 ++ ;
        sta2 ++ ;
    }
    public static void main(String[] args) {
        System.out.println(ConstroctTest.sta1);
        System.out.println(ConstroctTest.sta2);
    }
}

结果:

1
21

结果分析:

1. 按照静态变量的顺序,初始化各静态变量。(给变量赋予默认值)

2. 按照顺序,赋予静态变量的初始值。

3. 以上结果在于:类静态变量的位置,决定着通过构造方法给sta1 与 sta2 赋予的值是否有效。

4. 在代码一中,先对于sta2 执行了 sta2 ++ 操作。而后给sta2 赋予静态变量值。(只因为顺序问题)

代码3:

public 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 ++ ;
    }
    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);
    }
}

结果:

结果分析:

1. 从结果可以看出,Java的静态变量,只是在类第一次加载,初始化的时候执行。

2. 类变量不依赖类的实例,类变量只在初始化时候在栈内存中被分配一次空间,无论类的实例被创建几次,都不再为类变量分配空间。

3. 可以看出 ,类变量的执行与初始化,与实例对象没有关系。

代码4:

public class Test{
    public static void main(String[] args){
        Child ch = new Child();
    }
}
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");
    }
}

结果:

结果分析:

1. 明先初始化父类的静态属性在执行自己的静态属性,再是父类的构造方法再是自己的构造方法。

2. 实例化 Child 类。第一要初始化类Child ,因为Child拥有父类(会判断父类是否初始化),类的初始化只有一次。。初始化类(就是按照顺序加载静态变量与静态方法)。

3. 初始化Child后。开始实例化Child ,因为拥有父类,所以调用构造方法之前会调用父类的默认构造方法。

代码5:

public class Animal {
	private static int k;
	static{
		System.out.println("父类的静态方法");
	}
	{
		System.out.println("执行父类的构造代码块");
	}
	public Animal(){
		System.out.println("执行父类的构造方法");
	}
	public static void main(String[] args) {
		System.out.println(Animal.k);
	}
}

  运行结果:

父类的静态方法
0

结果分析:
1. 构造代码块与构造方法对于类的加载 没有关系。

代码6:

public class Animal {
    private static int k;
    {
        System.out.println("执行父类的构造代码块");
    }
    static{
        System.out.println("父类的静态方法");
    }
    public Animal(){
        System.out.println("执行父类的构造方法");
    }
    public static void main(String[] args) {
        Animal animal1 = new Animal();
        Animal animal2 = new Animal();
    }
}

结果:

结果分析:

1. 构造代码块至于构造方法相关,随着构造方法的执行而执行。

代码7:

public class Cat {
    private static int a;
    private static int b = 1000;
    static{
        a = 100;
        b = 200;
    }

    public static void main(String[] args) {
        System.out.println(Cat.a);
        System.out.println(Cat.b);
    }
}

结果分析:

1. 可以把静代码块中的内容 看做是赋予操作。

2.  当静态代码块在a,b前面。此时输出的结果是100 1000

代码8:

class Animal {
    {
        System.out.println("执行父类的构造代码块");
    }
    static{
        System.out.println("父类的静态方法");
    }
    public Animal(){
        System.out.println("执行父类的构造方法");
    }
    public void A(){
        System.out.println("执行父类的A方法");
    }
}
public class Cat extends Animal{
    static{
        System.out.println("子类的静态方法");
    }
    {
        System.out.println("执行子类的构造代码块");
    }
    public Cat(){
        System.out.println("执行子类的构造方法");
    }
    @Override
    public void A() {
        System.out.println("执行子类的A方法");
    }
    public static void main(String[] args) {
        Cat c = new Cat();
        c.A();
    }
}

通过上面的分析,结果应该很明确了:

总结:

1在new B一个实例时首先要进行类的装载。

2,在装载类时,先装载父类A,再装载子类B
3,装载父类A后,完成静态动作(包括静态代码和变量,它们的级别是相同的,安装代码中出现的顺序初始化)
4,装载子类B后,完成静态动作
类装载完成,开始进行实例化
1,在实例化子类B时,先要实例化父类A
2,实例化父类A时,先成员实例化(非静态代码)
3,父类A的构造方法
4,子类B的成员实例化(非静态代码)
5,子类B的构造方法

先初始化父类的静态代码--->初始化子类的静态代码-->初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函

时间: 2024-08-01 23:40:10

Java---类加载机制,构造方法,静态变量,父类,变量加载顺序的相关文章

Java基础6:代码块与代码加载顺序

Java基础6:代码块与代码加载顺序 代码块:用{}包围的代码 java中的代码块按其位置划分为四种: 局部代码块 位置:局部位置(方法内部) 作用:限定变量的生命周期,尽早释放,节约内存 调用:调用其所在的方法时执行 public class 局部代码块 {@Testpublic void test (){   B b = new B();   b.go();}}class B {   B(){}   public void go() {       //方法中的局部代码块,一般进行一次性地调

java web.xml listener servlet 和filter的加载顺序

在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是,加载顺序与它们在 web.xml 文件中的先后顺序无关.即不会因为 filter 写在 listener 的前面而会先加载 filter. 最终得出的结论是:listener -> filter -> servlet 同时还存在着这样一种配置节:context-param,它用于向 Servle

引用变量类型的加载顺序(类名+引用名=new +类名();)

程序如下: 运行结果如下: 以上结果说明:同一个引用名称(可以把它当做变量的一种类型)可能指代不同的对象,依据同一个引用是否处于同一个初始化的层次,决定是否在完成: static Cup c1=new Cup(11); 之后,立即对相同的引用进行重载. static { c1=new Cup(1); c2=new Cup(2); }

(转)面试题--JAVA中静态块、静态变量加载顺序详解

1 public class Test { //1.第一步,准备加载类 2 3 public static void main(String[] args) { 4 new Test(); //4.第四步,new一个类,但在new之前要处理匿名代码块 5 } 6 7 static int num = 4; //2.第二步,静态变量和静态代码块的加载顺序由编写先后决定 8 9 { 10 num += 3; 11 System.out.println("b"); //5.第五步,按照顺序加

两道面试题,带你透彻解析Java类加载机制

在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Grandpa { static { System.out.println("爷爷在静态代码块"); } } class Father extends Grandpa { static { System.out.println("爸爸在静态代码块"); } public static int factor = 25; public Father() { System.ou

用两道面试题带你详细了解 Java 类加载机制

在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Grandpa{static{System.out.println("爷爷在静态代码块");}} class Father extends Grandpa{static{System.out.println("爸爸在静态代码块");}public static int factor = 25;public Father(){System.out.println("

透彻解析Java类加载机制

目录 Java类加载机制的七个阶段 加载.验证.准备(重要).解析.初始化(重要).使用.卸载 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Grandpa { static { System.out.println("爷爷在静态代码块"); } } class Father extends Grandpa { static { System.out.println("爸爸在静态代码块"); } public sta

Java 类的实例变量初始化的过程 静态块、非静态块、构造函数的加载顺序

Java 类的实例变量初始化的过程 静态块.非静态块.构造函数的加载顺序 先看一道Java面试题: 1 public class Baset { 2 private String baseName = "base"; 3 // 构造方法 4 public Baset() { 5 callName(); 6 } 7 // 成员方法 8 public void callName() { 9 // TODO Auto-generated method stub 10 System.out.p

深入理解和探究Java类加载机制-

深入理解和探究Java类加载机制---- 1.java.lang.ClassLoader类介绍 java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个Java 类,即 java.lang.Class类的一个实例. ClassLoader提供了一系列的方法,比较重要的方法如: 2.JVM中类加载器的树状层次结构 Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写

Java类加载机制与反射 jvm学习

同一个JVM的有线程.所有变量都处于同一个进程里,他们都使用JVM进程的内存区.当系统出现以下几种情况时JVM进程将被终止: 1.程序运行到最后正常结束 2.程序运行到使用System.exit()或Runtime.getRuntime().exit)代码处结束程序. 3.程序执行过程中遇到未捕获的异常或错误而结束. 4.程序所在平台强制结束了JVM进程 注意两次运行java程序,处于两个不同的JVM他们不共享内存. 类的加载 1.当程序主动使用某个类时,如果该类还未加载到内存中,则系统会通过加