标签:网站 功能 允许 tin spec pos contains loading 强制转换
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在执行字节码的时候需要经过下边的步骤:
JVM在上边操作过程使用了“沙箱”模型,即把Java程序的代码和数据都限制起来放在一定的内存空间执行,不允许程序访问该内存空间以外的内存。这种访问过程不仅仅是本地的,也可以是远程的,最明显的体验是使用RMI的时候。
——[$]Java的“沙箱”详解——
[1]步骤一:“双亲委派类加载模型”:
双亲委派方式,指的是优先从顶层启动类加载器,自定向下的方式加载类模型,这种方式在“沙箱”安全模型里面做了第一道安全保障;而且这样的方式使得底层的类加载器加载的类和顶层的类加载器的类不能相互调用,哪怕两种类加载器加载的是同一个包里面的类,只要加载的时候不属于同一个类加载器,就是相互隔绝的,这样的操作称为JVM的“安全隔离”。
[2]步骤二:字节码校验:
字节码校验过程需要经过四个步骤:
——查找被引用的类(如果必要的话就装载它)
——将符号引用替换为直接引用,例如指向一个类、字段或方法的指针或偏移量
虚拟机必须记住这个直接引用,这样当它以后再次遇到同样的引用时,就可以直接使用,而不需要重新解析该符号引用了。
[3]步骤三:内置于JVM的安全特性:
在执行期,除了符号引用验证,JVM还会对一些内建的安全特性进行检查
强制内存的结构话访问,避免了恶意用户在了解内存分布的情况下通过指针对JVM的内部结构进行破外。当然要了解JVM的内存分布也不是易事。JVM对运行时数据空间的分配是一个黑盒过程,完全由JVM自己决定如何分配,在class中没有任何相关的信息。
字节码检查的局限就是对于那些不经过字节码检查的方法(如本地方法:native method)无法验证其安全性,所以这里采用的是对动态链接库的访问控制,对于那些足有足够可信度的代码才被允许访问本地方法。具体的实现是,由安全管理器来决定代码是否有调用动态链接库的权限,因为调用本地方法必须调用动态链接库。这样一来,不可信的代码将无法通过调用本地方法来绕过字节码检查。
[4]步骤四:安全管理器SecurityManager:
这一步是编程中最接近程序的一个环节,SecurityManager存在于JavaAPI里面,是可以通过编程来完成安全策略管理的,默认情况下,Java应用是不设置SecurityManager实例的,但是这个实例却需要我们在启动的时候通过System.setSecurityManager来进行设置。一般情况下,调用了SecurityManager.checkPermission(Permission perm)来完成的,外部程序可以创建一个权限实例Permission来进行Check操作。主要应用为:
【这一步内容比较多,这里不详细讲解,带过】
[5]步骤五:Java签名/证书机制:
Java签名机制使得使用者可以安全调用外部提供的jar文件,签名必须是基于jar包的,也就是如果要使用安全模型必须要将提供的class文件打包成jar,然后使用JDK工具(jarsigner)对jar进行签名。新安全平台中对足够信任度的代码放宽了限制,要获得充分信任须通过代码签名来实现,若我们对某一签名团体足够信任,比如SUN,那么具有该团体签名的代码将被给予充分信任。一个基本的思路大致为,代码发布者创建私钥/公钥对,然后利用私钥对发布代码进行签名,代码使用方在获得代码发布者提供的公钥后对代码进行验证,确认代码确为该提供者提供以及在发布后未经非法修改。这其中存在一些潜在的危险,既是公钥是否是该代码发布者提供的,恶意用户可能替换掉合法的公钥,这会导致用户将给与恶意用户发布的代码以充分信任,目前的常见做法是通过一些权威的证书机构来发布证书而不是公钥,代码发布者被证书发布机构认证合格后,可以将自己的公钥交付证书发布机构,证书发布机构再通过私钥加密该公钥,从而生成证书序列。这样替换公钥的可能性就变得微乎其微。不过世上无绝对安全之事,通过证书机构发布的证书也不是绝对安全的途径。
证书是在签名基础上,对签名值,再进一步做一次加密。而这次加密使用的私钥和公钥都是证书机构提供的。这种方式,是为了防止,有些恶意用户,在公钥发到你手上前,就对其做了手脚,然后再发一个动过手脚的jar给你,用动过手脚的公钥解动过手脚的jar包,是可以解开的。而使用证书后,它会对已经加密的签名值,再做一层加密,这样,到你手里,你只需要通过证书机构的公钥进行解密,然后再用jar包发布者的公钥解密就行了。(只能在一定程度上,提供一些安全性)
3)JVM的内部结构:
JVM是Java平台的核心,为了让编译产生的字节码能够更好的解释和执行,JVM主要分为6个部分【这里只是带过,想要了解JVM整体执行原理的读者可以去参考《Inside JVM》】:
ii.Java平台介绍:
Java平台(Java Platform)是一种纯软件平台,它可以在各种基于硬件的平台运行,它有三个版本(JavaSE,JavaME,JavaEE),它由Java应用程序接口(Java Application Programming Interface,API)和JVM组成,Java API是一个现成的软件组件集合,可以简化Applet和应用程序的开发部署,包括健壮、安全且可互操作的企业应用程序。它涵盖了从基本对象到连网和安全性,再到XML生成和Web服务的所有东西,Java API组织成相关类和接口的库,库也可以成为包。
每个包实现包括:
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平台所有的术语以及相关介绍,因为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,这就是主函数参数列表里面的参数的使用
小节一下上边几点:
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版本用法】
@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 package.class#member的典型形式 |
引用当前类的成员 |
@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}]
继承(拷贝)文档从最近的“继承类或可执行的接口”到当前在这个标签的位置的文档注释内容,这使您可以编写更多与继承相关的一般性文档
下边的情况比较适合:
{@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工具相关的,这个留到命令行工具里面去介绍。
iii.JDK和JRE的区别:
JDK(Java Development Kit的缩写),主要是指Java的开发环境和运行环境的一个集成开发包,这是面向开发人员的。
JRE(Java Runtime Enviroment的缩写),是指Java的运行环境,这一部分不包括开发环境,这是面向用户的。
JDK主要目的是为了开发、修改、调试、部署作为主体用途,因为有了JDK才能使用它提供的工具进行Java程序开发以及相关操作,这一开发包主要是针对开发人员的。JRE只是一个Java的运行环境,这里有一点需要说明的是,当一个程序开发完了需要在PC上运行的时候,该PC必须要提供一个JRE,也就是Java的运行环境,否则使用Java开发的软件是不能够直接运行在PC机上的,任何一个系统如果要运行Java的应用程序是必须依赖一个JRE的,有了这个运行时,才使得Java开发的软件可以无缝运行在操作系统上,而且对于像Tomcat这种服务器而言,JRE还远远不够,必须要JDK才能起到一定的作用,【*:这里提一下,Tomcat安装在搜索JDK的时候必须是JDK的路径,而不是JRE的路径,也就是说如果依赖Tomcat进行开发不能单纯配置一个JRE环境。】
其他相关知识参考一下网上的文档:
[1]为什么Sun要让JDK安装两套相同的JRE?这是因为JDK里面有很多用Java所编写的开发工具(如javac.exe、jar.exe等),而且都放置在 \lib\tools.jar 里。从下面例子可以看出,先将tools.jar改名为tools1.jar,然后运行javac.exe,显示如下结果: Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac /Main 这个意思是说,你输入javac.exe与输入 java -cp c:\jdk\lib\tools.jar com.sun.tools.javac.Main 是一样的,会得到相同的结果。从这里我们可以证明javac.exe只是一个包装器(Wrapper),而制作的目的是为了让开发者免于输入太长的指命。而且可以发现\lib目录下的程序都很小,不大于2 9K,从这里我们可以得出一个结论。就是JDK里的工具几乎是用Java所编写,所以也是Java应用程序,因此要使用JDK所附的工具来开发Java程序,也必须要自行附一套JRE才行,所以位于C:\Program Files\Java目录下的那套JRE就是用来运行一般Java程序用的。
[2]如果一台电脑安装两套以上的JRE,谁来决定呢?这个重大任务就落在java.exe身上。Java.exe的工作就是找到合适的JRE来运行Java程序。 Java.exe依照底下的顺序来查找JRE:自己的目录下有没有JRE;父目录有没有JRE;查询注册表: [HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment] 所以java.exe的运行结果与你的电脑里面哪个JRE被执行有很大的关系。
[3]介绍JVM JRE目录下的Bin目录有两个目录:server与client。这就是真正的jvm.dll所在。 jvm.dll无法单独工作,当jvm.dll启动后,会使用explicit的方法(就是使用Win32 API之中的LoadLibrary()与GetProcAddress()来载入辅助用的动态链接库),而这些辅助用的动态链接库(.dll)都必须位于jvm.dll所在目录的父目录之中。因此想使用哪个JVM,只需要设置PATH,指向JRE所在目录底下的jvm.dll。
iv.Java标识符:
标识符是指可被用来为类、变量或方法等命名的字符序列,换言之,标识符就是用户自定义的名称来标识类、变量或方法等。更简单的说,标识符就是一个名字。
标识符的选择并不是任意的,Java语言规定标识符由字母、数字、下划线和美元符号($)组成,并且第一个字符不能是数字,例如以下都是合法的标识符:
num、user3、price$、book_name、MIN_VALUE
Java标识符中的字符是区分大小写的,如name和Name是两个不同的标识符。Java中所谓的字母并不只包含英文字母、数字及一些常用符号。Java语言使用的是Unicode标准字符集中的字符,Unicode字符集最多可以识别65536个字符,其前128个字符与ASCII码表中的字符对应。其余的字符中就包含了世界上大部分语言中的“字母表”中的字母,大部分国家“字母表”中的字母都是Unicode字符集中的一个字符,如汉字中的“礼”字就是Unicode字符集中的第31036个字符。因此,Java可使用的字符不仅可以是英文字母等,也可以是汉字、朝鲜文、俄文、希腊字母以及其他许多语言中的文字。
总结起来:
[1]Java标识符只能由数字、字母、下划线“_”或“$”符号以及Unicode字符集组成
[2]Java标识符必须以字母、下划线“_”或“$”符号以及Unicode字符集开头
[3]Java标识符不可以是Java关键字、保留字(const、goto)和字面量(true、false、null)
[4]Java标识符区分大小写,是大小写敏感的
合法标识符举例:
_哈哈、哈哈、_name、name、$dollor、$123、哈1哈
非法标识符举例:
1name、1Hello、 H%llo
——[$]标识符举例——
package org.susan.java.basic;
public class IdentityTester {
public static void main(String args[]){
// 因为中文是Unicode字符集,所以是可以作为标识符的
String _哈哈 = "Hello";
String 哈哈 = "You are very good";
int _name = 0;
int name = 0;
float $dollor = 0.0f;
String 哈1哈 = "Hello One Hello";
//String 1Hello = "";
//String H%llo = "";
}
}
上边的代码段里面可以知道,合法标识符和非合法表示符的区别,这里特别需要注意的是中文汉字、朝鲜文、俄文、希腊字母以及其他文字,只要这些文字是属于Unicode字符集的,那么这些都是可以定义为标识符的,上边就是一个最简单的例子。
3.数据类型
数据类型在计算机语言里面,是对内存位置的一个抽象表达方式,可以理解为针对内存的一种抽象的表达方式。接触每种语言的时候,都会存在数据类型的认识,有复杂的、简单的。各种数据类型都需要在学习初期去了解,Java是强类型语言,所以Java对于数据类型的规范相对严格。数据类型是语言的抽象原子概念,可以说是语言中最基本的单元定义,在Java里面,本质上数据类型分为两种:简单类型和复杂类型。
简单类型:简单数据类型是不能简化的、内置的数据类型、由编程语言本身定义,它表示了真实的数字、字符和整数。
复杂类型:Java语言本身不支持C++中的结构(struct)或联合(union)数据类型,它的复合数据类型一般都是通过类或接口进行构造,类提供了捆绑数据和方法的方式,同时可以针对程序外部进行信息隐藏。
i.Java中的基本类型:
1)概念:
Java中的简单类型从概念上分为四种:实数、整数、字符、布尔值。但是有一点需要说明的是,Java里面有八种原始类型,其列表如下:
实数:double、float
整数:byte、short、int、long
字符:char
布尔值:boolean
复杂类型和基本类型的内存模型本质上不一样,简单数据类型的存储原理:所有的简单数据类型不存在“引用”概念,简单数据类型直接存储在内存中的内存栈上,数据本身的值存储在栈空间里面,而Java语言里面只有这八种数据类型是这种存储模型;而其他的只要是继承于Object类的复杂数据类型都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲,“引用”是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的。
2)原始类型特征:
Java的简单数据讲解列表如下:
int:int为整数类型,在存储的时候,用4个字节存储,范围为-2,147,483,648到2,147,483,647,在变量初始化的时候,int类型的默认值为0。
short:short也属于整数类型,在存储的时候,用2个字节存储,范围为-32,768到32,767,在变量初始化的时候,short类型的默认值为0,一般情况下,因为Java本身转型的原因,可以直接写为0。
long:long也属于整数类型,在存储的时候,用8个字节存储,范围为-9,223,372,036,854,775,808到9,223,372,036, 854,775,807,在变量初始化的时候,long类型的默认值为0L或0l,也可直接写为0。
byte:byte同样属于整数类型,在存储的时候,用1个字节来存储,范围为-128到127,在变量初始化的时候,byte类型的默认值也为0。
float:float属于实数类型,在存储的时候,用4个字节来存储,范围为32位IEEEE 754单精度范围,在变量初始化的时候,float的默认值为0.0f或0.0F,在初始化的时候可以写0.0。
double:double同样属于实数类型,在存储的时候,用8个字节来存储,范围为64位IEEE 754双精度范围,在变量初始化的时候,double的默认值为0.0。
char:char属于字符类型,在存储的时候用2个字节来存储,因为Java本身的字符集不是用ASCII码来进行存储,是使用的16位Unicode字符集,它的字符范围即是Unicode的字符范围,在变量初始化的时候,char类型的默认值为‘u0000‘。
boolean:boolean属于布尔类型,在存储的时候不使用字节,仅仅使用1位来存储,范围仅仅为0和1,其字面量为true和false,而boolean变量在初始化的时候变量的默认值为false。
——[$]提供一个字面量赋值的例子——
package org.susan.java.basic;
public class AssignTester {
public static void main(String args[]){
int x,y;//定义x,y变量
float f = 12.34f; //定义float类型的变量并赋值
double w = 1.234;//定义double类型变量并且赋值
boolean flag = true ; //指定变量flag为boolean型,且赋初值为true
char c ; //定义字符型变量c
String str ; //定义字符串变量str
String str1 = " Hi " ; //指定变量str1为String型,且赋初值为Hi
c = ‘A‘ ; //给字符型变量c赋值‘A‘
str = " bye " ; //给字符串变量str赋值"bye"
x = 12 ; //给整型变量x赋值为12
y = 300; //给整型变量y赋值为300
}
}
3)自动拆箱(AutoBox):
Java里面,每一种原始类型都对应着相应的包装类型,在JDK1.5之前(不包含JDK1.5),当包装类和原始类型进行相互转换的时候,需要调用包装类型的方法进行转换,不能通过操作符进行直接的计算。下边是一个原始类型和包装类型的一个对应表:
原始类型 | 对应的包装类型 | 默认值 | 存储格式 | 数据范围 |
short | java.lang.Short | 0 | 2个字节 | -32,768到32767 |
int | java.lang.Integer | 0 | 4个字节 | -2,147,483,648到2,147,483,647 |
byte | java.lang.Byte | 0 | 1个字节 | -128到127 |
char | java.lang.Character | /u0000 | 2个字节 | Unicode的字符范围 |
long | java.lang.Long | 0L或0l | 8个字节 | -9,223,372,036,854,775,808到9,223,372,036, 854,775,807 |
float | java.lang.Float | 0.0F或0.0f | 4个字节 | 32位IEEEE 754单精度范围 |
double | java.lang.Double | 0.0或0.0D(d) | 8个字节 | 64位IEEE 754双精度范围 |
boolean | java.lang.Boolean | false | 1位 | true(1)或false(0) |
简单看看下边这段代码:
package org.susan.java.basic;
public class AutoBoxTester {
public static void main(String args[]){
Integer integer = new Integer(12);
int integer2 = 33;
System.out.println(integer + integer2);
}
}
这段代码在JDK 1.5版本以上可以通过编译,而且不会报错,运行结果如下输出:
45
但是如果这段代码在JDK 1.4上边编译就会有问题了,因为在JDK 1.4的规范里面Integer属于一个包装类型,而int是原始类型,如果一个包装类型和原始类型要进行想对应的运算的时候,需要进行转换操作,直接将Integer类型转换称为原始类型操作,否则二者是不允许相加的,可以试试将上边代码用1.4版本进行编译:
javac -source 1.4 AutoBoxTester.java
就会收到下边的异常:
AutoBoxTester.java:5: operator + cannot be applied to java.lang.Integer,int
System.out.println(integer + integer2);
为什么呢?其实编译器给的信息很明显,使用JDK 1.5进行编译可以直接通过而且不会报错,是因为JDK 1.5提供了自动拆箱和自动装箱的功能,而JDK 1.4里面如果要使得上边的代码段可以编译通过,必须做一个简单的修改:
public class AutoBoxTester {
public static void main(String args[]){
Integer integer = new Integer(12);
int integer2 = 33;
System.out.println(integer.intValue() + integer2);
}
}
改成上边代码段了过后,在JDK 1.4平台下就可以得到输出:
45
从上边的例子可以看出,在JDK 1.5之前,如果要针对包装类进行数值计算,必须要将包装类直接转化称为原始类型,否则操作符本身是不会支持包装类的操作的,但是在JDK 1.5以及以后就没有这个限制了。
【简单总结:自动拆箱的意思就是不需要经过用户手工编程,编译器会直接识别包装类和原始类型相互之间的转换以及运算,并且把包装类型拆成原始类型进行代码里面规定的数值运算或者其他操作,这功能JDK的最低支持版本是1.5。其实对Java语言本身而言,Integer这种封装类实际上就是Java里面继承于Object的类的对象实例,只是在1.4之前,必须调用方法xxxValue()来完成手工拆箱的操作,只是这个在JDK 1.5不会有此限制。】
4)类型转换:
Java里面的类型转换包括两种:自动转换(隐式转换);强制转换(显示转换)
[1]自动转换:
条件:A.这两种类型是兼容的;B.目的类型数的范围(位数)比来源类型的大
当以上2个条件都满足的时候,拓宽转换(widening conversion)就会自动发生,例如,int类型范围比所有byte类型的合法范围大,因此不要求显示的强制转换语句。对于拓宽转换,兼容程度可以看下边的继承树:
java.lang.Object
|—java.lang.Boolean
|—java.lang.Character
|—java.lang.Number
|—java.lang.Byte
|—java.lang.Float
|—java.lang.Integer
|—java.lang.Long
|—java.lang.Short
|—java.lang.Double
从上边的继承树可以可以看到,Boolean类型、Character类型、Number类型是两两不兼容的,所以在隐式转换的过程,不兼容的类型是不能进行自动类型转换的
[2]强制转换:
尽管自动类型转换是很有帮助的,但并不能满足所有的编程需要。如果2种类型是兼容的,那么Java 将自动地进行转换。例如,把int 类型的值赋给long 类型的变量,总是可行的。然而,不是所有的类型都是兼容的,因此,不是所有的类型转换都是可以隐式实现的。例如,没有将double 型转换为byte 型的定义。幸好,获得不兼容的类型之间的转换仍然是可能的。要达到这个目的,你必须使用一个强制类型转换,它能完成两个不兼容的类型之间的显式变换。它的通用格式如下:
(target-type)value
[3]关于类型的自动提升,遵循下边的规则:
所有的byte、short、char类型的值将提升为int类型;
如果有一个操作数是long类型,计算结果是long类型;
如果有一个操作数是float类型,计算结果是float类型;
如果有一个操作数是double类型,计算结果是double类型;
自动类型转换图如下:
byte->short(char)->int->long->float->double
如果是强制转换的时候,就将上边的图反过来
[4]转换附加:
当两个类型进行自动转换的时候,需要满足条件:【1】这两种类型是兼容的,【2】目的类型的数值范围应该比源转换值的范围要大。(上边已经讲过了)而拓展范围就遵循上边的自动类型转换树,当这两个条件都满足的时候,拓展转换才会发生,而对于几个原始类型转换过程,根据兼容性boolean和char应该是独立的,而其他六种类型是可以兼容的,在强制转换过程,唯独可能特殊的是char和int是可以转换的,不过会使用char的ASCII码值比如:
int a = (int)‘a‘;
a的值在转换过后输出的话,值为97;
[5]基础类型的几个常见的代码例子:
——[$]附加转换和精度丢失——
package org.susan.java.basic;
public class CastingNumbers {
public static void main(String args[]){
double above = 1.7;
double below = 0.4;
System.out.println("above:" + above);
System.out.println("below:" + below);
System.out.println("(int)above:" + (int)above);
System.out.println("(int)below:" + (int)below);
System.out.println("(char)(‘a‘ + above):" + (char)(‘a‘ + above));
System.out.println("(char)(‘a‘ + below):" + (char)(‘a‘ + below));
}
}
可以分析上边这段代码的输出:
above:1.7
below:0.4
(int)above:1
(int)below:0
(char)(‘a‘ + above):b
(char)(‘a‘ + below):a
从上边的输出结果可以知道,在double到int的强制转换中,会发现精度丢失的情况,而且这种精度丢失是不考虑四舍五入的,是直接将浮点部分舍弃掉,从上边的输出就可以知道了;而且当int以及double转化称为char的时候,会使用上边提及的附加转换的结果,当‘a‘加了1过后进行char转换会生成b。
——[$]进制转换——
package org.susan.java.basic;
/**
*进制相互转换的例子,以十进制为基础
**/
public class SystemTester {
public static void main(String args[]){
//二进制和十进制相互转换
int integer = 117;
String binary = Integer.toBinaryString(integer);
System.out.println("Binary value of " + integer + " is " + binary);
String inputBinary = "100010011";
int bResult = Integer.parseInt(inputBinary,2);
System.out.println("Integer value of ‘" + inputBinary + "‘ is " + bResult);
//十进制和八进制的相互转换
int integer2 = 1024;
String octal = Integer.toOctalString(integer2);
System.out.println("Octal value of " + integer2 + " is " + octal);
String inputOctal = "712364";
int oResult = Integer.parseInt(inputOctal, 8);
System.out.println("Integer value of " + inputOctal + " is " + oResult);
//十进制和十六进制的相互转换
int integer3 = 4096;
String hex = Integer.toHexString(integer3);
System.out.println("Hex value of " + integer3 + " is " + hex);
String inputHex = "FEDD34";
int hResult = Integer.parseInt(inputHex, 16);
System.out.println("Integer value of " + inputHex + " is " + hResult);
}
}
上边这段代码的输出为:
Binary value of 117 is 1110101
Integer value of ‘100010011‘ is 275
Octal value of 1024 is 2000
Integer value of 712364 is 234740
Hex value of 4096 is 1000
Integer value of FEDD34 is 16702772
——[$]字符类型例子——
package org.susan.java.basic;
/**
*字符类型的例子
**/
public class CharTester {
public static void main(String args[]){
//Char和整数之间的相互转换
char ch1 = ‘a‘;
char ch2 = 66;
System.out.println("---------------");
System.out.println("ch1 is " + ch1);
System.out.println("ch2 is " + ch2);
//Character里面的方法
System.out.println("---------------");
System.out.println("isLowerCase:Z——" + Character.isLowerCase(‘Z‘));
System.out.println("isUpperCase:A——" + Character.isUpperCase(‘A‘));
System.out.println("isLetter:A——" + Character.isLetter(‘A‘));
System.out.println("isLetter:2——" + Character.isLetter(‘3‘));
System.out.println("isLetterOrDigit:%——" + Character.isLetterOrDigit(‘%‘));
System.out.println("isDigit:%——" + Character.isDigit(‘%‘));
System.out.println("isDigit:0——" + Character.isDigit(‘0‘));
System.out.println("isWhitespace: ‘ ‘——" + Character.isWhitespace(‘ ‘));
System.out.println("isWhitespace: A——" + Character.isWhitespace(‘A‘));
//从字符串里面抽取Char
System.out.println("---------------");
String inputValue = "123456";
System.out.println("Get 3 " + inputValue.charAt(2));
System.out.println(containsOnlyNumbers("123456"));
System.out.println(containsOnlyNumbers("123abc456"));
}
//检测某个字符串是否全部是数字
private static boolean containsOnlyNumbers(String str){
for(int i = 0; i < str.length(); i++ ){
if(!Character.isDigit(str.charAt(i))){
return false;
}
}
return true;
}
}
上边这段代码提取了Char类里面的一部分方法,其他的方法可以去查阅API的内容,输出为下:
---------------
ch1 is a
ch2 is B
---------------
isLowerCase: Z——false
isUpperCase: A——true
isLetter: A——true
isLetter: 2——false
isLetterOrDigit: %——false
isDigit: %——false
isDigit: 0——true
isWhitespace: ‘ ‘——true
isWhitespace: A——false
---------------
Get 3 3
true
false
Java的基本类型里面有几点需要说明:
[1]char类型是无符号16位整数,子面值必须用单引号括起来,如:‘a‘
[2]String在Java里面是类,直接父类是java.lang.Object,所以String不属于Java里面的原始类型
[3]长整数字有一个后缀为“L”或者“l”,八进制数字前缀为“0”,十六进制的前缀为“0x”
[4]默认的基本浮点类型为double
[5]float数据类型有一个后缀为“F”或“f”,Double数据类型后边可以跟“D”或者“d”,也可以不跟
[6]char类型可以使用通用的转义字符,但是不是ASCII码,应该是Unicode格式的如‘/u0000‘
标签:网站 功能 允许 tin spec pos contains loading 强制转换
原文地址:http://www.cnblogs.com/gispathfinder/p/6193980.html