logo资料库

JAVA语法.pdf

第1页 / 共36页
第2页 / 共36页
第3页 / 共36页
第4页 / 共36页
第5页 / 共36页
第6页 / 共36页
第7页 / 共36页
第8页 / 共36页
资料共36页,剩余部分请下载后查看
Java 语法总结 - 基本数据类型 Java 不是纯的面向对象的语言,不纯的地方就是这些基本数据类型不是对象。当然初 期 Java 的运行速度很慢,基本数据类型能在一定程度上改善性能。如果你想编写纯的 面向对象的程序,用包装器类是取代基本数据类型就可以了。 1、基本类型的存储空间。byte--8 位,short--16 位,int--32 位,long--64 位, float--32 位,double--64 位。这六种数字类型都是有符号的。固定的存储空间正是 Java 可移植性、跨平台的原因之一! 2、基本类型的存在导致了 Java OOP 的不纯粹性。因为基本类型不是对象,一切皆对 象是个小小的谎言。这是出于执行效率的权衡。 3、使用公式-2 的(位数-1)次幂到2 的(位数-1)次幂-1 确定整数类型的范围(byte、 short、int、long)。 4、char 是 16 位 Unicode 字符或者说是 16 位无符号整数,范围从 0 到 65535。即 便如此,可以强制转换非法的数据,如:char c1 = (char) 10000; char c2 = (char) -200;。可以从二进制存储的角度理解这点。 5、整数有八进制(以 0 开头的整数)、十进制、十六进制(以 0x 或 0X 开头的整数) 表示。 6、char 可以用单引号表示单个字符,如:'良'。也可以用 unicode 值'"ucafe'(四位 十六进制数)。 7、布尔型 boolean。布尔型只能是 true 或者 false,并且测试它为真还是假。它不能 进行任何其他的运算,或者转化为其他类型。 正例:boolean b1 = 1 > 2; 反例:int seen = button.isVisible(); 实践:简洁是美德,请不要这样写:if ( is == true && done == false ) ,只有新 手才那么写。 对于任何程序员 if ( whether && !done ) 都不难理解吧。所以去掉所有的==fasle 和 ==true 。 8、默认的浮点类型是双精度(double),要想要一个 float 必须在浮点数后面加 F 或 者 f。如:float pi = 3.14;是错误的。 9、默认的整数类型是 int 型,要想使用长整型可在后面加“l”或“L”,如:1000L。(小 写 l 容易被误认为 1,不推荐用) 10、float 可以精确到 7 位有效数字,第 8 位的数字是第 9 位数字四舍五入上取得的; double 可以精确到 16 位有效数字,第 17 位的数字是第 18 位数字四舍五入上取得的。 盖茨到底有多少钱?要用 double 表示,用 float 是装不下的…… PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
、 int 、 long--0 float--0.0f 11、如果要求精确的答案,请不要使用 float 和 double,因为它们是为了在广域数值 范围上提供较为精确的快速近似运算而精心设计的。然而,它们没有提供完全精确的结 果。尤其是对货币计算尤为不适合,因为要让一个 float 或 double 精确地表达 0.1(或 者 10 的任何) 12、BigInteger 支持任意精度的整数。BigDecimal 支持任意精度的定点数。 13、初始化无论怎么强调都不过分!Java 为所有的成员变量提供了默认初始化:byte、 short double--0.0 boolean--false char--'"u0000' ,特别地对象类型的引用全被初始化 为 null。(注意!除了数组之外的局部变量是得不到这种优待的,需要你自己初始化。 另外,默认初始化的值是你想要的吗?所以最好明确地对变量进行初始化,一般是在构 造函数中。) 14、基本类型之间的转化。Java 的类型检查很严格,从低精度转换到高精度是无须显 式转换的,double d = 123;。但是反过来,进行窄化转换,由高精度向低精度,或者 一种类型到另一种类型,则必须使用强制类型转化。Java 提供了安全转化机制,但是 结果是否是期望的,你自己保证吧。 double d = 12.5; float f = (int) d; //结果不是 13,而是 12! 浮点型转化为整型时,不进行四舍五入,直接截断小数点后面的数。 15、提升。各种基本数据类型进行混合运算,结果会是表达能力最强的那种。如:int 和 long 运算,结果是 long,整型和浮点型运算结果是浮点型。特殊的一点是:只要类 型比 int 小(如 char、byte、short),那么在运算之前,这些值会自动地转换成 int。 例子: byte b1 = 12; byte b2 = b1 + 1; //在编译时出错了!因为 b1+1 已经是 int 型了!切记! 16、浮点类型的科学表示法。在数学中 e 代表自然对数(Math.E 给出了 double 值), 而在 Java 中 e 代表 10 的幂次。浮点型的数可以这样表示 float f = 1e-27f; 代表 1 乘以 10 的负 27 次幂。 PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
Java 语法总结 - 数组 数组(array)是相同类型变量的集合,可以使用共同的名字引用它。数组可被定义为 任何类型,可以是一维或多维。数组中的一个特别要素是通过下标来访问它。数组提供 了一种将有联系的信息分组的便利方法。注意:如果你熟悉 C/C++,请注意, Java 数组的工作原理与它们不同。 1、数组不是集合,它只能保存同种类型的多个原始类型或者对象的引用。数组保存的 仅仅是对象的引用,而不是对象本身。 2、数组本身就是对象,Java 中对象是在堆中的,因此数组无论保存原始类型还是其他 对象类型,数组对象本身是在堆中的。 3、数组声明的两种形式:一、int[] arr; 二、int arr[]; 推荐使用前者,这符合 Sun 的命名规范,而且容易了解到关键点,这是一个 int 数组对象,而不是一个 int 原始类 型。 4、在数组声明中包含数组长度永远是不合法的!如:int[5] arr; 。因为,声明的时候 并没有实例化任何对象,只有在实例化数组对象时,JVM 才分配空间,这时才与长度有 关。 5、在数组构造的时候必须指定长度,因为JVM 要知道需要在堆上分配多少空间。反例: int[] arr = new int[]; 6、多维数组的声明。int[][][] arr; 是三维 int 型数组。 7、一维数组的构造。形如:String[] sa = new String[5]; 或者分成两句:String[] sa; sa = new String[5]; 8、原始类型数组元素的默认值。对于原始类型数组,在用new 构造完成而没有初始化 时,JVM 自动对其进行初始化。默认值:byte、short、 int 、long--0 float--0.0f double--0.0 boolean--false char--'"u0000' 。(无论该数组是成员变量还是局部 变量) 9、对象类型数组中的引用被默认初始化为 null。如:Car[] myCar = new Car[10]; 相当于从 myCar[0]到 myCar[9]都这样被自动初始化为 myCar[i] = null; 10、对象类型的数组虽然被默认初始化了,但是并没有调用其构造函数。也就是说: Car[] myCar = new Car[10]; 只创建了一个 myCar 数组对象!并没有创建 Car 对 象的任何实例! 11、多维数组的构造。float[][] ratings = new float[9][]; 第一维的长度必须给出, 其余的可以不写,因为 JVM 只需要知道赋给变量 ratings 的对象的长度。 PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
12、数组索引的范围。数组中各个元素的索引是从 0 开始的,到 length-1。每个数组 对象都有一个 length 属性,它保存了该数组对象的长度。(注意和 String 对象的 length()方法区分开来,这两者没有统一起来是很遗憾的。) 13 、 Java 有 数 组 下 标 检 查 , 当 访问 超 出 索 引 范 围 时 , 将 产 生 ArrayIndexOutOfBoundsException 运行时异常。注意,这种下标检查不是在编译 时刻进行的,而是在运行时!也就是说 int[] arr = new int[10]; arr[100] = 100; 这么明显的错误可以通过编译,但在运行时抛出!Java 的数组下标检查是需要额外开 销的,但是出于安全的权衡还是值得的,因为很多语言在使用数组时是不安全的,可以 任意访问自身内存块外的数组,编译运行都不会报错,产生难以预料的后果! PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
Java 语法总结 - 字符串 Java 的 String 太特别了,也太常用了,所以重要。我初学 Java 就被它搞蒙了,太多 混淆的概念了,比如它的不变性。所以必须深入机制地去理解它。 1、String 中的每个字符都是一个 16 位的 Unicode 字符,用 Unicode 很容易表达丰 富的国际化字符集,比如很好的中文支持。甚至 Java 的标识符都可以用汉字,但是没 人会用吧(只在一本清华的《Java2 实用教程》看过)。 2、判断空字符串。根据需要自己选择某个或者它们的组合 if ( s == null ) // 从引用的角度 if ( s.length() == 0 ) // 从长度判别 if ( s.trim().length () == 0 ) // 是否有多个空白字符 trim()方法的作用是是移除前导和尾部的 Unicode 值小于'"u0020'的字符,并返回“修 剪”好的字符串。这种方法很常用,比如需要用户输入用户名,用户不小心加了前导或 者尾部空格,一个好的程序应该知道用户不是故意的,即使是故意的也应该智能点地处 理。 判断空串是很常用的操作,但是 Java 类库直到 1.6 才提供了 isEmpty()方法。当且仅 当 length() 为 0 时返回 true 。 3、未初始化、空串""与 null。它们是不同的概念。对未初始化的对象操作会被编译器 挡在门外;null 是一个特殊的初始化值,是一个不指向任何对象的引用,对引用为 null 的对象操作会在运行时抛出异常 NullPointerException;而空串是长度为 0 的字符串, 和别的字符串的唯一区别就是长度为 0。 例子: public class StringTest{ static String s1; public static void main(String[] args) { String s2; String s3 = ""; System.out.print(s1.isEmpty()); // 运行时异常 System.out.print(s2.isEmpty()); // 编译出错 System.out.print(s3.isEmpty()); //ok !输出 true } } 4、String 类的方法很多,在编写相关代码的时候看看 JDK 文档时有好处的,要不然 花了大量时间实现一个已经存在的方法是很不值得的,因为编写、测试、维护自己的代 码使项目的成本增加,利润减少,严重的话会导致开不出工资…… 5、字符串的比较。 Java 不 允 许 自 定 义 操 作 符 重 载 , 因 此 字 符 串 的 比 较 要 用 compareTo() 或 者 compareToIgnoreCase()。s1.compareTo(s2),返回值大于 0 则,则前者大;等于 PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
0,一般大;小于 0,后者大。比较的依据是字符串中各个字符的 Unicode 值。 6、toString()方法。 Java 的任何对象都有 toString()方法,是从 Object 对象继承而来的。它的作用就是 让对象在输出时看起来更有意义,而不是奇怪的对象的内存地址。对测试也是很有帮助 的。 7、String 对象是不变的!可以变化的是 String 对象的引用。 String name = "ray"; name.concat("long"); // 字符串连接 System.out.println(name); //输出 name,ok,还是"ray" name = name.concat("long"); // 把字符串对象连接的结果赋给了 name 引用 System.out.println(name); //输出 name,oh!,变成了"raylong" 上述三条语句其实产生了 3 个 String 对象,"ray","long","raylong"。第 2 条语句 确实产生了"raylong"字符串,但是没有指定把该字符串的引用赋给谁,因此没有改变 name 引用。第 3 条语句根据不变性,并没有改变"ray",JVM 创建了一个新的对象, 把"ray","long"的连接赋给了 name 引用,因此引用变了,但是原对象没变。 8、String 的不变性的机制显然会在 String 常量内有大量的冗余。如:"1" + "2" + "3" +......+ "n" 产生了 n+(n+1)个 String 对象!因此 Java 为了更有效地使用内存,JVM 留出一块特殊的内存区域,被称为“String 常量池”。对 String 多么照顾啊!当编译器 遇见 String 常量的时候,它检查该池内是否已经存在相同的 String 常量。如果找到, 就把新常量的引用指向现有的 String,不创建任何新的 String 常量对象。 那么就可能出 现多个引用指向同一个 String 常量,会不会有别名的危险呢?No problem!String 对象的不变性可以保证不会出现别名问题!这是 String 对象与普通 对象的一点区别。 乍看起来这是底层的机制,对我们编程没什么影响。而且这种机制会大幅度提高 String 的效率,实际上却不是这样。为连接 n 个字符串使用字符串连接操作时,要消耗的时间 是 n 的平方级!因为每两个字符串连接,它们的内容都要被复制。因此在处理大量的字 符串连接时,而且要求性能时,我们不要用 String,StringBuffer 是更好的选择。 8、StringBuffer 类。StringBuffer 类是可变的,不会在字符串常量池中,而是在堆 中,不会留下一大堆无用的对象。而且它可将字符串缓冲区安全地用于多个线程。每个 StringBuffer 对象都有一定的容量。只要 StringBuffer 对象所包含的字符序列的长度 没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自 动增大。这个固定的容量是 16 个字符。我给这种算法起个名字叫“添饭算法”。先给你 一满碗饭,不够了再给你一满碗饭。 例子: StringBuffer sb = new StringBuffer(); // 初始容量为 16 个字符 sb.append("1234"); // 这是 4 个字符,那么 16 个字符的容量就足够了,没有 溢出 System.out.println(sb.length()); // 输出字符串长度是 4 PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
System.out.println(sb.capacity()); // 输出该字符串缓冲区的容量是 16 sb.append("12345678901234567"); // 这是 17 个字符,16 个字符的容 量不够了,扩容为 17+16 个字符的容量 System.out.println(sb.length()); // 输出字符串长度是 17 System.out.println(sb.capacity()); // 输出该字符串缓冲区的容量是 34 sb.append("890").reverse().insert(10,"-"); System.out.println(sb); // 输出 0987654321-09876543214321 字符串的长度和字符缓冲区的容量是两个概念,注意区别。 还有串联的方式看起来是不是很酷!用返回值连接起来可以实现这种简洁和优雅。 10、StringBuilder 类。 从 J2SE 5.0 提供了 StringBuilder 类,它和 StringBuffer 类是孪生兄弟,很像。它存在的价值在于:对字符串操作的效率更高。不足的是线程安 全无法保证,不保证同步。那么两者性能到底差多少呢?很多! 请参阅:http://book.csdn.net/bookfiles/135/1001354628.shtml 实践: 单个线程的时候使用 StringBuilder 类,以提高效率,而且它的 API 和 StringBuffer 兼容,不需要额外的学习成本,物美价廉。多线程时使用 StringBuffer,以保证安全。 11、字符串的比较。 下面这条可能会让你晕,所以你可以选择看或者不看。它不会对你的职业生涯造成任何 影响。而且谨记一条,比较字符串要用 equals()就 ok 了!一旦用了“==”就会出现很 怪异的现象。之所以把这部分放在最后,是想节省大家的时间,因为这条又臭又长。推 荐三种人:一、没事闲着型。二、想深入地理解 Java 的字符串,即使明明知道学了也 没用。三、和我一样爱好研究“茴”字有几种写法。 还是那句老话,String 太特殊了,以至于某些规则对 String 不起作用。个人感觉这种 特殊性并不好。看例子: 例子 A: String str1 = "java"; String str2 = "java"; System.out.print(str1==str2); 地球上有点 Java 基础的人都知道会输出 false,因为==比较的是引用,equals 比较 的是内容。不是我忽悠大家,你们可以在自己的机子上运行一下,结果是 true!原因 很简单,String 对象被放进常量池里了,再次出现“java”字符串的时候,JVM 很兴奋 地把 str2 的引用也指向了“java”对象,它认为自己节省了内存开销。不难理解吧 呵呵 例子 B: String str1 = new String("java"); String str2 = new String("java"); System.out.print(str1==str2); 看过上例的都学聪明了,这次肯定会输出 true!很不幸,JVM 并没有这么做,结果是 false。原因很简单,例子 A 中那种声明的方式确实是在 String 常量池创建“java”对象, PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
但是一旦看到 new 关键字,JVM 会在堆中为 String 分配空间。两者声明方式貌合神 离,这也是我把“如何创建字符串对象”放到后面来讲的原因。大家要沉住气,还有一个 例子。 例子 C: String str1 = "java"; String str2 = "blog"; String s = str1+str2; System.out.print(s=="javablog"); 再看这个例子,很多同志不敢妄言是 true 还是 false 了吧。爱玩脑筋急转弯的人会说 是 false 吧……恭喜你,你会抢答了!把那个“吧”字去掉你就完全正确。原因很简单, JVM 确实会对型如 String str1 = "java"; 的 String 对象放在字符串常量池里,但是 它是在编译时刻那么做的,而 String s = str1+str2; 是在运行时刻才能知道(我们 当然一眼就看穿了,可是Java 必须在运行时才知道的,人脑和电脑的结构不同),也就 是说 str1+str2 是在堆里创建的,s 引用当然不可能指向字符串常量池里的对象。没崩 溃的人继续看例子 D。 例子 D: String s1 = "java"; String s2 = new String("java"); System.out.print(s1.intern()==s2.intern()); intern()是什么东东?反正结果是 true。如果没用过这个方法,而且训练有素的程序员 会去看 JDK 文档了。简单点说就是用intern()方法就可以用“==”比较字符串的内容了。 在我看到 intern()方法到底有什么用之前,我认为它太多余了。其实我写的这一条也很 多余,intern()方法还存在诸多的问题,如效率、实现上的不统一…… 例子 E: String str1 = "java"; String str2 = new String("java"); System.out.print(str1.equals(str2)); 无论在常量池还是堆中的对象,用 equals()方法比较的就是内容,就这么简单! PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
分享到:
收藏