Java基础知识上(转载)
Posted ParamousGIS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础知识上(转载)相关的知识,希望对你有一定的参考价值。
http://blog.csdn.net/silentbalanceyh/article/details/4608272
(最终还是决定重新写一份Java基础相关的内容,原来因为在写这一个章节的时候没有考虑到会坚持往后边写,这次应该是更新该内容。而且很讨厌写基础的东西,内容比较琐碎,而且整理起来总会很多,有可能会打散成两个章节,但是我不保证,有可能一个章节就写完了,所以有时候希望基础的很多内容还是读者自己去看看,我基本保证把基础的内容全部都写出来,见谅。这一个章节写了过后我会把前边那个关于基础类型的章节从目录里面删除掉,以保证教材的完整性和唯一性,防止有人收藏过链接,我会继续保留在BLOG地址上边不删除,所以请读者见谅!初学者可以从本章的第三小节开始看,因为前两个章节内容也是比较概念性的,刚开始可以不去理解。这里直接从Java语法开始,不提及Java的历史以及Java的前序发展,如果有什么笔误,就发我Email:silentbalanceyh@126.com)
本章目录
1.概念以及提纲
2.语言基础
3.数据类型[一部分]
4.操作符
5.控制流程
6.关键字清单
1.概念以及提纲
Java技术是一种高级的面向对象的编程语言,也是一个平台,Java技术是基于Java虚拟机(Java Virtual Machine,JVM)的概念——这是语言和底层软件和硬件之间的一种转换器,Java语言的所有实现都是基于JVM的,从而使Java程序可以在有JVM的任何系统上运行。
i.JVM详细介绍:
1)JVM执行原理
JVM可以称为软件模拟的计算机,它可以在任何处理器安全地兼容并且执行.class字节码。其实JVM兼容的二进制字节码和操作系统的本地机器码有一定的区别,只是针对JVM上层的调用程序而言,执行过程效果一样,所以我们一般理解就是说直接用JVM来执行二进制码,实际上二者本质有一定的差异,但是这一点可以理解JVM具有跨平台性。一般情况下,编程人员都是直接编写.java的源文件,然后用Java编译器(javac命令)对源文件进行编译,生成.class文件,生成的.class文件就是我们平时所说的包含了“机器码”的文件,实际上JVM在编译和运行过程做了两件事,先是直接将源文件编译成二进制字节码.class文件,然后进行第二次处理:解释器负责将这些二进制字节码根据本地操作系统宿主环境生成相应的本地机器码解释执行。所以可以理解的一点是为什么Java语言具有跨平台性,因为JVM提供了Java运行的一个中间层,使得操作系统和上层应用相互之间是依靠JVM中间层进行通信的,也就是说Java编写的程序是运行在JVM上的;再者尽管Java确实可以做到“一次编译,多处运行”,但是在不同结构的操作系统平台生成的.class文件真正在执行的时候是存在一定差异的,只是JVM本身会根据安装的不同版本进行不同的操作系统平台下本地机器码的生成及运行,所以虽然我们在Sun公司官方网站可以下载到很多不同操作系统版本的JDK,但是执行效果一样。而且还有一点,这一步操作针对开发人员是透明的,所以真正在开发过程可以放心的是不需要去担心这种问题,只要下载的版本是和符合我们运行的操作系统的,只管进行普通编程的编译、解释运行操作就可以了。
Java语言既是编译型语言,也是解释型语言,在.class文件生成之前,JVM通过javac命令对源代码进行编译操作,然后用JVM根据包含了二进制码的.class生成机器码并且解释执行。所以Java程序的跨平台特性主要是指字节码文件可以在任何具有Java虚拟机的计算机或者电子设备上运行,Java虚拟机中的Java解释器负责将字节码文件解释成为特定的机器码进行运行。Java虚拟机的建立需要针对不同的软硬件平台来实现,既要考虑处理器的型号,也要考虑操作系统的种类。由此在SPARC结构、X86结构、MIPS和PPC等嵌入式处理芯片上,在UNIX、Linux、Windows和部分实时操作系统上都可实现Java虚拟机,这也是为了在运行过程生成本地机器码而考虑的,使得JVM可以兼容不同的软硬件平台。
2)JVM的安全检查机制【参考链接:http://galaxystar.javaeye.com/blog/225615】
JVM在执行字节码的时候需要经过下边的步骤:
- 由类加载器(Class Loader)负责把类文件加载到Java虚拟机中(.class),在这个过程需要校验该类文件是否符合类文件规范
- 字节码校验器(Bytecode Verifier)检查该类文件的代码中是否存在着某些非法操作
- 如果字节码校验器校验通过,就由Java解释器负责把该类文件解释成机器码进行执行
JVM在上边操作过程使用了“沙箱”模型,即把Java程序的代码和数据都限制起来放在一定的内存空间执行,不允许程序访问该内存空间以外的内存。这种访问过程不仅仅是本地的,也可以是远程的,最明显的体验是使用RMI的时候。
——[$]Java的“沙箱”详解——
[1]步骤一:“双亲委派类加载模型”:
双亲委派方式,指的是优先从顶层启动类加载器,自定向下的方式加载类模型,这种方式在“沙箱”安全模型里面做了第一道安全保障;而且这样的方式使得底层的类加载器加载的类和顶层的类加载器的类不能相互调用,哪怕两种类加载器加载的是同一个包里面的类,只要加载的时候不属于同一个类加载器,就是相互隔绝的,这样的操作称为JVM的“安全隔离”。
[2]步骤二:字节码校验:
字节码校验过程需要经过四个步骤:
- 检查class文件的内部结构是否正确,主要是检查该文件是否以某个内存地址打头一般为0xCAFEBABE,但是可能32bit和64bit存在一定的差异,通过这样的检查可以使得被损坏的class文件或者伪装的class文件不能够被加载,可以标记为不安全的。第一趟扫描的主要目的是保证这个字节序列正确的定义了一个类型,它必须遵从java class文件的固定格式,这样它才能被编译成在方法区中的(基于实现的)内部数据结构。
- 检查是否符合JVM语言特性里面的编译规则,因为Java里面所有的Class都是从Object类继承过来的,一旦发现这种不安全的类存在,就直接抛异常。这次检查,class文件检验器不需要查看字节码,也不需要查看和装载任何其他类型。在这趟扫描中,检验器查看每个组成部分,确认它们是否是其所属类型的实例,它们结构是否正确。比如,方法描述符(它的返回类型,以及参数的类型和个数)在class文件中被存储为一个字符串,这个字符串必须符合特定的上下文无关文法。另外,还会检查这个类本身是否符合特定的条件,它们是由java编程语言规定的。比如,除Object外,所有类都必须要有一个超类,final的类不能被子类化,final方法也没有被覆盖,检查常量池中的条目是合法的,而且常量池的所有索引必须指向正确类型的常量池条目。
- 检查字节码是否导致JVM崩溃掉,这里存在一个JVM中断的问题,编程过程无法捕捉Error,同样的没有办法判断程序是否因为执行的class字节码中断或者崩溃。字节码流代表了java的方法,它是由被称为操作码的单字节指令组成的序列,每一个操作码后都跟着一个或多个操作数。执行字节码时,依次执行操作码,这就在java虚拟机内构成了执行的线程,每一个线程被授予自己的java栈,这个栈是由不同的栈帧构成的,每一个方法调用将获得一个自己的栈帧——栈帧其实就是一个内存片段,其中存储着局部变量和计算的中间结果,用于存储中间结果的部分被称为操作数栈。字节码检验器要进行大量的检查,以确保采用任何路径在字节码流中都得到一个确定的操作码,确保操作数栈总是包含正确的数值以及正确的类型。它必须保证局部变量在赋予合适的值以前不能被访问,而且类的字段中必须总是被赋予正确类型的值,类的方法被调用时总是传递正确数值和类型的参数。字节码检验器还必须保证每个操作码都是合法的,即都有合法的操作数,以及对每一个操作码,合适类型的数值位于局部变量中或是在操作数栈中。这些仅仅是字节码检验器所做的大量检验工作中的一小部分,在整个检验过程通过后,它就能保证这个字节码流可以被java虚拟机安全的执行。
- 检查符号引用验证,一个类文件,它会包含它引用的其他类的全名和描述符,并跟他们建立符号引用(一种虚拟的,非物理连接的方式)。当程序第一次执行到需要符号引用的位置时,JVM会检查这个符号链接的正确性,然后建立真正的物理引用(直接引用)。java虚拟机将追踪那些引用——从被验证的class文件到被引用的class文件,以确保这个引用是正确的。这次扫描可能要装载新的类。考虑到虚拟机实现上的差别,第四趟扫描可能紧随第三趟扫描发生,也有可能在第三趟扫描之后很久,当字节码被执行时才执行。动态连接是一个将符号引用解析为直接引用的过程。当java虚拟机执行字节码时,如果它遇到一个操作码,这个操作码第一次使用一个指向另一个类的符号引用,那么虚拟机就必须解析这个符号引用。在解析时,虚拟机执行两个基本任务:
——查找被引用的类(如果必要的话就装载它)
——将符号引用替换为直接引用,例如指向一个类、字段或方法的指针或偏移量
虚拟机必须记住这个直接引用,这样当它以后再次遇到同样的引用时,就可以直接使用,而不需要重新解析该符号引用了。
[3]步骤三:内置于JVM的安全特性:
在执行期,除了符号引用验证,JVM还会对一些内建的安全特性进行检查
- 类型安全的引用转化
- 结构化的内存访问(非指针算法)
- GC
- 数组边界检查
- 空引用检查(NullPointer)
强制内存的结构话访问,避免了恶意用户在了解内存分布的情况下通过指针对JVM的内部结构进行破外。当然要了解JVM的内存分布也不是易事。JVM对运行时数据空间的分配是一个黑盒过程,完全由JVM自己决定如何分配,在class中没有任何相关的信息。
字节码检查的局限就是对于那些不经过字节码检查的方法(如本地方法:native method)无法验证其安全性,所以这里采用的是对动态链接库的访问控制,对于那些足有足够可信度的代码才被允许访问本地方法。具体的实现是,由安全管理器来决定代码是否有调用动态链接库的权限,因为调用本地方法必须调用动态链接库。这样一来,不可信的代码将无法通过调用本地方法来绕过字节码检查。
[4]步骤四:安全管理器SecurityManager:
这一步是编程中最接近程序的一个环节,SecurityManager存在于JavaAPI里面,是可以通过编程来完成安全策略管理的,默认情况下,Java应用是不设置SecurityManager实例的,但是这个实例却需要我们在启动的时候通过System.setSecurityManager来进行设置。一般情况下,调用了SecurityManager.checkPermission(Permission perm)来完成的,外部程序可以创建一个权限实例Permission来进行Check操作。主要应用为:
- 默认安全管理器:java.lang.SecurityManager
- 代码签名和认证
- 策略:java.security.Policy
- 权限:java.security.Permission
- 策略文件
- 保护域:CodeSource,PersimissionCollection,ProtectionDomain
- 访问控制器:java.security.AccessController
【这一步内容比较多,这里不详细讲解,带过】
[5]步骤五:Java签名/证书机制:
Java签名机制使得使用者可以安全调用外部提供的jar文件,签名必须是基于jar包的,也就是如果要使用安全模型必须要将提供的class文件打包成jar,然后使用JDK工具(jarsigner)对jar进行签名。新安全平台中对足够信任度的代码放宽了限制,要获得充分信任须通过代码签名来实现,若我们对某一签名团体足够信任,比如SUN,那么具有该团体签名的代码将被给予充分信任。一个基本的思路大致为,代码发布者创建私钥/公钥对,然后利用私钥对发布代码进行签名,代码使用方在获得代码发布者提供的公钥后对代码进行验证,确认代码确为该提供者提供以及在发布后未经非法修改。这其中存在一些潜在的危险,既是公钥是否是该代码发布者提供的,恶意用户可能替换掉合法的公钥,这会导致用户将给与恶意用户发布的代码以充分信任,目前的常见做法是通过一些权威的证书机构来发布证书而不是公钥,代码发布者被证书发布机构认证合格后,可以将自己的公钥交付证书发布机构,证书发布机构再通过私钥加密该公钥,从而生成证书序列。这样替换公钥的可能性就变得微乎其微。不过世上无绝对安全之事,通过证书机构发布的证书也不是绝对安全的途径。
证书是在签名基础上,对签名值,再进一步做一次加密。而这次加密使用的私钥和公钥都是证书机构提供的。这种方式,是为了防止,有些恶意用户,在公钥发到你手上前,就对其做了手脚,然后再发一个动过手脚的jar给你,用动过手脚的公钥解动过手脚的jar包,是可以解开的。而使用证书后,它会对已经加密的签名值,再做一层加密,这样,到你手里,你只需要通过证书机构的公钥进行解密,然后再用jar包发布者的公钥解密就行了。(只能在一定程度上,提供一些安全性)
3)JVM的内部结构:
JVM是Java平台的核心,为了让编译产生的字节码能够更好的解释和执行,JVM主要分为6个部分【这里只是带过,想要了解JVM整体执行原理的读者可以去参考《Inside JVM》】:
- JVM解释器:即这个虚拟机处理字段码的CPU。
- JVM指令系统:该系统与计算机很相似,一条指令由操作码和操作数两部分组成。操作码为8位二进制数,主要是为了说明一条指令的功能,操作数可以根据需要而定,JVM有多达256种不同的操作指令。
- 寄存器:JVM有自己的虚拟寄存器,这样就可以快速地与JVM的解释器进行数据交换。为了功能的需要,JVM设置了4个常用的32位寄存器:pc(程序计数器)、optop(操作数栈顶指针)、frame(当前执行环境指针)和vars(指向当前执行环境中第一个局部变量的指针)。
- JVM栈:指令执行时数据和信息存储的场所和控制中心,它提供给JVM解释器运算所需要的信息。
- 存储区:JVM存储区用于存储编译过后的字节码等信息。
- 碎片回收区:JVM碎片回收是指将使用过的Java类的具体实例从内存进行回收,这就使得开发人员免去了自己编程控制内存的麻烦和危险。随着JVM的不断升级,其碎片回收的技术和算法也更加合理。JVM 1.4.1版后产生了一种叫分代收集技术,简单来说就是利用对象在程序中生存的时间划分成代,以此为标准进行碎片回收。
ii.Java平台介绍:
Java平台(Java Platform)是一种纯软件平台,它可以在各种基于硬件的平台运行,它有三个版本(JavaSE,JavaME,JavaEE),它由Java应用程序接口(Java Application Programming Interface,API)和JVM组成,Java API是一个现成的软件组件集合,可以简化Applet和应用程序的开发部署,包括健壮、安全且可互操作的企业应用程序。它涵盖了从基本对象到连网和安全性,再到XML生成和Web服务的所有东西,Java API组织成相关类和接口的库,库也可以成为包。
每个包实现包括:
- 用来编译、运行、监视、调试应用程序以及简历应用程序文档的开发工具
- 用来部署应用程序的标准机制
- 用来创建复杂的图形用户界面(GUI)的用户界面工具包
- 用来启用数据库访问和操作远程对象的集成库
1)Java平台的版本:
Java平台有三个版本,使得软件开发人员、服务提供商和设备生产商可以针对特定的市场进行开发:
[1]Java SE(Java Platform,Standard Edition):Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类,并为 Java Platform,Enterprise Edition(Java EE)提供基础。大多数 Java 开发人员使用 Java SE 5,也称为 Java 5.0 或 “Tiger”(2006 年 6 月,Java SE 6 或 “Mustang” 发布了 beta 版。)
[2]Java EE(Java Platform,Enterprise Edition):这个版本以前称为 J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端 Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web 2.0 应用程序。
[3]Java ME(Java Platform,Micro Edition):这个版本以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对可以动态下载的连网和离线应用程序的丰富支持。基于 Java ME 规范的应用程序只需编写一次,就可以用于许多设备,而且可以利用每个设备的本机功能。
2)Java组件技术提纲:【写此提纲的目的是防止学习过程术语混乱,这里提供的分类不标准,但是覆盖了Java里面大部分我们开发过程会碰到的规范和术语】
- Java SE中的规范:
JavaBeans Component Architecture【JavaBeans】:一个为Java平台定义可重用软件组件的框架,可以在图形化构建工具中对这些组件进行设计
Java Foundation Classes(Swing)【JFC】:一套Java的类库,支持为基于Java的客户端应用程序构建GUI和图形化功能
JavaHelp:一个独立于平台的可扩展帮助系统,开发人员和做着可以使用它将在线帮助集成到Applet、组件、应用程序、操作系统和设备中,还可以提供Web的在线文档
Java Native Interface【JNI】:使JVM中运行的Java代码可以与用其他编程语言编写的应用程序和库进行互操作,很多时候实现部分用C来写,有兴趣的读者可以写一个简单的Java版任务管理器,嘿嘿,写这个可以收获很多哦!
Java Platform Debugger Architecture【JPDA】:用于Java SE的调试支持的基础结构
Java 2D API【Java 2D】:是一套用于高级2D图形和图像的类、一套提供了精确控制颜色空间定义和转换的类以及一套面向显示图像的操作符
Java Web Start:允许用户通过一次点击下载并启动特性完整的网络应用程序,而不需要安装,从而简化了Java的部署工作
Certification Path API:提供了一套用于创建、构建和检验认证路径(也称为 “认证链”)的 API,可以安全地建立公共密钥到主体的映射。
Java Advanced Imaging【JAI】:提供一套面向对象的接口,这些接口支持一个简单的高级编程模型,使开发人员能够轻松地操作图像。
Java Cryptography Extension【JCE】:提供用于加密、密钥生成和协商以及 Message Authentication Code(MAC)算法的框架和实现,它提供对对称、不对称、块和流密码的加密支持,它还支持安全流和密封的对象。
Java Data Objects【JDO】:是一种基于标准接口的持久化 Java 模型抽象,使程序员能够将 Java 领域模型实例直接存储进持久化存储(数据库)中,这可以替代直接文件 I/O、串行化、JDBC 以及 EJB Bean Managed Persistence(BMP)或 Container Managed Persistence(CMP)实体 bean 等方法。
Java Management Extensions【JMX】提供了用于构建分布式、基于 Web、模块化且动态的应用程序的工具,这些应用程序可以用来管理和监视设备、应用程序和服务驱动的网络。
Java Media Framework【JMF】:可以将音频、视频和其他基于时间的媒体添加到 Java 应用程序和 applet 中。
Java Secure Socket Extensions【JSSE】:支持安全的互联网通信,实现了 SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)的 Java 版本,包含数据加密、服务器身份验证、消息完整性和可选的客户机身份验证等功能。
Java Speech API【JSAPI】:包含 Grammar Format【JSGF】和 Markup Language【JSML】规范,使 Java 应用程序能够将语音技术集成到用户界面中。JSAPI 定义一个跨平台的 API,支持命令和控制识别器、听写系统和语音识别器。
Java 3D API【Java 3D】:它提供一套面向对象的接口,这些接口支持一个简单的高级编程模型,开发人员可以使用这个 API 轻松地将可伸缩的独立于平台的 3D 图形集成到 Java 应用程序中。
Metadata Facility【JMI】:允许给类、接口、字段和方法标上特定的属性,从而使开发工具、部署工具和运行时库能够以特殊方式处理它们,Java元数据接口(使用Annotation实现)
Java Content Repository API:用于访问 Java SE 中独立于实现的内容存储库的 API。内容存储库是一个高级信息管理系统,它是传统数据存储库的超集。
Concurrency Utilities:一套中级实用程序,提供了并发程序中常用的功能。
Juxtapose【JXTA】:一个用来解决P2P计算的开放的网络计算平台。JXTA P2P平台使开发者在其上建立PtoP的应用。 - Java EE中的规范:
Java Database Connectivity【JDBC】:使用户能够从 Java 代码中访问大多数表格式数据源,提供了对许多 SQL 数据库的跨 DBMS 连接能力,并可以访问其他表格式数据源,比如电子表格或平面文件。
Java Naming and Directory Interface【JNDI】:为 Java 应用程序提供一个连接到企业中的多个命名和目录服务的统一接口,可以无缝地连接结构不同的企业命名和目录服务。
Enterprise JavaBeans【EJB】: J2EE技术之所以赢得某体广泛重视的原因之一就是EJB。它们提供了一个框架来开发和实施分布式商务逻辑,由此很显著地简化了具有可伸缩性和高度复杂的企业级应用的开发。EJB规范定义了EJB组件在何时如何与它们的容器进行交互作用。容器负责提供公用的服务,例如目录服务、事务管理、安全性、资源缓冲池以及容错性。但这里值得注意的是,EJB并不是实现J2EE的唯一途径。正是由于J2EE的开放性,使得有的厂商能够以一种和EJB平行的方式来达到同样的目的。
Remote Method Invoke【RMI】: 正如其名字所表示的那样,RMI协议调用远程对象上方法。它使用了序列化方式在客户端和服务器端传递数据。RMI是一种被EJB使用的更底层的协议。
Java IDL/CORBA:在Java IDL的支持下,开发人员可以将Java和CORBA集成在一起。 他们可以创建Java对象并使之可在CORBA ORB中展开, 或者他们还可以创建Java类并作为和其它ORB一起展开的CORBA对象的客户。后一种方法提供了另外一种途径,通过它Java可以被用于将你的新的应用和旧的系统相集成。
Portlet Specification:定义了一套用于 Java 门户计算的 API,可以解决聚合、个人化、表示和安全性方面的问题。
JavaMail:提供了一套对邮件系统进行建模的抽象类。
Java Message Service【JMS】:为所有与 JMS 技术兼容的消息传递系统定义一套通用的消息概念和编程策略,从而支持开发可移植的基于消息的 Java 应用程序。
JavaServer Faces【JSF】:提供一个编程模型,帮助开发人员将可重用 UI 组件组合在页面中,将这些组件连接到应用程序数据源,将客户机生成的事件连接到服务器端事件处理程序,从而轻松地组建 Web 应用程序。
JavaServer Pages【JSP】:允许 Web 开发人员快速地开发和轻松地维护动态的独立于平台的 Web 页面,并将用户界面和内容生成隔离开,这样设计人员就能够修改页面布局而不必修改动态内容。这种技术使用类似 XML 的标记来封装为页面生成内容的逻辑。
Java Servlets:提供一种基于组件的独立于平台的方法,可以构建基于 Web 的应用程序,同时避免 CGI 程序的性能限制,从而扩展并增强 Web 服务器的功能。
J2EE Connector Architecture【JCA】:为将 J2EE 平台连接到各种结构的 Enterprise Information Systems(EIS)定义了一个标准的体系结构,它定义了一套可伸缩的安全的事务性机制,使 EIS 厂商能够提供标准的资源适配器,可以将这些资源适配器插入应用服务器中。
J2EE Management Specification【JMX】:为 J2EE 平台定义了一个信息管理模型。根据其设计,J2EE Management Model 可与多种管理系统和协议进行互操作;包含模型到 Common Information Model(CIM)的标准映射,CIM 是一个 SNMP Management Information Base(MIB);还可以通过一个驻留在服务器上的 EJB 组件 —— J2EE Management EJB Component【MEJB】 —— 映射到 Java 对象模型。
Java Transaction API【JTA】:是一个独立于实现和协议的高级 API,它使应用程序和应用服务器可以访问事务。
Java Transaction Service【JTS】:JTS是CORBA OTS事务监控的基本的实现。JTS规定了事务管理器的实现方式。该事务管理器是在高层支持Java Transaction API (JTA)规范,并且在较底层实现OMG OTS specification的Java映像。JTS事务管理器为应用服务器、资源管理器、独立的应用以及通信资源管理器提供了事务服务……
Java Authentication and Authorization Service【JAAS】:实现了标准的 Pluggable Authentication Module(PAM)框架的 Java 版本并支持基于用户的授权,使服务能够对用户进行身份验证和访问控制。
JavaBeans Activation Framework【JAF】:JavaMail利用JAF来处理MIME编码的邮件附件。MIME的字节流可以被转换成Java对象,或者转换自Java对象。大多数应用都可以不需要直接使用JAF。
Java API for XML Web Service【JAX-WS】:一组XML web services的JAVA API。JAX-WS允许开发者可以选择RPC-oriented或者message-oriented 来实现自己的web services。
Java API for XML Processing【JAXP】:允许 Java 应用程序独立于特定的 XML 处理实现对 XML 文档进行解析和转换,允许灵活地在 XML 处理程序之间进行切换,而不需要修改应用程序代码。
Java API for XML Binding【JAXB】:允许在 XML 文档和 Java 对象之间进行自动的映射。
SOAP with Attachments API for Java【SAAJ】:使开发人员能够按照 SOAP 1.1 规范和 SOAP with Attachments note 生成和消费消息。
Streaming API for XML【StAX】:就提供了两种方法来处理 XML:文档对象模型(DOM)方法是用标准的对象模型表示 XML 文档;Simple API for XML (SAX) 方法使用应用程序提供的事件处理程序来处理 XML。JSR-173 提出了一种面向流的新方法:Streaming API for XML (StAX)。其最终版本于 2004 年 3 月发布,并成为了 JAXP 1.4(将包含在即将发布的 Java 6 中)的一部分。
Java API for XML Registries【JAXR】:提供了一种统一和标准的Java API,用于访问不同类型的基于XML的元数据注册中心。JAXR目前实现支持ebXML Registry2.0版和UDDI2.0版。未来可以支持更多的类似的注册中心。JAXR为客户端提供了API,与XML注册中心进行交互,同时为服务中心提供者提供了服务提供者接口(SPI),这样,注册中心的实现是可插拔的。JAXR API将应用代码与下层的注册中心机制相隔离。当编写基于JAXR的客户端浏览和操作注册中心时,当注册中心更换时,比如从UDDI更换为ebXML,代码不需要进行修改。
Java Persistence API【JPA】:通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中,一个标准的ORM框架。
Java Authorization Service Provider Contract for Containers【JACC】:在J2EE应用服务器和特定的授权认证服务器之间定义了一个连接的协约,以便将各种授权认证服务器插入到J2EE产品中去。
Java API for RESTful Web Services【JAX-RS】:定义一个统一的规范,使得 Java 程序员可以使用一套固定的接口来开发 REST 应用,避免了依赖于第三方框架。同时,JAX-RS 使用 POJO 编程模型和基于标注的配置,并集成了 JAXB,从而可以有效缩短 REST 应用的开发周期。 - Java ME中的规范:
Connected Limited Device Configuration【CLDC】:是组成资源有限的移动信息设备的 Java 运行时环境的两种配置之一。CLDC 描述最基本的库和虚拟机特性,所有包含 K 虚拟机(K virtual machine,KVM)的 J2ME 环境实现中都必须提供这些库和特性。
Mobile Information Device Profile【MIDP】:是组成资源有限的移动信息设备的 Java 运行时环境的两种配置之一。MIDP 提供核心应用程序功能,包括用户界面、网络连接、本地数据存储和应用程序生命周期管理。
Connected Device Configuration【CDC】:是一个基于标准的框架,用来构建和交付可以跨许多连接网络的消费类设备和嵌入式设备共享的应用程序。
Mobile 3D Graphics API for J2ME【M3G】:是一种轻量的交互式 3D 图形 API,它作为可选的包与 J2ME 和 MIDP 结合使用。
【*:上边这份清单基本上涵盖了Java平台所有的术语以及相关介绍,因为WebBeans是Java EE 6的新规范,而且JBI和SCA具体是为ESB开发存在的,这三个规范我没有归纳进来,有兴趣的读者可以自己去查阅一下,还有一点需要说明JXTA以前不属于Java规范里面的,也是因为该组件用起来比较方便貌似现在纳入JSR规范了,具体情况如何我没有查证,见谅,若有遗漏掉的规范提纲,也请有心的读者来Email告知,谢谢:silentbalanceyh@126.com。这套教程我在书写的时候我只会写一部分与我自己开发相关的使用过的组件技术,其他我不熟悉的可能不会涉及到。而且需要提醒一下读者的是:SSH(Struts+Spring+Hibernate)框架虽然很流行,但是不属于Sun公司Java EE里面的官方标准规范,这三个框架是三个开源框架,所以:JavaEE的规范定义里面并不包含SSH!】
2.语言基础【*:本教材不会讲JDK的环境配置,环境配置以后一必要我在BLOG的配置分类里面单独讲解】
i.开发第一个Java程序:
步骤一:书写.java源代码
步骤二:使用javac命令编译.java源代码,将该代码编译成.class字节码
步骤三:使用java命令运行.class字节码
接着按照步骤,书写第一个Java程序:
/**
*我的第一个Java程序
**/
class Hello{
}
public class HelloJava {
public static void main(String[] args) {
System.out.println("Hello Java");
}
}
将上边的代码保存成HelloJava.java文件名,放于D盘根目录。【*:这里的放置位置根据读者爱好自己决定】
第二步:使用命令行工具:
javac HelloJava.java
第三步:运行.class文件
java HelloJava
输出应该为:
Hello Java
针对这样一个过程有几点需要说明:
[1]关于Java源文件:Java的源文件是以.java结尾的,每一个源文件里面可以定义很多class,但是只能定义一个public的class,如果不定义public的class,文件名必须和其中至少一个class的名称一致;若定义了一个public的class,文件名必须和定义的public的class的类名一致。【*:这点是Java的语言规范,但是从语言设计上来讲这是没有必要的,实际上编译器不应该把文件名和类名关联,但是Java语言是一个特殊,学过Scala和C#的读者应该就明白这一点,所以这一点在Java使用的时候需要特别小心。】
[2]关于函数入口:一个Java程序可能由一个或者多个class构成,上边使用了javac过后,同一个目录下可以生成两个.class文件,分别是Hello.class和HelloJava.class,不论怎样必须在运行的类里面(使用java命令的时候后边跟的类名的类)定义一个Java应用程序的入口:public static void main(String args[]),在这里,该定义成为Java语言的主函数入口,也是程序运行的起点,上边的程序的入口就在HelloJava类里面。main()方法的签名是不可以更改的,因此下边的函数入口的写法都是不对的:
static void main(String args[])
public void main(String args[])
public static void main(String args)
使用上边三种入口函数的定义都会使得JVM没有办法找到主函数入口,后两种定义会抛出下边的异常,第一种情况比较特殊,JVM会提示:Main method not public,也就是说第一种情况JVM能够找到主函数,但是该主函数不符合Java应用程序的运行规范。
Exception in thread "Main Thread" java.lang.NoSuchMethodError: main
[3]在上边的程序里面,HelloJava的类可以不是public的时候,这里需要说明的是,不是说因为某个类是public主函数入口就必须放在该类里面,读者可以试试下边的代码段:
class HelloTester{
public static void main(String[] args){
System.out.println("Hello World");
}
}
public class MainTester {
}
当我们使用javac MainTester.java的时候,编译是可以通过的,而且会生成两个类文件:HelloTester.class和MainTester.class。注意这里的代码结构,按照第一点提到的,这个.java文件只能保存为MainTester.java,如果这段代码保存为HelloTester.java文件,编译的时候会抛出下边的异常:
HelloTester.java:8:class MainTester is public,should be declared in a file named MainTester.java
也就是说一旦在一个.java源文件里面定义了一个类为public,那么这个源文件的名称就被限制了必须和public的类保持一致。上边的代码经过编译过后使用下边的命令读者可以测试以下:
java HelloTester【这种做法会输出:Hello World,因为在这个类里面找到了主函数的入口】
java MainTester【这种做法不会成功,因为在执行类MainTester里面,JVM找不到主函数的入口】
[4]main函数的参数:
对于java里面的主函数入口方法main,JVM有一定的限制,首先是不可以有返回值,因此返回值为void,而且必须有一个参数,类型为String[]的,这也是Java语言里面的规范,这个参数会匹配命令行里面的参数,至于参数名是里面唯一可以更改的,所以上边的定义可以为:
public static void main(String[] myInputValue)
一般情况下,约定使用args的名称,而这里的args代表了命令行的输入参数,这一点可以提供一个带命令行参数的例子:
public class MainTester {
public static void main(String args[])
{
System.out.println(args[0]);
System.out.println(args[1]);
}
}
把上边的代码保存为MainTester.java,然后使用javac命令编译,这一步之前所有的的内容都不用担心,和前边一样,但是运行的时候可能需要下边这种格式:
java MainTester hello1 hello2
上边这段代码会输出为:
hello1
hello2
也就是说,该参数读取的是在java ClassName之后的参数,按照空白为分隔符,然后输入的内容就为参数的值,这些值构成了一个String[]的参数列表,上边代码里面args.length的值为2,第一个参数为hello1,第二个参数为hello2,这就是主函数参数列表里面的参数的使用
小节一下上边几点:
- 使用javac命令的时候:如果.java里面没有public的class,直接针对class的定义进行编译操作,这种情况下,.java源文件的文件名只要和里面的任何一个类的类名一致就可以了;如果.java里面定义了一个类是public的,这种情况下,.java源文件的名称只能和这个类的类名保持一致,否则编译不会通过。
- 使用java命令的时候:在使用java命令的时候,后边敲入命令不需要填写文件全名【不需要java ClassName.class格式】,只是需要填写类名就可以了,这种情况下,JVM会在ClassName对应的类定义里面去寻找主函数入口,如果找不到就会抛出异常,找到过后就可以执行,也可以这样讲,包含主函数的类不一定在一个public的类里面可以是非public的。
- Java应用程序在执行的时候,必须有一个主函数的入口【*:这里不包括Applet的运行,因为Applet里面有特殊的入口以及特殊的运行机制】,而且该主函数的入口必须定义为:public static void main(String args[])
- 这里还有一点需要说明:main函数是可以抛异常的,JVM在检查方法签名的时候,不会检查main后边带的异常定义,比如下边这种方式也是定义函数入口的正确方式,也就是说带异常抛出的时候仅仅检测方法签名就可以了:
public static void main(String args[]) throws Exception - 注意主函数传入参数的使用,args参数实际上就是在使用java命令的时候传入的参数的值的使用,这些使用可以通过写几个简单的程序来实现,在参数使用的过程里面,一般情况下在编写程序的时候针对参数进行一定的检测,上边使用参数的代码实际上是会抛异常的,因为会存在数组越界的问题,为了保证数据不会越界,一般可以通过代码if( args.length > 0 )来对传入的参数进行判断,而且把使用参数的代码放在try-catch块里面进行数组越界异常的捕捉。
ii.Java的注释:
在Java里面主要有三种注释:行注释、段落注释、文档注释
1)行注释:行注释也成为单行注释,行注释使用 “//注释文字”的格式来对某一行的代码进行注释或者加以说明
public class LineComment
{
//这是单行注释的范例
public static void main(String args[])
{
//这只是一个单行注释的例子
System.out.println("Single Line Comment");
}
}
上边代码里面//后边的文字就是行注释的一个例子
2)段注释:段注释也成为多行注释,通常是当说明文字比较长的时候的注释方法
public class MultiCommont
{
/*
*这是段注释的一个简单的例子
*这里是函数入口main方法
*/
public static void main(String args[])
{
System.out.println("Multi Lines Comments");
}
}
3)文档注释:文档注释是Java里面的一个比较厉害的功能,它可以用于注释类、属性、方法等说明,而且通过JDK工具javadoc直接生成相关文档,文档注释的基本格式为“/**...*/”,不仅仅如此,文档注释本身还存在语法
[1]文档和文档注释的格式化:
生成的文档是html格式的,而这些HTML格式的标识符并不是javadoc加的,而是我们在写注释的时候写上去的。因此在格式化文档的时候需要适当地加入HTML标签,例如:
/**
*This is first line.<br/>
*This is second line.<br/>
*This is third line.<br/>
**/
[2]文档注释的三部分:
根据在文档中显示的效果,文档注释可以分为三个部分,这里举个例子:
/**
*testDoc方法的简单描述
*<p>testDoc方法的详细说明</p>
*@param testInput String 打印输入的字符串
*@return 没有任何返回值
**/
public void testDoc(String testInput)
{
System.out.println(testInput);
}
简述:文档中,对于属性和方法都是现有一个列表,然后才在后面一个一个的详细说明,列表中属性名或者方法名后面那段说明都是简述。
详细说明:该部门对属性或者方法进行了详细说明,在格式上不需要特殊的要求,可以写成前边讲的HTML的格式,如同上边第二行的内容。【*:这里有个技巧就是简述和详细说明尽量不要重复,在简述中出现过的内容不需要在详细说明中进行第二次描述,可以理解为详细说明是简述的一种扩展。后边章节的概念说明代码大部分我都没有写注释,也请各位读者见谅!】
特殊说明:除开上边的两部分,最后一个部分就是特殊说明部分,特殊说明部分使用JavaDoc标记进行,这些都是JavaDoc工具能够解析的特殊标记,这一点下边章节将会讲到
[3]使用javadoc标记:
javadoc标记是java插入文档注释中的特殊标记,它们用于识别代码中的特殊引用。javadoc标记由“@”以及其后跟着的标记类型和专用注释引用组成。它的格式包含了三个部分:
@、标记类型、专用注释引用
有时候我们也可以直接理解为两个方面:@和标记类型、专用注释引用;Javadoc工具可以解析Java文档注释中嵌入的特殊标记,这些文档标记可以帮助自动从源代码生成完整的格式化API,标记用“@”符号开头,区分大小写,必须按照正确的大小写字母输入。标记必须从一行的开头开始,否则会被视为普通文本,而且按照规定应将相同名字的标记放一起,比如所有的@see标记应该放到一起,接下来看一看每一种标记的含义。
@author(1.0):语法[@author name-text]
当使用-author选项的时候,用指定的name-text在生成文档的时候添加“Author”项,文档注释可以包含多个@author标记,可以对每个@author指定一个或者多个名字。
@deprecated(1.0):语法[@deprecated deprecated-text]
添加注释,只是不应该再使用该API(尽管是可用的),Javadoc工具会将deprecated-text移动到描述前面,用斜体显示,并且在它前边添加粗体警告:“不鼓励使用”。deprecated-text的首句至少应该告诉用户什么时候开始不鼓励使用该API以及使用什么替代它。Javadoc仅将首句复制到概览部分和索引中,后面的语句还可解释为什么不鼓励使用,应该还包括一个指向替代API的{@link}标记【1.2版本用法】
- 对于Javadoc 1.2,使用{@link}标记,这将在需要的地方创建内嵌链接,如:
/**
*@deprecated 在JDK X.X中,被{@link #methodName(paramList)}取代
**/
【*:在上边的标记里面X.X指代JDK的版本,后边的链接链接的是方法的签名,methodName为方法名,paramList为参数列表】 - 对于Javadoc 1.1,标准格式是为每个@deprecated标记创建@see标记(它不可内嵌)
@exception(1.0):语法[@exception class-name description]
@throws(1.2):语法[@throws class-name description]
以上两个标记是同义词,用class-name和description文本给生成的文档添加“抛出”子标题,其中class-name是该方法可抛出的异常名。
{@link}(1.2):语法[{@link name label}]
出入指向指定name的内嵌链接,该标记中name和label的语法与@see标记完全相同,如下所述,但是产生的内嵌链接而不是在“参见”部分防止链接。该标记用花括号开始并用花括号结束,以使它区别于其他内嵌文本,如果需要在标签内使用“}”,直接使用HTML的实体表示法:}
@param(1.0):语法[@param parameter-name description]
给“参见”部分添加参数,描述可以继续到下一行进行操作,主要是提供了一些参数的格式以及描述
@return(1.0):语法[@return description]
用description本文添加“返回”部分,该文本应描述值的返回类型和容许范围
@see(1.0):语法[@see reference]
该标记是一个相对复杂的标记,添加“参见”标题,其中有指向reference的链接或者文本项,文档注释可包含任意数目的@see标记,它们都分组在相同的标题下,@see有三种格式:
- @see “string” 注:该形式在JDK 1.2中没有用,它不打印引用文本
为string添加文本项,不产生链接,string是通过该URL不可用的书籍或者其他信息引用,Javadoc通过查找第一个字符为双引号(")的情形来区分它前边的情况,比如:
@see "这是Java教材,主要是提供给初学者"
上边的注释将会生成:
参见:
“这是Java教材,主要是提供给初学者” - @see <a href="page.html#section">Java某章节</a>
添加URL#value定义的链接,其中URL#value是相对URL或者绝对URL,JavaDoc工具通过查找第一个字符小写符号(<)区分它与其他情况,比如:
@see <a href="page.html#section">测试规范</a>
上边的注释将会生成:
参见:
测试规范 - @see package.class#member label【比较常用的一种格式】
添加带可见文本label的链接,它指向Java语言中指定名字的文档。其中label是可选的,如果省略,则名字作为可见文本出现,而且嵌在<code>HTML标记中,当想要缩写可见文本或不同于名字的可见文本的时候,可以使用label。
——package.class#member是Java语言中的任何有效名字——包名、类名、接口名、构造函数名、方法名或域名——除了用hash字符(#)取代成员名前面的点之外,如果该名字位于带文档的类中,则Javadoc将自动创建到它的链接,要创建到外部的引用链接,可使用-link选项,使用另外两种@see形式中的任何一种引用不属于引用类的名字的文档。
——label是可选文本,它是链接的可见标签,label可包含空白,如果省略label,则将显示package.class.member,并相对于当前类和包适当缩短
——空格是package.class#member和label之间的分界符,括号内的空格不表示标签的开始,因此在方法各参数之间可使用空格
@see package.class#member的典型形式 |
引用当前类的成员 |
- 简单说明一下:
——第一套形式(没有类和包)将导致 Javadoc 仅搜索当前类层次。它将查找当前类或接口、其父类或超接口、或其包含类或接口的成员。它不会搜索当前包的其余部分或其他包(搜索步骤 4-5)。
——如果任何方法或构造函数输入为不带括号的名字,例如 getValue,且如果没有具有相同名字的域,则 Javadoc 将正确创建到它的链接,但是将显示警告信息,提示添加括号和参数。如果该方法被重载,则 Javadoc 将链接到它搜索到的第一个未指定方法。
——对于所有形式,内部类必须指定为 outer.inner,而不是简单的 inner。
——如上所述,hash 字符(#)而不是点(.)用于分隔类和成员。这使 Javadoc 可正确解析,因为点还用于分隔类、内部类、包和子包。当 hash 字符(#)是第一个字符时,它是绝对不可少的。但是,在其他情况下,Javadoc 通常不严格,并允许在不产生歧义时使用点号,但是它将显示警告。
@see标记的搜索次序——JavaDoc将处理出现在源文件(.java)、包文件(package.html)或概述文件(overview.html)中的@see标记,在后两种文件中,必须完全限定使用@see提供的名字,在源文件中,可指定全限定或部分限定的名字,@see的搜索顺序为:
- 当前类或接口
- 任何包含类和接口,先搜索最近的
- 任何父类和超接口,先搜索最近的
- 当前包
- 任何导入包、类和接口,按导入语句的次序搜索
@since(1.1):语法[@since since-text]
用since-text指定的内容给生成文档添加“Since”标题,该文本没有特殊内部结构,该标记表示该改变或功能自since-text所指定的软件件版本后就存在了,例如:@since JDK 1.4
@serial(1.2):语法[@serial field-description]
用于缺省的可序列化域的文档注释中,可选的field-description增强了文档注释对域的描述能力,该组合描述必须解释该域的意义并列出可接受值,如果有需要描述可以多行,应该对自Serializable类的最初版本之后添加的每个可序列化的域添加@since标记。
@serialField(1.2):语法[@serialField field-name field-type field-description]
简历Serializable类的serialPersistentFields成员的ObjectStreamField组件的文档,应该对每个ObjectStreamField使用一个@serialField标记
@serialData(1.2):语法[@serialData data-description]
data-description建立数据(尤其是writeObject方法所写入的可选数据和Externalizable.writeExternal方法写入的全部数据)序列和类型的文档,@serialData标记可用于writeObject、readObject、writeExternal和readExternal方法的文档注释中
@version(1.0):语法[@version version-text]
当使用-version选项时用version-text指定的内容给生成文档添加“版本”子标题,该文本没有特殊内部结构,文档注释最多只能包含一个@version标记。
{@code}(1.5):语法[{@code text}]
该标签等同于<code>{@literal}</code>,里面可以直接过滤掉HTML的标签,可以不用<和>来显示(<和>),在这个代码块里面的text部分,可以直接书写代码,即使使用了<b>Hello</b>,在HTML里面也不会识别成为加粗的Hello,而还是原来的代码段<b>Hello</b>的格式输出
{@docRoot}(1.3):语法[{@docRoot}]
代表相对路径生成的文件的(目标)的根从任何产生的网页目录,当您要包括如版权页或公司徽标文件的时候它是有用的,你要引用所生成的网页,链接从每个页面底部的版权页面是常见的。(@docRoot将标记可用于在命令行,并在两个文档注释:这个标记是有效的,在所有文档注释:概述、包装类、接口、构造、方法和领域,包括任何标记文本的一部分(如@return,@param和@deprecated的使用)。
比如:
/**
* See the <a href="{@docRoot}/copyright.html">Copyright</a>.
**/
{@inheritDoc}(1.4):语法[{@inheritDoc}]
继承(拷贝)文档从最近的“继承类或可执行的接口”到当前在这个标签的位置的文档注释内容,这使您可以编写更多与继承相关的一般性文档
下边的情况比较适合:
- 在一个方法的主要描述块,在这种情况下,主要描述是整个继承树结构里面的类和接口的一个拷贝。
- 在文本参数返回的@return @param和@throws等方法标记,在这种情况下,文本标记是整个层次结构里面标签的拷贝。
{@linkplain}(1.4):语法[{@linkplain package.class#member label}]
和{@link}类似,除非链接的label是用普通文本的格式显示的,当文本是普通文本的时候该标签就能够起作用,例如:
Refer to {@linkplain add() the overridden method}
这个会显示成:
Refer to the overridden method
{@value}(1.4):语法[{@value package.class#field}]
主要用来显示静态字段的值:
/**
* The value of this constant is {@value}
**/
public static final String SCRIPT_START = "script";
[4]JavaDoc标记的举例:
——[$]一个使用JavaDoc标记的例子——
/**
* @author Lang Yu
* @version 1.2
*/
public class JavaDocBasic {
/**
* @see "Main Function JavaDoc"
* @since JDK 1.4
* @param args The params of console
**/
public static void main(String args[]){
System.out.println("Hello World!");
}
}
例如有这样一小段代码,在我机器上我放在了D:\\Source\\work下,然后进入该目录下,使用下边的命令:
D:\\Source\\work>javadoc -d doc JavaDocBasic.java
通过这样的命令使用,在执行该命令了过后电脑上有下边这样的输出,而且去目录下边可以看到一个doc文件夹,用浏览器打开里面的index.html就可以看到生成的文档的内容:
Loading source file JavaDocBasic.java...
Constructing Javadoc information...
Standard Doclet version 1.6.0_16
Building tree for all the packages and classes...
Generating doc\\JavaDocBasic.html...
Generating doc\\package-frame.html...
Generating doc\\package-summary.html...
Generating doc\\package-tree.html...
Generating doc\\constant-values.html...
Building index for all the packages and classes...
Generating doc\\overview-tree.html...
Generating doc\\index-all.html...
Generating doc\\deprecated-list.html...
Building index for all classes...
Generating doc\\allclasses-frame.html...
Generating doc\\allclasses-noframe.html...
Generating doc\\index.html...
Generating doc\\help-doc.html...
Generating doc\\stylesheet.css...
——[$]一个使用{@link}的例子——
/**
* @author Lang Yu
* @see java.lang.String
*/
public class JavaDocLink {
private int a;
private int b;
/**
* {@link #getAdd() getAdd()} Method
* @return the result of (a + b)
**/
public int getAdd(){
return a + b;
}
}
同样的方式生成对应的文档,就可以看到@link的效果了,讲到这里Java注释相关的内容就介绍了一半了,后边一般是与JavaDoc工具相关的,这个留到命令行工具里面去介绍
以上是关于Java基础知识上(转载)的主要内容,如果未能解决你的问题,请参考以下文章