1:类与对象
类是抽象的概念 对象是具体的概念
类的实例就是对象
想要有对象 当然必须要有类
如何获取类?
通过类加载的方式 从字节码文件中获取 类
如何获取对象?
通过创建该类的创建对象方法(我们所说的new方法) 生成一个对象
类应该有什么东西?
1:什么时候加载类?
2:通过什么加载类?
3:加载好的类放在哪里?
4:类里面有什么?
对象应该有什么东西?
1:什么时候创建 类的对象
2:通过什么方式创建 类的对象
3:创建好的 类的对象放在哪里
4:对象里面有什么?
2:Java源代码经过 编译解释成二进制文件 流程
1:Java源代码
2:经过JDK中Javac 编译
3:字节码文件(.class)
4:JVM 类加载器 进行加载字节码文件
5:方法:解释:
1:解释器 逐行解释执行
2:机器可执行的二进制机器码
5:方法:编译:
后续引进:JIT即时编译器(Just In Time Compiler)
处理热点代码(一次编译 多次执行)
2:JIT 运行时进行编译
3:机器可执行的二进制机器码
4:编译完成后机器码保留
5:机器码下次可以直接使用
3:流程图中类加载(包括类初始化) 流程
加载类解读
其中loadClass的类加载过程有如下几步:
加载 >> 验证 >> 准备 >> 解析 >> 初始化
1:加载:在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,
例如调用类的main()方法,new对象等等,在加载阶段会在内存中生成一个代表这个类的java.lang.Class对象,
作为方法区这个类的各种数据的访问入口
2:验证:校验字节码文件的正确性
3:准备:给类的静态变量分配内存,并赋予默认值 (如整型为0 布尔类型为false)(注意final 是常量 直接赋值)
4:解析:将符号引用 (符号 符号 符号) 替换为 直接引用(内存地址)
静态链接过程(类加载期间完成):该阶段会把一些静态方法(符号引用,比如main()方法)
替换为指向数据所存内存的指针或句柄等(直接引用),
动态链接过程(程序运行期间完成):将符号引用替换为直接引用,下节课会讲到动态链接。
5:初始化(加载到方法区):对类的静态变量初始化为指定的值,执行静态代码块被加载到方法区中
主要包含 运行时常量池、类型信息、字段信息、方法信息、类加载器的引用、对应class实例的引用等信息
类加载器的加载(懒加载)(类创建才执行):ClassLoader classLoad =new ClassLoader()
类加载器实例 加载 这个类
classLoad 加载 User.CLass
如何获取方法区里面的类信息:类加载器在加载类信息放到方法区中后,
会有一个对应的Class 类型的对象实例放到堆(Heap)中,
作为开发人员访问方法区中类定义的入口和切入点。
类对象创建时 栈 堆 方法区 的关系:
User user = new User()
1:类加载完后,其类信息存放在方法区中,并在堆中提供方法区入口 UserClass
2:堆中申请 user(真实的对象)的内存空间 ,它指向方法区的User类型信息的引用;
可以认为是根据方法区入口UserClass 生成堆中的user(真实的对象)
3:栈中生成user(地址)(就是变量名user)
4:栈中有user(地址)(就是变量名user)指向堆中的user(真实的对象)
5:这样 栈中user地址 方法区中User类信息 堆中user真实对象 就完成串联在一起了
特别注意:
1:加载 >> 验证 >> 准备 >> 解析 >> 初始化
类加载 类初始化
2:类对象创建 (class实例 的引用)
一个对应的Class 类型的对象实例 是指 user (User user = new User() )
3:加载的时机:
类的懒加载:第一次创建该类的对象时进行类加载,假如该类被加载过,则不需要重新加载。
那么执行顺序就有意思了
1:创建类的对象 >> 类未加载 >> 类加载器进行加载 >> 加载 >> 验证 >> 准备 >> 解析 >> 初始化 >> 类对象创建
2:创建类的对象 >> 类已加载 >> 类对象创建
4:类对象创建(包括对象初始化) 流程
类的实例化也叫对象初始化,这是一个概念。类是对象的抽象,对象是类的具体实例!
1:虚拟机遇到一条new指令时,会先检查相应的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
2:分配给新生的对象分配内存 即是申请内存空间
3:虚拟机需要将分配到的内存空间都初始化为零值
4:设置对象头(先了解)
5:执行<init>方法 ,即对象按照程序员的意愿进行初始化,对应到语言层面上讲,就是为属性赋值
5:问题回答
类应该有什么东西?
1:什么时候加载类?
类使用懒加载的方式 即是创建该类的对象时 才进行加载
2:通过什么加载类?
项目启动后 项目有个类加载器(实际上就是JVM自带的一个类) 来进行加载
3:加载好的类放在哪里?
加载的类信息会放在JVM的方法区
对象应该有什么东西?
1:什么时候创建 类的对象
当你需要使用该对象时创建该对象
2:通过什么方式创建 类的对象
通过new的方式创建对象
3:创建好的 类的对象放在哪里
new一个对象时 会在JVM的堆中申请内存空间 然后该对象当然放在堆中
4:类里面有什么?
4:对象里面有什么?
类是抽象概念 对象时具体概念 相应的类里面有什么 对象里面也就有什么
如果对 加载类 和 创建类的对象 的时机 还是不理解没关系 看下面打印结果
打印结果:
load TestDynamicLoad
静态方法执行了一次
load ClassLoaderA
构造方法执行了两次
initial ClassLoaderA
initial ClassLoaderA
load test
public class TestDynamicClassLoader {
static {
System.out.println("*************load TestDynamicLoad************");
}
public static void main(String[] args) {
//第一次创建对象 (进行类加载)
new ClassLoaderA();
//第二次创建对象 (不进行类加载)
new ClassLoaderA();
System.out.println("*************load test************");
//B不会加载,除非这里执行 new B()
ClassLoaderB b = null;
}
}
public class ClassLoaderA {
static {
System.out.println("*************load ClassLoaderA************");
}
public ClassLoaderA() {
System.out.println("*************initial ClassLoaderA************");
}
}
public class ClassLoaderB {
static {
System.out.println("*************load ClassLoaderB************");
}
public ClassLoaderB() {
System.out.println("*************initial ClassLoaderB************");
}
}
6:User user = new User( ) 做了什么
public class User {
private String name = "章鱼";
private int age = 18;
public User() {
name = "何穗金";
age = 18;
}
}
class UserDemo {
public static void main(String[] args) {
User user = new User();
}
}
注意:
1:堆中 user真实对象 是根据方法区中User的类信息创建的
2:然后才是 栈中user的地址 指向堆中的user真实对象
1:用户创建了一个User对象,运行时JVM首先会去方法区寻找该对象的类型信息,
没有则使用类加载器classloader将Userclass字节码文件加载至内存中的方法区,
并将Student类的类型信息存放至方法区。
2:接着JVM在堆中为新的User实例分配内存空间,
这个实例持有着指向方法区的User类型信息的引用,引用指的是类型信息在方法区中的内存地址。
3:在此运行的JVM进程中,会首先起一个线程跑该用户程序,而创建线程的同时也创建了一个线程栈,
线程栈用来跟踪线程运行中的一系列方法调用的过程,每调用一个方法就会创建并往栈中压入一个栈帧,
栈帧用来存储方法的参数,局部变量和运算过程的临时数据。
上面程序中的user是对User的引用,就存放于栈中,并持有指向堆中User实例的内存地址。
4:JVM根据user引用持有的堆中对象的内存地址,定位到堆中的User实例,
由于堆中实例持有指向方法区的User类型信息的引用,
因此也可以获取到 该类在方法区的其他信息(常量 静态变量 类信息)
对象就是一种变量
1、把User. class文件加载到内存
2、在栈内存给user对象(变量)申请一个空间
3、在堆内存为user对象(变量)申请一个空间
4、给成员变量进行默认初始化。name=null, age =0
5、给成员变量进行显示初始化。name=章鱼,age=18
6、通过构造方法给成员变量进行初始化。name=何穗金,age=18
7、数据初始化完毕,然后把堆内存的地址值赋值给栈内存的 user变量。
网友评论