Java实践(一)---程序设计基本概念

来源:互联网 发布:淘宝卖家跑路了 编辑:程序博客网 时间:2024/06/07 17:27

JVM(Java Virtual Machine)

1-1、ClassLoader基本概念

Java程序并不是一个可执行文件,而是由许多独立的类文件组成的,每一个文件的对应一个Java类,而且,这些类文件并非全部装入内存,而是根据程序需要逐渐装入

ClassLoader是JVM实现的一部分,它包括bootstrap classloader(启动类加载器)。

ClassLoader在JVM运行是加载Java核心API,以满足Java程序最基本的需求,其中包括用户自定义的ClassLoader。

用户自定义的ClassLoader:是指通过Java程序实现的2个ClassLoader:

  • ExtClassLoader:加载Java的扩展API,即/jre/lib/ext中的类
  • AppClassLoader:加载用户机器上CLASSPATH设置目录中的Class

1-2、ClassLoader加载流程

当运行一个程序时:

  1. JVM启动
  2. 运行bootstrap classloader
  3. 该ClassLoader加载Java核心API和ExtClassLoader、AppClassLoader
  4. ExtClassLoader加载扩展API & AppClassLoader加载CLASSPATH目录下定义的Class

一个类加载的过程使用一种父类委托的模式,这样的的原因如下:

  • 避免重复加载
  • 考虑到安全因素

1-3、一些重要的方法

  1. loadClass:是ClassLoader的入口点
  2. defineClass:接受由原始字节组成的数组,并把它转换成Class对象
  3. findSystemClass:从本地文件系统装入文件
  4. resolveClass:可以不带解析装入类,也可以带解析装入类
  5. findLoadedClass:充当一个缓存,当请求loadclass装入类时,调用该方法查看ClassLoader是否已经装入这个类
  6. findClass: 从本地文件系统使用实现的类装载器装载一个类
  7. getSystemClassLoader:如果覆盖findClass或loadClass,该方法能以实际的ClassLoader对象来访问系统ClassLoader
  8. forName:用来加载class

JVM加载类的时候,需要经过三个步骤:

  • 装载:找到相应的class文件,读入JVM
  • 连接:
  • 初始化:1-验证class是否符合规格;2-为类变量分配内存的同时是设置默认初始值;3-解释(可选)

2-1、 JVM使用的字符

在Java中字符只以一种形式存在,那就是Unicode(不选择任何特定的编码,直接使用它们在字符集中的编号,这是统一的唯一方法)

在Java中指的是,JVM中,内存中,在代码里声明的每一个char、String类型的变量中

例如:
编写如下代码

public class T1 {    public static void main(String[] args) {        char achar = '爱';        System.out.println(achar);        System.out.format("%x",(int)achar);//%d 则输出十进制        System.out.println();        char bchar = 0x7231;//十六进制        System.out.println(bchar);    }}

输出结果

爱7231爱

在内存中的相应区域,这个字符就表示为0x7231,同时用Unicode码也找到了这个字符

只要正确读入一个字符,那么它在内存中的表示形式就是唯一的,使用Unicode码

2-2、字符编码方案

JVM的这种约定使得一个字符分为两部分:

  • JVM内部:统一使用Unicode表示,当这个字符被从JVM内部移到外部(即保存到系统的文件系统中的一个文件的内容时)就进行编码转换,使用具体的编码方案
  • OS的文件系统:所以的编码转换只发生在边界的地方,JVM和OS的交界处(各种输入/输出流即Reader、Writer类起作用的地方)

Java中文件与流参考这里:http://blog.csdn.net/wee_mita/article/details/71157964

所有的I/O基本上可以分为2大阵营:

  • 面向字节的输入输出:如果面向字节,那么这类工作要保证系统中的文件二进制内容和读入JVM内部的二进制内容一致,不能变化任何0和1的顺序【这种输入/输出方式适合读入视频音频文件,或者任何不需要变换的文件内容】
  • 面向字符的输入输出:如果面向字符,那么这类工作要保证系统中的文件的字符和读入JVM的字符要一致

例如:

假设在文件系统中有一个GBK保存的文本文件,其中保存了一个汉字,不论这个汉字的GBK码是什么,当我们使用面向字符的I/O把它读入内存并保存在一个char型变量中时,不关心这个char变量具体的二进制内容是什么,只要这个字符读进来之后仍然是该汉字就行。

从中可以看出,面向字符的I/O(Reader和Writer类)实际上隐式地做了编码转换,在输出时,将内存中Unicode字符使用系统默认的编码方式进行编码,在输入时,将系统已经编码过的字符使用默认编码方案进行还原

Reader和Writer只进行默认的编码转换,即GBK<—>Unicode,如果使用其他编码方案的文件,必须采用编码转换(字符与字节之间的转换,InputStreamReader和OutputStreamWriter)

3-1、关于i++

i++和++i的区别在于,前者是程序完毕后自增,后者是程序开始前自增;

int i= 0 ;i = i++ + ++i;
  1. 执行i++,并不自增,i=0
  2. 执行++i,执行自增,i=1
  3. 此时,程序执行完毕,执行i++的自增,i=2
  4. i = 0+2
int j = 0;j = j++;

Java中用了中间缓存变量的机制,j = j++;转变为如下:

temp =  j;j = j+1;j = temp;

所以j依然为0;

原创粉丝点击