zoukankan      html  css  js  c++  java
  • Java高级之类结构的认识


            本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


    Java体系包括,各种版本的虚拟机,可执行文件,各种第三方类库,Java API类库,Java语言

    发展史:91年James Gosling博士带领开发出Oak,95年互联网兴起来变成Java,并正式改名,并提出“一次编译到处执行”的口号。96年1.0正式发布,代表技术有Java虚拟机,AWT和Applet-以前很喜欢的Swing开发套件;

    97年1.1,代表技术有Jar文件格式、JDBC、JavaBeans、RMI、内部类、反射等

    98年1.2,拆分三个方向,就是J2ME,J2EE,J2SE 99年正式使用HotSpot,代表技术JIT、Collections集合类等

    2000年1.3,代表技术有数学运算、TimeApi、JNDI(正式应用)等,此后2年发布一次

    2002年1.4,走向成熟,正则表达式、XML解析器等出现

    2004年1.5,自动装箱、泛型、注解、枚举、可变长参数、循环等语法

    2006年1.6,提供动态语言支持、编译API和HTTP服务器API,对锁、同步、垃圾回收、类加载做了大量优化

    2009年1.7,由于涉及sun收购,之后的发布节奏也被打乱,提供新的G1收集器、加强对非JAVA语言的调用、升级类加载架构

    2012年1.8,支持接口有默认实现方法、支持Lamda表达式(android studio已支持)、TimerAPI的全新优化。


    Java的类结构是对变量,各种访问标记,接口和继承,同步、枚举,注解,内部类,异常、方法等的组合


    类文件是以8个字节为基础单位的二进制流


    类文件和图片都有魔数,用来标识它可以被虚拟机接受,即0xCafeBabe-全大写,只是为了方便大家记忆;在很多地方都有应用,因为文件后缀名可以改变,而它不能改变。


    Java类文件的前4位代表它是否能被虚拟机接受,之后是版本号,5和6代表次版本号,7和8代表主版本号

    紧接下来的是常量,大概有11种表结构,除了常见的String,Integer,Float,Double,Long以外,还有Class,Utf-8,Field,Method,InterfaceMethod,NameAndType类型,数量不确定


    接着是访问标志有8种,public,final,abstract,interface,super,enum,annotation,synthetic(非用户代码产生的类)


    接着是“继承”索引,this索引和super索引,除Object以外,其他索引值均不为0,代表有父类;索引集合描述这个类实现了哪些接口,从左到右按顺序排列,有几个计数器值为几


    再接下来是字段表集合,描述所有的变量(如作用范围-public,并变性-final,并发可见-volatile等)和返回值(基本数据类型和类),基本数据类型的全限定名,开头都是其英文大写,如'[()V; '和'[[Ljava/lang/String';前者代表一个空返回值,后者代表一个String二维数组,类都以L开头作表示;全限定名可以理解为对象的地址。


    接下来到方法表集合了,跟字段表一样,但某些访问控制答不能修饰方法,如volatile和transient关键字,方法名加尖括号表示,如<init>-指实例构造器,<cinit>-指类构造器,编译后的代码存在一个"Code"的属性里

    属性表,类、方法体、常量表中都有属性表

    1、Code属性指编译后的字节码,还有它的长度,栈的最大深度,最大存储空间,一个方法编译后不允许超过65535个字节码指令,一个指令=1Slot=32位,这是最小的存储单位,而float和int都是32位;一般还可以分为源码和元数据(即对源码的描述,如类,字段,方法等)

    	public static int getFinally() {
    		int a = 1;
    		try {
    			a = 2;
    			return a;
    		} catch (Exception e) {
    			// TODO: handle exception
    			a = 3;
    			return a;
    		} finally {
    			a = 4;
    		}
    	}
    上面是用一段源码,来对字节码指令进行分析,很多人看见后,都很想对照自己的结果,准确答案是2

    跟你的结果是否一致,为什么是2而不是4呢?

    这段代码可以分为三层来分析:

    第一层如果try没有任何问题,则执行a=2 return a

    第二层,如果try出错,则执行finally,再执行catch语句,a=3 return a

    第三层,如果try无错,catch无错,而出现了其他error,则直接执行finally语句的a=4

    这个地方可以这样理想,按照正常的Java指令没有打乱的情况下,先执行try return时已经执行a的write方法,则finally中仅执行了a的assign方法,此时a已经为2。不懂变量加载过程的,可以查看:Java高级之内存模型分析

    2、Exceptions属性 列举出可检查出的异常如catch语句后和throws的异常

    3、LineNumberTable属性 描写源码行号与字节码行号的关系,即这段代码位于哪一行,用于异常抛出时定位

    4、LocalVariableTable属性 定义后别人引用,不会产生参数是arg0,arg1的情况

    5、SourceFile属性,用于记录Class源码文件名称,主要异常抛出时可以定位是哪个文件

    6、ConstantValue属性,通知虚拟机自动定义为静态变量,只能为基本数据类型和String类型

    7、InnerClasses属性 显然定义内部类的,数量位置等

    8、Deprecated及Synthetic 前者是定义废弃类,方法,变量等,后者指非源码产生由编译器自动加的东西。


    Class文件是虚拟机解释的入口,了解其内部结构,有助于对代码进行分析定位错误,以及热加载等其他功能的理解。


    以下是拓展知识


    1位=1bit 最小的计算机单位,指0和1

    byte=8bit 字节 取值范围 -128到127 记忆技巧 2^字节次方

    char =2byte Unicode

    short=2byte -2^15到2^15-1

    int =4byte -2^31到2^31-1

    float=4byte

    long=8byte -2^63到2^63-1

    double=8byte  

    boolean 无意义

    一个汉字是2位,一个英文字母1位

    虚拟机的存存储区域,一般常说的有栈和堆,栈放指针和基本数据类型,而堆放对象,还有一种需要熟悉的是常量存储,就是存代码内部(方法里的);还有两种拓展了解:寄存器位于处理器内部,极少,处理极快;非RAM存储,如持久化对象和流对象,特指数据流传输和硬盘对象。除了常量存储存在只读存储器(ROM-Only)和寄存器,其他都存在随机访问存储器(RAM-Acess)里。

    位操作介绍四种,位与(&),位或(|),位否(~)和异或(^)

    位与,同为1则为1,否则为0

    位或,有一个1则为1,否同为0

    位否,1变0,0变1 计算方式~x=-(x+1)

    异或,不同则为1,相同则为0

    		int a = 0x010101;
    		int b = 0x110100;
    		System.out.println(a & b);
    		System.out.println("位于操作:"+0x010100);
    		System.out.println(a | b);
    		System.out.println("位或操作:"+0x110101);
    		System.out.println(a ^ b);
    		System.out.println("异或操作:"+0x100001);
    结果

    65792
    位于操作:65792
    1114369
    位或操作:1114369
    1048577
    异或操作:1048577
    Tips:负数操作 要先获得补码再操作,然后变源码+1操作

    另外一个例子:

    System.out.println((1 & 0) + "," + (1 & 1) + "," + (0 & 0));//两个为1才为1,否则为0
    System.out.println((1 | 0) + "," + (1 | 1) + "," + (0 | 0));//有一个为1则为1,否则为0
    System.out.println((1 ^ 0) + "," + (1 ^ 1) + "," + (0 ^ 0));//只有一个为1才为1,否则为0

    结果:

    0,1,0
    1,1,0
    1,0,0


    图片的大小=图片width*height*颜色深度

    格式有四种(A-Alpha不透明度 R-Red G-Green B-Blue)

    ALPHA_8格式  8位=1byte

    ARGB_4444格式 16位=4+4+4+4=2byte

    RGB_565格式 16位=5+6+5=2byte

    ARGB_8888格式 32位=8+8+8+8=4byte

    借用格式来压缩图片是一种不错的办法。

    以下是摘抄的图片魔数

    图像文件头
      1)1-2:(这里的数字代表的是"字",即两个字节,下同)图像文件头。0x4d42='BM',表示是Windows支持的BMP格式。(注意:查ascii表B 0x42,M0x4d,bfType 为两个字节,B为low字节,M为high字节所以bfType=0x4D42,而不是0x424D,但注意)
      2)3-6:整个文件大小。4690 0000,为00009046h=36934。
      3)7-8:保留,必须设置为0。
      4)9-10:保留,必须设置为0。
      5)11-14:从文件开始到位图数据之间的偏移量(14+40+4*(2^biBitCount))。4600 0000,为00000046h=70,上面的文件头就是35字=70字节。

    位图信息头

      6)15-18:位图图信息头长度。
      7) 19-22:位图宽度,以像素为单位。8000 0000,为00000080h=128。
      8)23-26:位图高度,以像素为单位。9000 0000,为00000090h=144。
      9)27-28:位图的位面数,该值总是1。0100,为0001h=1。
      10)29-30:每个像素的位数。有1(单色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增强型真彩色)。1000为0010h=16。
      11)31-34:压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)。RLE简单地说是采用像素数+像素值的方式进行压缩。T408采用的是位域存放方式,用两个字节表示一个像素,位域分配为r5b6g5。图中0300 0000为00000003h=3。
      12)35-38:用字节数表示的位图数据的大小,该数必须是4的倍数,数值上等于(≥位图宽度的最小的4的倍数)×位图高度×每个像素位数。0090 0000为00009000h=80×90×2h=36864。
      13)39-42:用象素/米表示的水平分辨率。A00F 0000为0000 0FA0h=4000。
      14)43-46:用象素/米表示的垂直分辨率。A00F 0000为0000 0FA0h=4000。
      15)47-50:位图使用的颜色索引数。设为0的话,则说明使用所有调色板项。
      16)51-54:对图象显示有重要影响的颜色索引的数目。如果是0,表示都重要。 

    Java中的switch语句支持整型和枚举,整型包括byte,short,int,char



  • 相关阅读:
    POJ 2018 二分
    873. Length of Longest Fibonacci Subsequence
    847. Shortest Path Visiting All Nodes
    838. Push Dominoes
    813. Largest Sum of Averages
    801. Minimum Swaps To Make Sequences Increasing
    790. Domino and Tromino Tiling
    764. Largest Plus Sign
    Weekly Contest 128
    746. Min Cost Climbing Stairs
  • 原文地址:https://www.cnblogs.com/fengju/p/6174403.html
Copyright © 2011-2022 走看看