Java Jdk6学习笔记[Ppt]

3,764 views

Published on

2 Comments
1 Like
Statistics
Notes
No Downloads
Views
Total views
3,764
On SlideShare
0
From Embeds
0
Number of Embeds
50
Actions
Shares
0
Downloads
106
Comments
2
Likes
1
Embeds 0
No embeds

No notes for slide

Java Jdk6学习笔记[Ppt]

  1. 1. 第1章 • 了解Java – 什么是Java – Java的特性 – 如何学习Java
  2. 2. 什么是Java • 最早是Sun公司GreenProject中撰写Star7 应用程序的一个程序语言 – JamesGosling的窗外有颗橡树(Oak) • 全球信息网兴起,JavaApplet成为网页互动 技术的代表 • 1995/5/23,Java DevelopmentKits(当时 的JDK全名)1.0a2版本正式对外发表
  3. 3. 什么是Java • Java是面向对象(Object-Oriented)程序 语言,具有更高的跨平台可能性 • 在今日,更多时候代表了软件开发的架构 • 开发者版本发表时是以Java DevelopmentKits名称发表,简称JDK • J2SE 5.0(Java 2 Platform Standard Edition5.0)时的JDK称为J2SE Development Kit 5.0
  4. 4. 什么是Java • J2SE 5.0(Java 2 Platform Standard Edition5.0)时的JDK称为J2SE Development Kit 5.0 • 从JavaSE 6(Java Platform, Standard Edition6)开始的JDK6则称之为Java SE Development Kit 6 – 不再带有“2”这个号码,版本号6或1.6.0都使用 – 6是产品版本(productversion),而1.6.0是开 发者版本(developerversion)
  5. 5. Java的特性 • 语言特性 – 简单(Simple) – 面向对象(Object-oriented) – 网络(Network-savvy) – 解译(Interpreted) – 坚固(Robust) – 安全(Secure) – 可携(Portable) – 高效能(High-performance)
  6. 6. Java的特性 • 应用平台 – Java SE • Java Platform, Standard Edition – Java EE • Java Platform, Enterprise Edition – Java ME • Java Platform, Micro Edition
  7. 7. Java Platform, Standard Edition (Java SE) • Java各应用平台的基础
  8. 8. Java Platform, Standard Edition (Java SE) • JVM – Java虚拟机(Java Virtual Machine,JVM) • JRE – Java执行环境(Java SE Runtime Environment,JRE) • JDK • Java语言
  9. 9. Java Platform, Enterprise Edition (Java EE) • 以JavaSE的基础,定义了一系列的服务、 API、协定等 • 适用于开发分布式、多层式(Multi- tiered)、以组件为基础、以Web为基础的 应用程序 • 技术像是JSP、Servlet、Enterprise JavaBeans(EJB)、Java Remote Method Invocation(RMI)等
  10. 10. Java Platform, Micro Edition (Java ME) • 作为小型数字设备上开发及部署应用程序 的平台,像是消费性电子产品或嵌入式系 统等 • 最为人所熟悉的设备如手机、PDA、股票 机等
  11. 11. 活跃的社群与丰富的资源 • 开发工具 • 开放原始码的组件 • 容器 • 测试工具 • 各式各样的软件专案 • 各个社群所支持的讨论区 • 取之不尽的文件
  12. 12. 如何学习Java • 奠定Java语法基础 • 运用基本的JavaSE API – 字符串处理、例外处理、对象容器 (Container)、输入输出(I/O)、线程 (Thread) • http://java.sun.com/javase/6/docs/api/inde x.html
  13. 13. 如何学习Java • 使用搜索引擎 – http://www.google.com/ • 加入社群参与讨论 – http://www.javaworld.com.tw/ • 学习地图 – http://java.sun.com/developer/onlineTraining/n ew2java/javamap/intro.html
  14. 14. 第2章 • 入门准备 – 下载、安装、瞭解JDK – 设定Path与Classpath – 第一个Java程序 – 选择开发工具
  15. 15. 下载JDK • JDK6发表日期为2006年12月11日 • 较新的修正版本将以Update名称,加上号 码来表示修正的版本号 • http://java.sun.com/javase/downloads/inde x.jsp
  16. 16. 安装JDK 包括公用JRE 一定要记得
  17. 17. 安装JDK 一定要记得
  18. 18. 了解JDK • 公用JRE是给开发好的程序之执行平台 • JDK本身也有自己的JRE – 位于JDK安装目录的「jre」目录下 • JDK本身所附的JRE比公用JRE多了个 server的VM(VirtualMachine)执行选项
  19. 19. 了解JDK JDK的JRE有server选项
  20. 20. 了解JDK • JDK的安装目录 – 「bin」目录 • JDK的工具程序 – 「demo」目录 • 范例程序 – 「jre」目录 • JDK自己附带的JRE – 「db」目录 • ApacheDerby数据库,纯Java所撰写的数据库
  21. 21. 了解JDK • JDK的安装目录 – 「lib」目录 • 工具程序实际上会使用的Java工具类别 – JDK中的工具程序,大多也是由Java所撰写而 成 – bin文件夹下的工具程序,不过是个包装器 (Wrapper) – 执行javac.exe等程序时,最后会呼叫lib目录中 tools.jar中的对应类别
  22. 22. 了解JDK • JDK的安装目录 – src.zip • Java提供的API类别之原始码文件压缩档
  23. 23. 设定Path • 找不到javac工具程序 • 必须告诉操作系统,应该到哪些目录下尝 试找到您所想使用的工具程序 – 设定系统变量中的 Path环境变量
  24. 24. 设定Path • 必须告诉操作系统,应该到哪些目录下尝 试找到您所想使用的工具程序 – 直接设定目前的环境变量包括Path变数 set Path= C:Program FilesJavajdk1.6.0bin;%Path% • Windows下安装JRE时,会将java.exe复制 至「C:WindowsSystem32」路径之下, 而这个路径在Path变量中是默认的路径
  25. 25. 设定Classpath • Java执行环境本身就是个平台,执行于这 个平台上的程序是已编译完成的Java程序 • 设定Path变量是为了让操作系统找到指定 的工具程序(例如Windows exe) • 设定Classpath目的就是为了让Java执行环 境找到指定的Java程序(JVM class)
  26. 26. 设定Classpath • JDK6默认会到现行工作目录,以及JDK的 「lib」目录中寻找Java程序 • javac -classpath classpath1;classpath2 … • 对于Windows操作系统来说,Path是让操 作系统可以找到“.exe”执行档的存在 • 对于Java执行环境来说,ClassPath就是让 JVM可以找到".class"执行档的存在
  27. 27. 第一个Java程序
  28. 28. 第一个Java程序 • 新增一个「文字文件」 • 重新命名文件为「HelloJava.java」
  29. 29. 第一个Java程序 • Java的源文件必须以扩展名.java作结束 • 主档名与类别名称必须一致 • 注意每个字母的大小写 • 空白只能是半型空格符或是Tab字符
  30. 30. 第一个Java程序 • javac HelloJava.java • error: cannot read: HelloJava.java – javac工具程序找不到您指定的.java档案 • HelloJava.java:1: class HelloJava is public, should be declared in a file named HellJava.java – 类别名称与主档名不符
  31. 31. 第一个Java程序 • HelloJava.java:3: cannot find symbol – 程序代码中某些部份打错了,最常发生的原因 可能是没有注意到字母大小写 • ‘javac’不是内部或外部命令、可执行的程序 或批处理文件 – Path设定有误或没有在Path中加入JDK的 「bin」目录
  32. 32. 第一个Java程序 • java HelloJava • Exception inthread"main" java.lang.NoClassDefFoundError – java工具程序找不到您所指定的类别 • Exceptionin thread "main" java.lan.NosuchMethodError: main – 没有指定Java程序的进入点(Entrypoint),java工具 程序指定的类别必须要有一个程序进入点,也就是必 须包括main(String[] args)这个方法(method)
  33. 33. 选择开发工具 • 从简单的文字编辑辅助工具开始 – UltraEdit(http://www.ultraedit.com/) – Editplus(http://www.editplus.com/) • 简单的开发环境 – JCreater(http://www.jcreator.com/) – BlueJ(http://www.bluej.org/index.html) • 功能更齐全的IDE – Eclipse(http://www.eclipse.org/) – NetBeans(http://www.netbeans.org/)
  34. 34. 第3章 • 语法入门 – 第一个Java程序 – 文本模式下与程序互动 – 数据、运算 – 流程控制
  35. 35. 第一个Java程序 • 定义类别(Class) • 定义区块(Block) • 定义main()方法(Method) • 撰写陈述(Statement) public class HelloJava { public static void main(String[] args) { System.out.println("嗨!我的第一个Java程序!"); } }
  36. 36. 给C使用者的第一個Java程序 • 给了C使用者类似printf()的功能 public class HelloJavaForC { public static void main(String[] args) { System.out.printf("%s! 这是您的第一个Java程序!n", "C语言Fan"); } } System.out.printf("%s! 这是您的第二个Java程序!", "C语言Fan").println(); System.out.printf("%s! 这是您的第%d 个Java程序!n", "C语言Fan", 3);
  37. 37. 为程序加入批注 • 原始码档案中被标注为批注的文字,编译 程序不会去处理它 /*作者:良葛格 * 功能:示范printf()方法 * 日期:2005/4/30 */ public class ThirdJavaForC { public static void main(String[] args) { // printf()是J2SE5.0的新功能,必须安裝JDK5.0才能编译 System.out.printf("%s! 这是您的第%d个Java程序!n", "C语言Fan", 3); } }
  38. 38. 为程序加入批注 • 不能用巢状方式来撰写多行批注 /*批注文字1……bla…bla /* 批注文字2……bla…bla */ */ • 多行批注可以包括单行批注 /*批注文字1……bla…bla //批注文字2……bla…bla */
  39. 39. 使用Scanner取得输入 • 在J2SE 5.0中,可以使用java.util.Scanner 类别取得使用者的输入 Scanner scanner = new Scanner(System.in); System.out.print("请输入您的名字:"); System.out.printf("哈啰!%s!n", scanner.next()); • 可以使用这个工具的next()功能,来取得用 户的输入字符串 System.out.print("请输入一个数字:"); System.out.printf("您输入了%d!n", scanner.nextInt());
  40. 40. 使用BufferedReader取得输入 • BufferedReader建构时接受java.io.Reader 物件 – 可使用java.io.InputStreamReader BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(System.in)); System.out.print("请输入一列文字,可包括空白: "); String text = bufferedReader.readLine(); System.out.println("您输入的文字: " + text);
  41. 41. 标准输入输出串流 • System类别中的静态物件out – 提供标准输出串流(Stream)输出 – 通常对应至显示输出(终端机输出) – 可以将输出重新导向至一个档案 – java HelloJava > HelloJavaResult.txt • System标准输入串流in – 在程序开始之后它会自动开启,对应至键盘或 其它的输入来源
  42. 42. 标准输入输出串流 • 标准错误输出串流err – 在程序执行后自动开启,将指定的字符串输出 至显示设备或其它指定的装置 – err会立即显示错误讯息 – err输出串流的讯息不会被重新导向 System.out.println("使用out输出讯息"); System.err.println("使用err输出讯息"); java ErrDemo > ErrDemoResult.txt 使用err输出讯息
  43. 43. 输出格式控制 控制字符 作用 反斜杠 ' 单引号' " 双引号" uxxxx 以16进位数指定Unicode字符输出 xxx 以8进位数指定Unicode字符输出 b 倒退一个字符 f 换页 n 换行 r 游标移至行首 t 跳格(一个Tab键) System.out.println("u0048u0065u006Cu006Cu006F");
  44. 44. 输出格式控制 • 若是使用J2SE5.0或更高的版本 //输出19的十进制表示 System.out.printf("%d%n", 19); //输出19的八进制表示 System.out.printf("%o%n", 19); //输出19的十六进制表示 System.out.printf("%x%n", 19);
  45. 45. 格式字符 作 用 %% 在字符串中显示% %d 以10进位整数方式输出,提供的数必须是Byte、Short、 Integer、Long、 或BigInteger %f 将浮点数以10进位方式输出,提供的数必须是Float、Double或 BigDecimal %e, %E 将浮点数以10进位方式输出,并使用科学记号,提供的数必须是Float、 Double或BigDecimal %a, %A 使用科学记号输出浮点数,以16进位输出整数部份,以10进位输出指数 部份,提供的数必须是Float、Double、BigDecimal %o 以8进位整数方式输出,提供的数必须是Byte、Short、 Integer、Long、 或BigInteger %x, %X 将浮点数以16进位方式输出,提供的数必须是Byte、Short、 Integer、 Long、或BigInteger %s, %S 将字符串格式化输出 %c, %C 以字符方式输出,提供的数必须是Byte、Short、Character或 Integer %b, %B 将"true"或"false"输出(或"TRUE"、"FALSE",使用 %B)。另外,非null值输 出是"true",null值输出是"false" %t, %T 输出日期/时间的前置,详请看在线API文件
  46. 46. 输出格式控制 • 可以在输出浮点数时指定精度 – System.out.printf("example:%.2f%n", 19.234); – example:19.23 • 可以指定输出时,至少要预留的字符宽度 – System.out.printf("example:%6.2f%n", 19.234); – example: 19.23 – 补上一个空白在前端
  47. 47. 基本的数据型态(Primitivetype) • 整数 – 短整数(short)(占2个字节) – 整数(int)(占4个字节) – 长整数(long)(占8个字节) • 字节 – 专门储存位数据 – 占一个字节 • 浮点数 – 浮点数(float)(占4个字节) – 倍精度浮点数(double)(占8个字节)
  48. 48. 基本的数据型态(Primitivetype) • 字符 – 采Unicode编码 – 前128个字符编码与ASCII编码兼容 – 每个字符数据型态占两个字节 – 可储存的字符范围由'u0000'到'uFFFF' • 布尔数 – 占内存2个字节 – 可储存true与false两个数值
  49. 49. 基本的数据型态(Primitivetype) System.out.printf("short t数值范围:%d ~ %dn", Short.MAX_VALUE,Short.MIN_VALUE); System.out.printf("int t数值范围:%d ~ %dn", Integer.MAX_VALUE, Integer.MIN_VALUE); System.out.printf("long t数值范围:%d ~ %dn", Long.MAX_VALUE, Long.MIN_VALUE); System.out.printf("byte t数值范围:%d ~ %dn", Byte.MAX_VALUE, Byte.MIN_VALUE); System.out.printf("float t数值范围:%e ~ %en", Float.MAX_VALUE, Float.MIN_VALUE); System.out.printf("double t数值范围:%e ~ %en", Double.MAX_VALUE, Double.MIN_VALUE);
  50. 50. 变数、常数 • 在Java中要使用变量,必须先宣告变量名 称与数据型态 int age; //宣告一个整数变量 double scope; //宣告一个倍精度浮点数变量 • 使用int、float、double、char等关键词来宣 告变量名称并指定其数据型态 – 不可以使用数字作为开头 – 不可以使用一些特殊字符,像是*&^%之类 – 不可以與Java内定的关键词同名
  51. 51. 变数、常数 • 鼓励用清楚的名称来表明变量的作用 int ageOfStudent; int ageOfTeacher; • 不可以宣告变量后,而在未指定任何值给 它之前就使用它 • 编译程序在编译时会回报这个错误 variable var might not have been initialized
  52. 52. 变数、常数 • 使用「指定运算符」'='来指定变数的值 int ageOfStudent = 5; double scoreOfStudent = 80.0; char levelOfStudent = 'B'; System.out.println("年級t得分t等級"); System.out.printf("%4dt %4.1ft %4c", ageOfStudent, scoreOfStudent, levelOfStudent);
  53. 53. 变数、常数 • 宣告变量名称的同时,加上“final”关键词来 限定 • 这个变量一但指定了值,就不可以再改变 它的值 final int maxNum = 10; maxNum = 20; cannot assign a value to final variable maxNum
  54. 54. 算术运算 • 加(+)、减(-)、乘(*)、除(/)、余 除运算符(%) – System.out.println(1 + 2 * 3); – System.out.println(1+2+3 / 4); – System.out.println((double)(1+2+3) / 4);
  55. 55. 算术运算 • 这段程序会印出什么结果? int testNumber = 10; System.out.println(testNumber / 3); • 使用下面的方法 int testNumber = 10; System.out.println(testNumber / 3.0); System.out.println((double) testNumber / 3);
  56. 56. 算术运算 • 将精确度大的值指定给精确度小的变量 时,由于在精确度上会有遗失,编译程序 会认定这是一个错误 int testInteger = 0; double testDouble = 3.14; testInteger = testDouble; System.out.println(testInteger); possible loss of precision found : double required: int testInteger = testDouble ^ 1 error
  57. 57. 算术运算 • 必须明确加上转换的限定字,编译程序才 不会回报错误 testInteger =(int) testDouble; • '%'运算符是余除运算符 count = (count + 1) % 360;
  58. 58. 比较、条件运算 • 大于(>)、不小于(>=)、小于(<)、 不大于(<=)、等于(==)、不等于 (!=) System.out.println("10 > 5结果" + (10 > 5)); System.out.println("10 >= 5结果" + (10 >= 5)); System.out.println("10 < 5结果" + (10 < 5)); System.out.println("10 <= 5结果" + (10 <= 5)); System.out.println("10 == 5结果" + (10 == 5)); System.out.println("10 != 5结果" + (10 != 5));
  59. 59. 比较、条件运算 • 条件运算符 条件式?成立传回值:失败传回值 System.out.println("该生是否及格? " + (scoreOfStudent >= 60 ? '是' : '否')); System.out.println("是否为奇數? " + (number%2 != 0 ? '是' : '否'));
  60. 60. 逻辑、位运算 • 「且」(&&)、「或」(||)、「反相」(!) int number = 75; System.out.println((number > 70 && number < 80)); System.out.println((number > 80 || number < 75)); System.out.println(!(number > 80 || number < 75)); • &(AND)、|(OR)、^(XOR)与~(补 码) System.out.println("0 AND 0tt" + (0 & 0)); System.out.println("0 AND 1tt" + (0 & 1)); System.out.println("1 AND 0tt" + (1 & 0)); System.out.println("1 AND 1tt" + (1 & 1)); byte number = 0; System.out.println((int)(~number));
  61. 61. 逻辑、位运算 • 左移(<<)、右移(>>)、>>>运算符 int number = 1; System.out.println( "2的0次: " + number); number =number << 1; System.out.println("2的1次: " + number); number = number << 1; System.out.println("2的2次: " + number); number = number << 1; System.out.println("2的3次:" + number); 00000001 1 00000010 2 00000100 4 00001000 8
  62. 62. 递增、递减运算 • 递增、递减运算符 int i = 0; System.out.println(++i); System.out.println(--i); • 将递增或递减运算符撰写在变量之前或变 量之后 int i = 0; int number = 0; number = ++i; //相当於i = i + 1; number = i; System.out.println(number); number = --i; //相当於i = i - 1; number = i; System.out.println(number);
  63. 63. 递增、递减运算 • 将递增或递减运算符撰写在变量之前或变 量之后 int i = 0; int number = 0; number = i++; //相当於number = i; i = i + 1; System.out.println(number); number = i--; //相当于number = i; i = i - 1; System.out.println(number);
  64. 64. 递增、递减运算 指定运算符 范 例 结 果 += a += b a=a+b -= a -= b a=a-b *= a *= b a=a*b /= a /= b a=a/b %= a %= b a=a%b &= a &= b a=a&b |= a |= b a=a|b ^= a ^= b a=a^b <<= a <<= b a = a << b >>= a >>= b a = a >> b
  65. 65. if条件式 • 语法 if(条件式) 陈述句一; else 陈述句二; • 复合陈述句 if(条件式) { 陈述句一; 陈述句二; } else { 陈述句三; 陈述句四; }
  66. 66. if条件式 Scanner scanner = new Scanner(System.in); System.out.print("请输入数字: "); int input = scanner.nextInt(); int remain = input % 2; //求除2的余数 if(remain == 1) //如果余数为1 System.out.println(input +"为奇數"); else System.out.println(input +"为偶數");
  67. 67. if条件式 • if中再设定执行的条件 if(条件式一) { 陈述句一; if(条件式二) 陈述句二; 陈述句三; } if(条件式一) { if(条件式一) { 陈述句一; 陈述句一; //其它陈述句 //其它陈述句 } else } else if(条件式二) if(条件式二) 陈述句二; 陈述句二;
  68. 68. if条件式 Scanner scanner = new Scanner(System.in); System.out.print("输入分数:"); int score = scanner.nextInt(); if(score >= 90) System.out.println("得A"); else if(score >= 80 && score < 90) System.out.println("得B"); else if(score >= 70 && score < 80) System.out.println("得C"); else if(score >= 60 && score < 70) System.out.println("得D"); else System.out.println("得E(不及格)");
  69. 69. switch条件式 • switch的语法架构 switch(变量名称或表达式) { case符合数字或字符: 陈述句一; break; case符合数字或字符: 陈述句二; break; default: 陈述三; }
  70. 70. Scanner scanner = new Scanner(System.in); System.out.print("请输入分數: "); int score = scanner.nextInt(); int level = (int) score/10; switch(level) { case 10: case 9: System.out.println("得A"); break; case 8: System.out.println("得B"); break; case 7: System.out.println("得C"); break; case 6: System.out.println("得D"); break; default: System.out.println("得E(不及格)");
  71. 71. for循环 • 基本语法 for(初始式;判断式;递增式) { 陈述句一; 陈述句二; } for(int j = 1; j < 10; j++) { for(int i = 2; i < 10; i++) { System.out.printf("%d*%d=%2d ",i, j, i * j); } System.out.println(); }
  72. 72. for循环 • for括号中的每个陈述区块是以分号';'作区 隔,而在一个陈述区块中若想写两个以上 的陈述句,则使用逗号','作区隔 for (int i = 2, j = 1; j < 10; i = (i==9)?((++j/j)+1):(i+1)) { System.out.printf("%d*%d=%2d%c", i, j, i * j, (i==9 ? 'n' : ' ')); }
  73. 73. while循环 Scanner scanner = new Scanner(System.in); int score = 0; int sum = 0; int count = -1; while(score != -1) { count++; sum += score; System.out.print("输入分数(-1结束):"); score = scanner.nextInt(); } System.out.println("平均:" + (double) sum/count)
  74. 74. while循环 Scanner scanner = new Scanner(System.in); int input = 0; int replay = 0; do { System.out.print("输入整数值:"); input = scanner.nextInt(); System.out.println("输入数为奇数?" + ((input%2 == 1) ? 'Y': 'N')); System.out.print("继续(1:继续0:结束)?"); replay = scanner.nextInt(); } while(replay == 1);
  75. 75. break、continue • break可以离开目前switch、for、while、 dowhile的区块 • continue只会结束其之后区块的陈述句,并 跳回循环区块的开头继续下一个循环 for(int i = 1; i < 10; i++) { if(i == 5) break; System.out.println("i = " + i); } for(int i = 1; i < 10; i++) { if(i == 5) continue; System.out.println("i = " + i); }
  76. 76. break、continue • break与continue还可以配合标签使用 back : { for(int i = 0; i < 10; i++) { if(i == 9) { System.out.println("break"); break back; } } System.out.println("test"); }
  77. 77. break、continue • break与continue还可以配合标签使用 back1: for(int i = 0; i < 10; i++){ back2: for(int j = 0; j < 10; j++) { if(j == 9) { continue back1; } } System.out.println("test"); }
  78. 78. 第4章 • 从autoboxing、unboxing认识对象 – 关于对象 – 自动装箱、拆箱
  79. 79. 使用对象 • 想写一个程序取得现在的系统时间,您只 要产生一个java.util.Date工具就可以了 • Date实际上如何向系统取得时间,则无需 您来操心 Date date = new Date(); System.out.println(date.toString()); Tue May 03 16:06:46 GMT+08:00 2005
  80. 80. 使用对象 • 字符串就是对象,是java.lang.String类别的 一个实例 String text = "Have a nice day!! :)"; System.out.println("原文:" + text); //传回全为大写的字符串内容 System.out.println("大写:" + text.toUpperCase()); //转回全为小写的字符串内容 System.out.println("小写:" + text.toLowerCase()); //计算字符串长度 System.out.println("长度:" + text.length()); //传回取代文字后的字符串 System.out.println("取代:" + text.replaceAll("nice", "good")); //传回指定位置后的子字符串 System.out.println("子字符串:" + text.substring(5));
  81. 81. 使用对象 • 简单的用户登入程序 System.out.print("使用者名称:"); String username = scanner.next(); System.out.print("用户密码:"); String password = scanner.next(); if("caterpillar".equals(username) && "1975".equals(password)) { System.out.println("秘密信息在此!"); } else { System.out.println(username + "您好,输入的登入数据有误,请重新输入!"); }
  82. 82. 包裹(Wrap)基本型态 • Long、Integer、Double、Float、Boolean 等类别是所谓的Wrapper类别 • 主要目的,就是让您提供一个对象实例作 为「壳」,将基本型态包到这个对象之中 • 如此您就可以操作这个对象,就好像您将 基本型态当作对象一样操作
  83. 83. 包裹(Wrap)基本型态 int data1 = 10; int data2 = 20; //使用Integer来包里int资料 Integer data1Wrapper = new Integer(data1); Integer data2Wrapper = new Integer(data2); //直接除以3 System.out.println(data1 / 3); //转为double值再除以3 System.out.println(data1Wrapper.doubleValue() / 3); //进行两个值的比较 System.out.println(data1Wrapper.compareTo(data2Wrapper));
  84. 84. 包裹(Wrap)基本型态
  85. 85. 自动装箱、拆箱 • 在J2SE5.0之前,要如下才能将int包装为一 个Integer物件 Integer integer = new Integer(10); • 在J2SE5.0之后提供了自动装箱的功能 Integer integer = 10;
  86. 86. 自动装箱、拆箱 Integer data1 = 10; Integer data2 = 20; //转为double值再除以3 System.out.println(data1.doubleValue() / 3); //进行两个值的比较 System.out.println(data1.compareTo(data2));
  87. 87. 自动装箱、拆箱 • 自动装箱运用的方法还可以如下: int i = 10; Integer integer = i; • 更一般化的java.lang.Number类别自动装箱 Number number = 3.14f;
  88. 88. 自动装箱、拆箱 • 自动拆箱(unboxing) Integer fooInteger = 10; int fooPrimitive = fooInteger; • 在运算时,也可以进行自动装箱与拆箱 Integer i = 10; System.out.println(i + 10); System.out.println(i++); Boolean boo = true; System.out.println(boo && false);
  89. 89. 小心使用boxing • 自动装箱与拆箱的功能是编译程序来帮忙 Integer i = 100; Integer i = new Integer(100); • 自动装箱与拆箱的功能是所谓的「编译程 序蜜糖」(Compilersugar) Integer i = null; Integer i = null; int j = i; int j = i.intValue(); NullPointerException
  90. 90. 小心使用boxing Integer i1 = 100; Integer i2 = 100; if (i1 == i2) System.out.println("i1 == i2"); 显示"i1 == i2" else System.out.println("i1 != i2"); Integer i1 = 200; Integer i2 = 200; if (i1 == i2) System.out.println("i1 == i2"); else System.out.println("i1 != i2"); 显示"i1 != i2"
  91. 91. 小心使用boxing • ‘==’也用于判断两个对象参考名称是否参考 至同一个对象 • 在自动装箱时对于值从-128到127之间的 值,它们被装箱为Integer对象后,会存在 内存之中被重用 Integer i1 = 200; Integer i2 = 200; if (i1.equals(i2)) System.out.println("i1 == i2"); else System.out.println("i1 != i2");
  92. 92. 第5章 • 阵列 – 一维数组、二维数组 – 进阶数组观念
  93. 93. 一维数组对象 • 宣告一个数组并初始数组内容 int[] score = {90, 85, 55, 94, 77}; for(int i = 0; i < score.length; i++) System.out.printf("score[%d] = %dn", i, score[i]); • 指定的索引值不可超出数组范围 – 会发生ArrayIndexOutOfBoundsException • length为数组对象的属性成员
  94. 94. 一维数组对象 • 当您宣告一个数组时,其实就是在配置一 个数组对象 • 一个完整的数组宣告方式如下 int[] arr = new int[10];
  95. 95. 一维数组对象 数据型态 初始值 byte 0 short 0 int 0 long 0L float 0.0f double 0.0d char u0000 boolean false
  96. 96. 一维数组对象 int[] arr = new int[10]; System.out.print("arr初始值: "); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); arr[i] = i; } System.out.print("narr设定值: "); for(int i = 0; i < arr.length; i++) System.out.print(arr[i] + " "); System.out.println();
  97. 97. 一维数组对象 • 在使用new新增数组时一并指定初始值 int[] score = new int[] {90, 85, 55, 94, 77}; for(int i = 0; i < score.length; i++) System.out.printf("score[%d] = %dn", i, score[i]);
  98. 98. 一维数组对象 • 可以使用动态的方式来宣告数组长度,而 不用在程序中事先决定数组大小 int length = scanner.nextInt(); float[] score = new float[length]; //动态配置长度 for(int i = 0; i < score.length; i++) { System.out.print("输入分数:"); float input = scanner.nextFloat(); score[i] = input; }
  99. 99. 二维数组对象 • 二维数组使用「名称」与「两个索引」来 指定存取数组中的元素 int[][] arr = {{1, 2, 3}, {4, 5, 6}}; for(int i = 0; i < arr.length; i++) { for(int j = 0; j < arr[0].length; j++) System.out.print(arr[i][j] + " "); System.out.println(); } • 以对象的方式来配置一个二维数组对象 int[][] arr = new int[2][3];
  100. 100. 二维数组对象 • 以对象的方式来配置一个二维数组对象 int[][] arr = new int[2][3];
  101. 101. 二维数组对象 int[][] arr = {{1, 2, 3}, {4, 5, 6}}; int[] foo = arr[0]; //将arr[0]所参考的数组对象指定给foo for(int i = 0; i < foo.length; i++) { System.out.print(foo[i] + " "); } System.out.println(); foo = arr[1]; //将arr[1]所参考的数组对象指定给foo for(int i = 0; i < foo.length; i++) { System.out.print(foo[i] + " "); } System.out.println();
  102. 102. 二维数组对象 • 使用new配置二维数组一并指定初值 int[][] arr = new int[][] {{1, 2, 3}, {4, 5, 6}}; • 宣告三维以上的数组 nt[][][] arr = { {{1, 2, 3}, {4, 5, 6}}, {{7, 8, 9}, {10, 11, 12}} }; int[][][] arr = new int[2][2][3];
  103. 103. 不规则数组 int arr[][]; arr = new int[2][]; arr[0] = new int[3]; // arr[0]参考至长度为3的一维数组 arr[1] = new int[5]; // arr[1]参考至长度为5的一维数组 for(int i = 0; i < arr.length; i++) { for(int j = 0; j < arr[i].length; j++) arr[i][j] = j + 1; } for(int i = 0; i < arr.length; i++) { for(int j = 0; j < arr[i].length; j++) System.out.print(arr[i][j] + " "); System.out.println(); }
  104. 104. 进阶的数组操作 • 一维数组的参考名称之宣告 int[] arr = null; • 将同一个对象指定给两个参考名称 int[] arr1 = {1, 2, 3, 4, 5}; int[] tmp1 = arr1; int[] tmp2 = arr1; System.out.print("透过tmp1取出数组值:"); for(int i = 0; i < tmp1.length; i++) System.out.print(tmp1[i] + " ");
  105. 105. 进阶的数组操作 • 将同一个对象指定给两个参考名称 System.out.print("n透过tmp2取出数组值:"); for(int i = 0; i < tmp2.length; i++) System.out.print(tmp2[i] + " "); tmp1[2] = 9; System.out.print("nn透过tmp1取出数组值:"); for(int i = 0; i < tmp1.length; i++) System.out.print(tmp1[i] + " "); System.out.print("n透过tmp2取出数组值:"); for(int i = 0; i < tmp2.length; i++) System.out.print(tmp2[i] + " "); System.out.println();
  106. 106. 进阶的数组操作 • 将同一个对象指定给两个参考名称 int[] arr1 = {1, 2, 3, 4, 5}; int[] tmp1 = arr1; int[] tmp2 = arr1;
  107. 107. 进阶的数组操作 • int[]arr之后,arr是一维数组的参考名称, 可以参考至任何长度的一维数组对象 int[] arr1 = {1, 2, 3, 4, 5}; int[] arr2 = {5, 6, 7}; int[] tmp = arr1; System.out.print("使用tmp取出arr1中的元素:"); for(int i = 0; i < tmp.length; i++) System.out.print(tmp[i] + " "); tmp = arr2; System.out.print("n使用tmp取出arr2中的元素:"); for(int i = 0; i < tmp.length; i++) System.out.print(tmp[i] + " "); System.out.println();
  108. 108. 数组复制 • 使用循环作数组复制 int[] arr1 = {1, 2, 3, 4, 5}; int[] arr2 = new int[5]; for(int i = 0; i < arr1.length; i++) arr2[i] = arr1[i]; for(int i = 0; i < arr2.length; i++) System.out.print(arr2[i] + " "); System.out.println();
  109. 109. 数组复制 • 使用System类别所提供的arraycopy()方法 int[] arr1 = {1, 2, 3, 4, 5}; int[] arr2 = new int[5]; System.arraycopy(arr1, 0, arr2, 0, arr1.length); for(int i = 0; i < arr2.length; i++) System.out.print(arr2[i] + " "); System.out.println(); • 在JDK6中,也为Arrays类别新增了数组复 制的copyOf()方法
  110. 110. Arrays类别 名 称 说 明 sort() 帮助您对指定的数组排序,所使用的是快速排序法 binarySearch() 让您对已排序的数组进行二元搜寻,如果找到指定的值就 传回该值所在的索引,否则就传回负值 fill() 当您配置一个数组之后,会依数据型态来给定默认值,例 如整数数组就初始为 0,您可以使用Arrays.fill()方法来将所 有的元素设定为指定的值 equals() 比较两个数组中的元素值是否全部相等,如果是将传回 true,否则传回 false
  111. 111. 数组比较 • 不可用'=='比较两个数组的元素值是否相等 int[] arr1 = {1, 2, 3, 4, 5}; int[] arr2 = {1, 2, 3, 4, 5}; int[] tmp = arr1; System.out.println(arr1 == tmp); System.out.println(arr2 == tmp);
  112. 112. 数组比较 • deepEquals()与deepToString() int[][] arr1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int[][] arr2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int[][] arr3 = {{0, 1, 3}, {4, 6, 4}, {7, 8, 9}}; System.out.println("arr1内容等于arr2 ? " + Arrays.deepEquals(arr1, arr2)); System.out.println("arr1内容等于arr3 ? " + Arrays.deepEquals(arr1, arr3)); System.out.println("arr1 deepToString()nt" + Arrays.deepToString(arr1));
  113. 113. foreach与数组 • 加强的for循环(Enhanced forLoop) for(type element : array) { System.out.println(element).... } • J2SE 5.0之前 int[] arr = {1, 2, 3, 4, 5}; for(int i = 0; i < arr.length; i++) System.out.println(arr[i]); • 在J2SE5.0之后 int[] arr = {1, 2, 3, 4, 5}; for(int element : arr) System.out.println(element);
  114. 114. foreach与数组 • 如果是对象的话 String[] names = {"caterpillar", "momor", "bush"}; for(String name : names) System.out.println(name); • 二维数组 int[][] arr = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; for(int[] row : arr) { for(int element : row) { System.out.println(element); } }
  115. 115. 对象数组 • 以下产生几个对象? int[] arr = new int[3]; • 以下的宣告产生几个对象? int[][] arr = new int[2][3]; • 以下产生几个对象? Integer[] arr = new Integer[3];
  116. 116. 对象数组 • 以下的宣告产生几个对象? Integer[][] arr = new Integer[2][3];
  117. 117. 第6章 • 字串 – 认识字符串(String) – 字符串进阶运用
  118. 118. String类别 • 在某些程序语言中,字符串是以字符数组 的方式存在 • 在Java中字符串不仅仅是字符数组,而是 String类别的一个实例 String text ="字符串的使用"; System.out.println(text);
  119. 119. String类别 • 字符串必须使用“”来包括您的文字 • 字符串的字符是使用Unicode字符来建构 • 字符串的串接在Java中可以直接使用'+' String msg ="哈啰!"; msg = msg + "Java程序设计!"; System.out.println(msg);
  120. 120. String类别 • 字符串在Java中以String类别的一个实例存 在 法 方 说 明 length() 取得字符串的字符长度 equals() 判断原字符串中的字符是否相等于指定字符串中的字符 toLowerCase() 转换字符串中的英文字符为小写 toUpperCase() 转换字符串中的英文字符为大写 String text = "hello"; System.out.println("字符串内容: " + text); System.out.println("字符串长度: " + text.length()); System.out.println("等於hello? " + text.equals("hello")); System.out.println("转为大寫: " + text.toUpperCase()); System.out.println("转为小寫: " + text.toLowerCase());
  121. 121. String类别 • 将输入的字符串转换为整数、浮点数等 方 法 说 明 Byte.parseByte(字符串) 将字符串剖析为位 Short.parseShort(字符串) 将字符串剖析为short整数 Integer.parseInt(字符串) 将字符串剖析为int整数 Long.parseLong(字符串) 将字符串剖析为long整数 Float.parseFloat(字符串) 将字符串剖析为float浮点数 Double.parseDouble(字符串) 将字符串剖析为double浮点数 • 指定的字符串无法剖析为指定的数据型态数值, 则会发生NumberFormatException例外
  122. 122. String类别 • 以配置对象的观念来宣告字符串 String str = new String("caterpillar"); • 两种宣告方式是有所差别的 String str = "caterpillar";
  123. 123. String类别 • 使用索引取得字符的相关方法 方 法 说 明 char charAt(int index) 传回指定索引处的字符 int indexOf(int ch) 传回指定字符第一个找到的索引位置 int indexOf(String str) 传回指定字符串第一个找到的索引位置 int lastIndexOf(int ch) 传回指定字符最后一个找到的索引位置 String substring(int beginIndex) 取出指定索引处至字符串尾端的子字符串 String substring(int beginIndex, int 取出指定索引范围子字符串 endIndex) char[] toCharArray() 将字符串转换为字符数组
  124. 124. String类别 • endsWith()方法 String[] filenames = {"caterpillar.jpg", "cater.gif", "bush.jpg", "wuwu.jpg", "clockman.gif"}; System.out.print("过滤出jpg檔案: "); for(int i = 0; i < filenames.length; i++) { if(filenames[i].endsWith("jpg")) { System.out.print(filenames[i] + " "); } } System.out.println("");
  125. 125. 不可变(immutable)字符串 • 一个字符串对象一旦被配置,它的内容就 是固定不可变的(immutable) • 不要以为下面的陈述就是改变一个字符串 对象的内容 String str = "Just"; str = "Justin";
  126. 126. 不可变(immutable)字符串 • 对于一些可以共享的字符串对象,会先在 String池中查找是否存在相同的String内容 String str1 = "flyweight"; String str2 = "flyweight"; System.out.println(str1 == str2); • 当您直接在程序中使用""来包括一个字符串 时,该字符串就会在String池中
  127. 127. 不可变(immutable)字符串 • String的intern()方法 – 如果池(Pool)中已经包括了相同的String对 象(相同与否由equals()方法决定),那么会 从池中返回该字符串 – 否则的话原String对象会被加入池中,并返回 这个String对象的参考
  128. 128. 不可变(immutable)字符串 String str1 = "fly"; String str2 = "weight"; String str3 = "flyweight"; String str4 = null; str4 = str1 + str2; System.out.println(str3 == str4); str4 = (str1 + str2).intern(); System.out.println(str3 == str4);
  129. 129. 不可变(immutable)字符串
  130. 130. 不可变(immutable)字符串 • 不可用‘==’比较字符串的字符内容是否相同 String str1 = new String("caterpillar"); String str2 = new String("caterpillar"); System.out.println(str1 == str2); • 要比较两个字符串对象的字符值是否相 同,您要使用equals()方法 String str1 = new String("caterpillar"); String str2 = new String("caterpillar"); System.out.println(str1.equals(str2));
  131. 131. StringBuilder类别 • 使用‘+’来串接字符串以达到附加新字符或 字符串的目的,但‘+’会产生一个新的String 实例 • 不建议使用'+'来进行字符串的串接
  132. 132. StringBuilder类别 String text = ""; long beginTime = System.currentTimeMillis(); for(int i = 0; i < 10000; i++) text = text + i; long endTime = System.currentTimeMillis(); System.out.println("运行时间:" + (endTime - beginTime)); StringBuilder builder = new StringBuilder(""); beginTime = System.currentTimeMillis(); for(int i = 0; i < 10000; i++) builder.append(String.valueOf(i)); endTime = System.currentTimeMillis(); System.out.println("运行时间:" + (endTime - beginTime));
  133. 133. 命令行自变量
  134. 134. 命令行自变量 • 在main()的参数列撰寫String[]args,目的就 是用来接受一个字符串数组 public static void main(String[] args) { System.out.print("读入的引數: "); for(int i = 0; i < args.length; i++) System.out.print(args[i] + " "); System.out.println(); } java CommandLineArg -file student.dat 读入的自变量: -file student.dat
  135. 135. 分离字符串 • 使用String的split() String[] fakeFileData = { "justint64/5/26t0939002302t5433343", "momort68/7/23t0939100391t5432343" }; for(String data : fakeFileData) { String[] tokens = data.split("t"); for(String token : tokens) { System.out.print(token + "t| "); } System.out.println(); }
  136. 136. 使用正则表示式 • matches()、replaceAll()等方法时使用 • Java在J2SE1.4之后开始支持正则表示式 • 可以在API文件的java.util.regex.Pattern类 别中找到支持的正则表示式相关信息
  137. 137. 使用正则表示式 • 几个常用的字符比对符号 方 法 说 明 . 符合任一字符 d 符合0到9任一个数字字符 D 符合0-9以外的字符 s 符合't'、'n'、'x0B'、'f'、'r'等空格符 w 符合a到z、A到Z、0到9等字符,也就是数字或是字母都符合 W 符合a到z、A到Z、0到9等之外的字符,也就是除数字与字母外 都符合
  138. 138. 使用正则表示式 String text = "abcdebcadxbc"; String[] tokens = text.split(".bc"); for(String token : tokens) { System.out.print(token + " "); } System.out.println(); tokens = text.split("..cd"); for(String token : tokens) { System.out.print(token + " "); } System.out.println();
  139. 139. 使用正则表示式 • Character class 范 例 作 用 [abc] 符合a、b或c [^abc] 符合「a或b或c」之外的字符 [a-zA-Z] 符合a到z或者是A到Z的字符 [a-d[m-p]] a到d或者是m到p,也可以写成[a-dm-p] [a-z&&[def]] a到z并且是d或e或f,结果就是d或e或f可以符合 [a-z&&[^bc]] a到z并且不是b或c [a-z&&[^m-p]] a到z并且不是m到p
  140. 140. 使用正则表示式 • Greedy quantifiers 范 例 作 用 X? X可出现一次或完全没有 X* X可出现零次或多次 X+ X可出现一次或多次 X{n} X可出现n次 X{n,} X可出现至少n次 X{n, m} X可出现至少n次,但不超过m次 X? X可出现一次或完全没有
  141. 141. Pattern、Matcher • 将正则表示式视为一个对象来重复使用, 可用Pattern的静态方法compile()进行编译 • compile()方法会传回一个Pattern的实例, 这个实例代表您的正则表示式
  142. 142. Pattern、Matcher String phones1 = "Justin的手机号码:0939-100391n" + "momor的手机号码:0939-666888n"; Pattern pattern = Pattern.compile(".*0939-d{6}"); Matcher matcher = pattern.matcher(phones1); while(matcher.find()) { System.out.println(matcher.group()); } String phones2 = "caterpillar的手机号码:0952-600391n" + "bush的手机号码:0939-550391"; matcher = pattern.matcher(phones2); while(matcher.find()) { System.out.println(matcher.group());
  143. 143. Pattern、Matcher String text = "abcdebcadxbc"; Pattern pattern = Pattern.compile(".bc"); Matcher matcher = pattern.matcher(text); while(matcher.find()) { System.out.println(matcher.group()); } System.out.println();
  144. 144. 第7章 • 封装 – 定义类别(Class) – 关于方法
  145. 145. 以对象思考问题 • 有一个帐户,帐户中有存款余额,您可以 对帐户进行存款与提款的动作,并可以查 询以取得存款余额。 – 识别问题中的对象与属性 – 识别对象上的方法
  146. 146. 以对象思考问题
  147. 147. 使用class定义类别 • 在Java中使用"class"关键词来定义类别 public class Account { 定义类别 private String accountNumber; privatedouble balance; public Account(){ 定义建构方法 this("empty", 0.0); } public Account(String accountNumber, double balance) { this.accountNumber = accountNumber; this.balance = balance; } …
  148. 148. 使用class定义类别 • 在Java中使用"class"关键词来定义类别 … publicString getAccountNumber() { return accountNumber; } publicdouble getBalance() { return balance; } publicvoid deposit(double money) { 定义成员 balance += money; } publicdouble withdraw(double money) { balance -= money; return money; } }
  149. 149. 使用class定义类别 • 可根据类别来建构对象 Account account1= newAccount(); Account account2 =newAccount("123-4567", 100.0); • 要透过公开成员来操作对象或取得对象信 息的话,可以在对象名称后加上「.」运算 符来进行 account1.getBalance(); account1.deposit(1000.0);
  150. 150. 使用class定义类别 Account account = new Account(); System.out.println("帐戶: " + account.getAccountNumber()); System.out.println("余額: " + account.getBalance()); account = new Account("123-4567", 100.0); account.deposit(1000.0); System.out.println("帐戶: " + account.getAccountNumber()); System.out.println("余額: " + account.getBalance());
  151. 151. 类别成员(Classmember) • 类别成员可用的访问权限修饰词有 “public”、“protected”、“private”三个 • 在宣告成员时不使用存取修饰词,则预设 以「套件」(package)为存取范围
  152. 152. 类别成员(Classmember) • 数据成员被宣告为“private”,表示它是 「私 用成员」(Privatemember),私用成员只 能在类别中被使用 • 方法被宣告为"public",表示这些方法可以 藉由对象的参考名称加上"."直接呼叫 存取修饰 传回值型态 方法名称(参数列) { //实作 return传回值; }
  153. 153. 类别成员(Classmember) • 方法区块中可以宣告变量(Variable),参 数在方法区块执行结束后就会自动清除 • 方法中的相同变量名称会暂时覆盖数据成 员的作用范围 • 可以使用"this"关键词来特别指定
  154. 154. 类别成员(Classmember) class MethodDemo { private int data = 10; public void scopeDemo() { // void表示没有传回值 int data = 100; } public int getData() { return data; } public void setData(int data) { // void表示没有传回值 data = data; //这样写是没用的 //写下面这个才有用 // this.data = data; } }
  155. 155. 类别成员(Class member) • 信息的最小化 – 如果数据成员能不公开就不公开 • 透过公开方法存取私用成员的好处 – 如果存取私用成员的流程有所更动,只要在公 开方法中修改就可以了 public double withdraw(double money) { if(balance – money < 0) { return 0; } else { balance -= money; return money; } }
  156. 156. 建构方法(Constructor) • 建构方法是与类别名称相同的公开方法成 员,且没有传回值 public class SafeArray { // .. public SafeArray() { //建构方法 // .... } public SafeArray(参数列) {//建构方法 // .... } }
  157. 157. 建构方法(Constructor) public class SafeArray { private int[] arr; public SafeArray() { this(10); //预设10个元素 } public SafeArray(int length) { arr = new int[length]; } … }
  158. 158. 关于this 方法成员在内存中会只有一份
  159. 159. 关于this • 使用参考名称来呼叫对象的方法成员时, 程序会将对象的参考告知方法成员 • 在方法中所撰写的每一个数据成员其实会 隐含一个this参考名称 • this名称参考至呼叫方法的对象 public double getBalance() { return this.balance; }
  160. 160. 关于this • 在方法中使用数据成员时,都会隐含的使 用this名称 public Account(String accountNumber, double balance) { this.accountNumber = accountNumber; this.balance = balance; } public Account(String number, double money) { accountNumber = number; //实际等于this.accountNumber = number; this.balance = money; //实际等于this.balance = money; }
  161. 161. 关于this • this还有一种可以带自变量的用法,主要是 用于呼叫建构方法 public class Ball { private String name; public Ball() { this(“No name”); //会使用Ball(“No name”)来建构 } public Ball(String name) { this.name = name; .... } }
  162. 162. 关於static • 被宣告为“static”的数据成员,又称「静态 数据成员」 • 静态成员是属于类别所拥有,而不是个别 的对象 • 可以将静态成员视为每个对象实例所共享 的数据成员 public class Ball { public static double PI = 3.14159; //宣告static资料 ... }
  163. 163. 关于static • 属于类别所拥有,可以在不使用名称参考 下,直接使用类别名称加上‘.’运算符来存取 • 同样遵守“public”、“protected”与“private”的 存取限制 • 设定为“public”成员的话就可以如下存取 System.out.println("PI = " + Ball.PI); • 下面的方式是不被鼓励的 Ball ball = new Ball(); System.out.println("PI = " + ball.PI);
  164. 164. 关于static • 可以宣告方法成员为"static"方法,又称 「静态方法」 public class Ball { ... public static double toRadian(double angle) { return 3.14159 / 180 * angle; } } System.out.println("角度90等于径度" + Ball.toRadian (90));
  165. 165. 关于static • 静态方法中不会有this参考名称 • 静态方法中不允许使用非静态成员 non-static variable test cannot be referenced from a static context • 在静态方法中不能呼叫非静态方法 non-static method showHello() cannot be referenced from a static context
  166. 166. 关于static • 可以使用“static”定义一个静态区块,并在 当中撰写类别载入时的初始化动作 public class Ball { static { //一些初始化程序代码 } .... } • 在类别被加载时,默认会先执行静态区块 中的程序代码,且只会执行一次
  167. 167. 重载(Overload)方法 • 为类似功能的方法提供统一名称,可根据 参数列的不同而自动呼叫对应的方法 • String的valueOf()方法就提供了多个版本 static String valueOf(boolean b) static String valueOf(char c) static String valueOf(char[] data) static String valueOf(char[] data, int offset, int count) static String valueOf(double d) static String valueOf(float f) static String valueOf(int i) static String valueOf(long l) static String valueOf(Object obj)
  168. 168. 重载(Overload)方法 • 参数个数也可以用来设计方法重载 public class SomeClass { //以下重载了someMethod()方法 public void someMethod() { // ... } public void someMethod(int i) { // ... } public void someMethod(float f) { // ... } public void someMethod(int i, float f) { // ... } }
  169. 169. 重载(Overload)方法 • 返回值型态不可用作为方法重载的区别根 据,以下是不正确的 public class SomeClass { public int someMethod(int i) { // ... return 0; } public double someMethod(int i) { // ... return 0.0; } }
  170. 170. 重载(Overload)方法 • 注意到autoboxing、unboxing的问题 public static void main(String[] args) { someMethod(1); } public static void someMethod(int i) { System.out.println("int版本被呼叫"); } public static void someMethod(Integer integer) { System.out.println("Integer版本被呼叫"); }
  171. 171. 重载(Overload)方法 • 注意到autoboxing、unboxing的问题 – 找寻在还没有装箱动作前可以符合自变量个数 与型态的方法 – 尝试装箱动作后可符合自变量个数与型态的方 法 – 尝试设有「不定长度自变量」并可以符合的方 法 – 编译程序找不到合适的方法,回报编译错误
  172. 172. 不定长度自变量 • J2SE5.0之后开始支持「不定长度自变量」 (Variable-lengthArgument) public static int sum(int... nums) { //使用...宣告参数 int sum = 0; for(int num : nums) { sum += num; } return sum; } • 实际上nums是一个数组
  173. 173. 不定长度自变量 • 宣告的参数必须设定在参数列的最后一 个,下面的方式是合法的 public void someMethod(int arg1, int arg2, int... varargs) { // .... } • 下面的方式是不合法的 public void someMethod(int... varargs, int arg1, int arg2) { // .... }
  174. 174. 不定长度自变量 • 没办法使用两个以上的不定长度自变量, 下面的方式是不合法的 public void someMethod(int... varargs1, int... varargs2) { // .... } • 如果使用对象的不定长度自变量,宣告的 方法相同 public void someMethod(SomeClass... somes) { // .... }
  175. 175. 递归方法 • 在方法中呼叫自身同名方法,而呼叫者本 身会先被置入内存「堆栈」(Stack)中 • 堆栈是一种「先进后出」(First in, lastout)的数据结构 private static int gcd(int m, int n) { if(n == 0) return m; else return gcd(n, m % n); }
  176. 176. 垃圾收集 • Java提供垃圾收集机制 • 在适当的时候,Java执行环境会自动检查 对象,看看是否有未被参考的对象 • 如果有的话就清除对象、回收对象所占据 的内存空间 • 在程序执行的空闲时候,您可以建议执行 环境进行垃圾收集,但也仅止于建议
  177. 177. 垃圾收集 • finalize()会在对象被回收时执行 • 因为不知道对象资源何时被回收,所以也 就不知道finalize()真正被执行的时间
  178. 178. 垃圾收集 public class GcTest { private String name; public GcTest(String name) { this.name = name; System.out.println(name + "建立"); } //对象回收前执行 protected void finalize() { System.out.println(name + "被回收"); } }.
  179. 179. 垃圾收集 System.out.println("请按Ctrl +C终止程式........"); GcTest obj1 = new GcTest("object1"); GcTest obj2 = new GcTest("object2"); GcTest obj3 = new GcTest("object3"); //令名称不参考至对象 obj1 = null; obj2 = null; obj3 = null; //建议回收对象 System.gc(); while(true); //不断执行程序
  180. 180. 第8章 • 继承、多型 – 继承 – 多型
  181. 181. 扩充(extends)父类别 • 使用"extends"作为其扩充父类别的关键词 public class Bird { private String name; public Bird() { } public Bird(String name) { this.name = name; } public void walk() { System.out.println("走路"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
  182. 182. 扩充(extends)父类别 public class Chickenextends Bird { //扩充Bird类别 private String crest; //新增私有成员,鸡冠描述 public Chicken() {super(); } //定义建构方法 public Chicken(String name, String crest) { super(name); this.crest = crest; } //新增方法 public void setCrest(String crest) { this.crest = crest; } public String getCrest() { return crest; } public void wu() { System.out.println("咕咕叫…"); } }
  183. 183. 扩充(extends)父类别 Chicken chicken1 = new Chicken("小克","红色小鸡冠"); Chicken chicken2 = new Chicken(); System.out.printf("小雞1 -名称%s,鸡冠是%s。n", chicken1.getName(), chicken1.getCrest()); chicken1.wu(); System.out.printf("小雞2 -名称%s,鸡冠是%s。n", chicken2.getName(), chicken2.getCrest()); chicken2.wu();
  184. 184. 被保护的(protected)成员 • 保护意思表示存取该成员是有条件限制的 • 继承的类别就可以直接使用这些成员,但 这些成员仍然受到保护 • 不同套件(package)的对象不可直接呼叫 使用protected成员
  185. 185. 被保护的(protected)成员 public class Rectangle { //受保护的member protected int x; protected int y; protected int width; protected int height; … } public class CubicextendsRectangle { … public int getVolumn() { //可以直接使用父类别中的width、height成员 return length*width*height; } }
  186. 186. 重新定义(Override)方法 • 如果父类别中的定义并不符合您的需求, 可以在扩充类别的同时重新定义 • 可以重新定义方法的实作内容、成员的访 问权限,或是成员的返回值型态
  187. 187. 重新定义(Override)方法 public class SimpleArray { protected int[] array; public SimpleArray(int i) { array = new int[i]; } public void setElement(int i, int data) { array[i] = data; } .... } public class SafeArrayextends SimpleArray { … //重新定义setElement() public void setElement(int i, int data) { if(i < array.length) super.setElement(i, data); } .... }
  188. 188. 重新定义(Override)方法 • 实际运作的对象是SafeArray的实例,所以 被呼叫执行的会是SafeArray中重新定义过 的setElement()方法 SimpleArray simpleArray = new SafeArray(); simpleArray.setElement();
  189. 189. 重新定义(Override)方法 • 在衍生类别中想要呼叫基类的建构方法, 可以使用super()方法 • 要在衍生类别中呼叫基类方法,则可以如 使用super.methodName() • 条件限制 – 父类别中的方法或建构方法不能是"private", 也就是不能是私用成员
  190. 190. 重新定义(Override)方法 • 您可以增大父类别中的方法权限,但不可 以缩小父类别的方法权限 – 若原来成员是"public"的话,您不可以在父类别 中重新定义它为"private"或"protected" public class SafeArray extends SimpleArray { //不可以缩小父类别中同名方法的权限 private void setElement(int i, int data) { .... } } setElement(int,int) in SafeArray cannot override setElement(int,in t) in SimpleArray; attempting to assign weaker accessprivileges; was publicprivate void setElement(int i, int data) {^1 error
  191. 191. 重新定义(Override)方法 • 从J2SE5.0开始在重新定义方法时,您可以 重新定义返回值的型态 public class Bird { protected String name; public Bird(String name) { this.name = name; } public Bird getCopied { return new Bird(name); } }
  192. 192. 重新定义(Override)方法 • 重新定义的返回值型态必须是父类别中同一方法 返回型态的子类别 public class Chicken extends Bird { protected String crest; public Chicken(String name, String crest) { super(name); this.crest = crest; } //重新定义返回值型态为Chicken publicChicken getCopied() { return new Chicken(name, crest); } } • 无法重新定义static方法
  193. 193. Object类别 • Object是Java程序中所有类别的父类别 • 每个类别都直接或间接继承自Object类别 public class Foo { //实作 } public class Foo extends Object { //实作 }
  194. 194. toString()、equals()、hashCode() • toString()方法是对对象的文字描述 • Object的toString()预设会传回类别名称及 16进位制的编码 getClass().getName() + '@' + Integer.toHexString(hashCode()) • 预设的equals()本身是比较对象的内存地址 是否相同
  195. 195. toString()、equals()、hashCode() • 可以重新定义equals()方法,以定义您自己 的对象在什么条件下可视为相等的对象 • 在重新定义equals()方法时,建议同时重新 定义hashCode()方法
  196. 196. toString()、equals()、hashCode() public boolean equals(Object other) { if (this == other) return true; if (!(other instanceof Cat)) return false; final Cat cat = (Cat) other; if (!getName().equals(cat.getName())) return false; if (!getBirthday().equals(cat.getBirthday())) return false; return true; } public int hashCode() { int result = getName().hashCode(); result = 29 * result + getBirthday().hashCode(); return result; }
  197. 197. clone()方法 • 如何复制对象本身 • 最基本的作法:实作java.lang.Cloneable界 面(Interface) public class PointimplementsCloneable { //要实作Cloneable … public Object clone() throws CloneNotSupportedException { //呼叫父类别的clone()来进行复制 return super.clone(); } }
  198. 198. clone()方法 public class TableimplementsCloneable { //要实作Cloneable private Point center; // … public Object clone () throws CloneNotSupportedException { //呼叫父类的clone()来复制 Table table = (Table) super.clone(); if(this.center != null) { //复制Point类型的数据成员 table.center = (Point) center.clone(); } return table; } }
  199. 199. clone()方法 Table table = new Table(); table.setCenter(new Point(2, 3)); Point originalCenter = table.getCenter(); Table clonedTable = (Table) table.clone(); Point clonedCenter = clonedTable.getCenter(); System.out.printf("原来的Table中心:(%d, %d)n", originalCenter.getX(), originalCenter.getY()); System.out.printf("复制的Table中心:(%d, %d)n", clonedCenter.getX(), clonedCenter.getY()); clonedCenter.setX(10); clonedCenter.setY(10); //改变复制品的内容,对原来的对象不会有影响 System.out.printf("原来的Table中心:(%d, %d)n", originalCenter.getX(), originalCenter.getY()); System.out.printf("复制的Table中心:(%d, %d)n", clonedCenter.getX(), clonedCenter.getY());
  200. 200. final关键词 • “final”关键词使用在变量宣告时,表示该变 量设定之后,就不可以再改变该变量的值 final double PI = 3.14159; • 如果在定义方法成员时使用"final",表示该 方法成员在无法被子类别重新定义 public class Ball { private double radius; publicfinal double getRadius() { return radius; } // .... }
  201. 201. final关键词 • 如果您在宣告类别时加上final关键词,则表 示要终止被扩充 publicfinal class Ball { // .... }
  202. 202. 多型导论 • 如果使用不正确类别型态转换对象操作接 口,会发生java.lang.ClassCastException
  203. 203. 多型导论 • 定义了两个execute()方法来分别操作 Class1与Class2的实例 public void execute(Class1 c1) { c1.doSomething(); } public void execute(Class2 c2) { c2.doSomething(); } • execute()分别依赖了Class1与Class2两个 类别
  204. 204. 多型导论 • 将程序中的execute()改成 public void execute(ParentClass c) { c.doSomething(); } • 只依赖ParentClass,程序对个别对象的依 赖程序降低了,日后在修改、维护或调整 程序时的弹性也增加了
  205. 205. 多型导论 • 实际上在设计并不依赖于具体类别,而是 依赖于抽象 • Java中在实现多型时,可以让程序依赖于 「抽象类」(Abstractclass)或是「接口」 (Interface)
  206. 206. 抽象类(Abstract class) public class ConcreteCircle { private double radius; public void setRedius(int radius) { this.radius = radius; } public double getRadius() { return radius; } public void render() { System.out.printf("画一个半径%f的实心圆n", getRadius()); } } public class HollowCircle { private double radius; public void setRedius(int radius) { this.radius = radius; } public double getRadius() { return radius; } public void render() { System.out.printf("画一个半径%f的空心圆n", getRadius()); } }
  207. 207. 抽象类(Abstractclass) • 要宣告抽象方法与抽象类,您要使用 "abstract"关键词 publicabstract class AbstractCircle { protected double radius; public void setRedius(int radius) { this.radius = radius; } public double getRadius() { return radius; } public abstract void render(); }
  208. 208. 抽象类(Abstract class) public class ConcreteCircle extends AbstractCircle { public ConcreteCircle() {} public ConcreteCircle(double radius) { this.radius = radius; } public void render() { System.out.printf("画一个半径%f的实心圆n", getRadius()); } } public class HollowCircle extends AbstractCircle { public HollowCircle() {} public HollowCircle(double radius) { this.radius = radius; } public void render() { System.out.printf("画一个半径%f的空心圆n", getRadius()); } }
  209. 209. 抽象类(Abstract class) public class CircleDemo { public static void main(String[] args) { renderCircle(new ConcreteCircle(3.33)); renderCircle(new HollowCircle(10.2)); } public static void renderCircle(AbstractCircle circle) { circle.render(); } }
  210. 210. 抽象类应用 publicabstract class AbstractGuessGame { … public void start() { showMessage("欢迎"); int guess = 0; do { guess =getUserInput(); if(guess > number) { showMessage("输入的数字较大"); } else if(guess < number) { showMessage("输入的数字较小"); } else { showMessage("猜中了"); } } while(guess != number); } protectedabstractvoid showMessage(String message); protectedabstract int getUserInput(); }
  211. 211. 抽象类应用 public class TextModeGameextends AbstractGuessGame { private Scanner scanner; public TextModeGame() { scanner = new Scanner(System.in); } protected void showMessage(String message) { for(int i = 0; i < message.length()*2; i++) { System.out.print("*"); } System.out.println("n"+ message); for(int i = 0; i < message.length()*2; i++) { System.out.print("*"); } } protected int getUserInput() { System.out.print("n输入数字:"); return scanner.nextInt(); } }
  212. 212. 抽象类应用 • 藉由在抽象类中先定义好程序的执行流 程,并将某些相依方法留待子类别中执行 AbstractGuessGame guessGame = new TextModeGame(); guessGame.setNumber(50); guessGame.start();
  213. 213. 界面(Interface) • 继承某抽象类的类别必定是该抽象类的一 个子类 • 实作某接口的类别并不被归属于哪一类 – 一个对象上可以实作多个接口 • 接口的宣告是使用"interface"关键词 [public] interface接口名称{ 权限设定 传回型态 方法(参数列); 权限设定 传回型态 方法(参数列); // .... }
  214. 214. 界面(Interface) • 在宣告接口时方法上的权限设定可以省 略,如果省略的话,预设是"public public interface IRequest { public void execute(); }
  215. 215. 界面(Interface) public class HelloRequestimplements IRequest { private String name; public HelloRequest(String name) { this.name = name; } public void execute() { System.out.printf("哈啰%s!%n", name); } } public class WelcomeRequestimplements IRequest { private String place; public WelcomeRequest(String place) { this.place = place; } public void execute() { System.out.printf("欢迎来到%s!%n", place); } }
  216. 216. 界面(Interface) public static void main(String[] args) { for(int i = 0; i < 10; i++) { int n = (int) (Math.random() * 10) % 2; //随机产生 switch (n) { case 0: doRequest(new HelloRequest("良葛格")); break; case 1: doRequest(new WelcomeRequest("Wiki网站")); } } } public static voiddoRequest(IRequestrequest) { request.execute(); }
  217. 217. 界面(Interface) • 在Java中您可以一次实作多个接口 public class类别名称implements界面1,界面2,界面3 { //界面实作 } • 必要时必须作「接口转换」,如此程序才 知道如何正确的操作对象 ISomeInterface1 obj1 = (ISomeInterface1) someObject; obj1.doSomeMethodOfISomeInterface1(); ISomeInterface2 obj2 = (ISomeInterface2) someObject;obj2.doSomeMethodOfISomeInterface2();
  218. 218. 界面(Interface) • 接口也可以进行继承的动作,同样也是使 用“extends”关键词来继承父接口 public interface名称extends界面1,界面2 { // ... } • 一个接口可以同时继承多个父接口,实作 子接口的类别必须将所有在父接口和子接 口中定义的方法实作出来
  219. 219. 第9章 • 管理类别档案 – 内部类别 – package与import
  220. 220. 成员内部类别、区域内部类别 • 成员内部类别,基本上是在一个类别中直 接宣告另一个类别 public class OuterClass { //内部类别 private class InnerClass { // .... } } • 所产生的文件名为「外部类别名称$内部类 别名称.class」
  221. 221. 成员内部类别、区域内部类别 • 区域内部类别定义于一个方法中,类别的 可视范围与生成之对象仅止于该方法之中 • 内部类别还可以被宣告为"static“ • 由于是“static”,它不能存取外部类别的方 法,而必须透过外部类别所生成的对象来 进行呼叫
  222. 222. 成员内部类别、区域内部类别 • 被宣告为static的内部类别,事实上也可以 看作是另一种名称空间的管理方式 public class Outer { public static class Inner { .... } .... } Outer.Inner inner = new Outer.Inner();
  223. 223. 匿名内部类别 • 内部匿名类别可以是继承某个类别或是实 作某个接口 new[类别或接口()] { //实作 } Object obj = new Object() { public String toString() { //重新定义toString() return"匿名类别物件"; } }; System.out.println(obj);
  224. 224. 匿名内部类别 • 注意如果要在内部匿名类别中使用外部的 局部变量,变量在宣告时必须為"final" .... public void someMethod() { finalint x = 10; //宣告final Object obj = new Object() { public String toString() { return String.valueOf(x); //x可在匿名类别中使用 } }; System.out.println(obj); } ....
  225. 225. 匿名内部类别 • 局部变量x并不是真正被拿来于内部匿名类 别中使用 • x会被匿名类别复制作为数据成员来使用 • 编译程序会要求您加上“final”关键词,这样 您就知道不能在内部匿名类别中改变x的值 • 内部匿名类别在编译完成之后会产生「外 部类别名称$编号.class」,编号为1、2、 3...n,每个编号n的档案对应于第n个匿名 类别
  226. 226. 设定套件(package) • 套件被设计与文件系统结构相对应 • 为了要能建立与套件相对应的文件系统结 构,您在编译时可以加入"-d"参数,并指定 产生的类别档案要储存在哪一个目录之下 package onlyfun.caterpillar; public class PackageDemo { public static void main(String[] args) { System.out.println("Hello! World!"); } }
  227. 227. 设定套件(package) • javac -d . UsePackage.java • 在目前的工作位置中会出现onlyfun目录, 之下会有个caterpillar目录,而当中有個 PackageDemo.class档案 • “package”的设定会成为类别名称的一部份 – 完整类别名onlyfun.caterpillar.PackageDemo – java onlyfun.caterpillar.PackageDemo
  228. 228. 设定套件(package) • 「完全描述」(Fullyqualified)名称 – 完整的指出「套件加类别」名称 onlyfun.caterpillar.Point2D p1 = new onlyfun.caterpillar.Point2D(10, 20); • 最后编译完成的.class档案必须放在onlyfun 目录的caterpillar目录下 bad class file: .Point2D.classclass file contains wrong class: onlyfun.caterpillar.Point2DPlease remove or make sure it appears in the correct subdirectory of the classpath. Point2D p1 = new Point2D(10, 20); ^1 error
  229. 229. import的意义 • 您可以使用"import"关键词,告知编译程序 您所要使用的类别是位于哪一个套件 import onlyfun.caterpillar.Point2D; public class Point2DDemo2 { public static void main(String[] args) { Point2D p1 = new Point2D(10, 20); System.out.printf("p1: (x, y) = (%d, %d)%n", p1.getX(), p1.getY()); } }
  230. 230. import的意义 • 使用"import"指定时,可于套件指定加上'*' import onlyfun.caterpillar.*; public class Point2DDemo3 { public static void main(String[] args) { Point2D p1 = new Point2D(10, 20); System.out.printf("p1: (x, y) = (%d, %d)%n", p1.getX(), p1.getY()); } }
  231. 231. import的意义 • 可能出现以下的错误讯息 bad class file: .Point2D.java file does not contain class Point2D Please remove or make sure it appears in the correct subdirectory of the classpath. • 将原始码与编译完成的档案放在一起并不 是一个好的管理方式 javac -d ./classes ./src/*.java • 指定Classpath的方式如下执行程序 java -cp ./classes Point2DDemo3
  232. 232. import的意义 • 同名冲突 import java.util.Arrays; import onlyfun.caterpillar.Arrays; public class SomeClass { .... } java.util.Arrays is already defined in a single-type import import onlyfun.caterpillar.Arrays; ^1 error
  233. 233. public与套件 • 没有被宣告为“public”的类别只能被同一个套件中 的类别之实例呼叫使用 Point2DDemo.java:3: onlyfun.caterpillar.Point2D is not public in onlyfun.caterpillar; cannot be accessed from outside package onlyfun.caterpillar.Point2D p1 = new • 类别成员也可以宣告为"public",宣告为"public" 的类别成员可以被其它对象呼叫使用 • 如果宣告类别时不使用"public"、"protected"或 "private"设定权限,则预设为「套件存取范围」
  234. 234. public与套件 Point2DDemo.java:7: getX() is not public in onlyfun.caterpillar.Point2D; cannot be accessed from outside package p1.getX(), p1.getY()); ^
  235. 235. public与套件 • 类别上的权限设定会约束类别成员上的权 限设定 package onlyfun.caterpillar; class SomeClass { // ... public void someMethod() { // .... } } • 效果等同于 package onlyfun.caterpillar; class SomeClass { // ... void someMethod() { // .... } }
  236. 236. public与套件 • 定义一个类别,但没有定义建构方法时, 编译程序会自动帮您产生一个预设建构方 法 package onlyfun.caterpillar; public class Test { .... } package onlyfun.caterpillar; public class Test { public Test() { } .... }
  237. 237. public与套件 • 如果您自行定义建构方法,则编译程序就 不会帮您加上预设建构方法 package onlyfun.caterpillar; public class Test { public Test(int i) { ... } .... } • 在建构时,就必须指明使用哪个建构方法
  238. 238. public与套件 • 建议即使没有用到,在定义自己的建构方法的同 时,也加上个没有参数的建构方法 package onlyfun.caterpillar; public class Test { public Test() { //即使没用到,也先建立一个空的建构方法 } public Test(int i) { ... } .... } • 没有使用super()指定要使用父类别的哪个建构方 法,则预设会寻找父类别中无参数的建构方法
  239. 239. public与套件 • 预设建构方法的访问权限是跟随着类别的 访问权限而设定 package onlyfun.caterpillar; public class Test {} • 由于类别宣告为public,所以预设建构方法 访问权限為public
  240. 240. public与套件 • 如果是以下的话 package onlyfun.caterpillar; class Test {} • 则预设建构方法访问权限为套件访问权 限,也就是编译程序会自动为您扩展为 package onlyfun.caterpillar; class Test { Test() { } }
  241. 241. public与套件 存取修饰 同一类别 同一套件 子类别 全局 private OK (default) OK OK protected OK OK OK public OK OK OK OK
  242. 242. import静态成员 import static java.lang.System.out; public class HelloWorld { public static void main(String[] args) { out.println("Hello! World!"); } } import static java.lang.System.out; import static java.util.Arrays.sort; public class ImportStaticDemo { public static void main(String[] args) { int[] array = {2, 5, 3, 1, 7, 6, 8}; sort(array); for(int i : array) { out.print(i + " "); } } }
  243. 243. import静态成员 • 如果您想要“import”类别下所有的静态成 员,也可以使用 ‘*’ 字符 import static java.util.Arrays.*; • 对于名称冲突编译程序可能透过以下的几 个方法来解决 – 成员覆盖 – 局部变量覆盖 – 重载(Overload)方法上的比对
  244. 244. 第10章 • 例外处理 – 例外处理入门 – 受检、执行时期例外 – throw、throws – 例外的继承架构
  245. 245. 例外处理入门 • 想尝试捕捉例外,可以使用"try"、"catch"、 "finally"三个关键词组合的语法来达到 try { //陈述句 } catch(例外型态 名称) { //例外处理 } finally { //一定会处理的区块 }
  246. 246. 例外处理入门 public class CheckArgsDemo { public static void main(String[] args) { try { System.out.printf("执行%s功能%n", args[0]); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("没有指定自变量"); e.printStackTrace(); } } }
  247. 247. 例外处理入门 • 例外处理最好只用于错误处理,而不应是 用于程序业务逻辑的一部份,因为例外的 产生要消耗资源
  248. 248. 例外处理入门 • 以下应用例外处理的方式就不适当 while(true) { try { System.out.println(args[i]); i++; } catch(ArrayIndexOutOfBoundsException e) { // .... } } • 下面的方式才是正确的 for(int i = 0; i < args.length; i++) { System.out.println(args[i]); }
  249. 249. 受检例外、执行时期例外 • 在某些情况下例外的发生是可预期的 – 例如使用输入输出功能 • 错误是可预期发生的这类例外称之为「受 检例外」(Checked Exception) • 受检例外编译程序会要求您进行例外处理 – 在使用java.io.BufferedReader的readLine()方 法取得使用者输入时,编译程序会要求您于程 序代码中明确告知如何处理 java.io.IOException
  250. 250. 受检例外、执行时期例外 • 如果您不在程序中处理的话,例如将 IOException的"catch"区块拿掉 CheckedExceptionDemo.java:9: unreported exception java.io.IOException; must be caught or declared to be thrown
  251. 251. 受检例外、执行时期例外 try { BufferedReader buf = new BufferedReader( new InputStreamReader(System.in)); System.out.print("请输入整數: "); int input = Integer.parseInt(buf.readLine()); System.out.println("input x 10 = " + (input*10)); } catch(IOException e) { // Checked Exception System.out.println("I/O错誤"); } catch(NumberFormatException e) { // Runtime Exception System.out.println("输入必须为整數"); }
  252. 252. 受检例外、执行时期例外 • 像NumberFortmatException例外是「执行 时期例外」(Runtime exception) • 例外是发生在程序执行期间,并不一定可 预期它的发生,编译程序不要求您一定要 处理 • 对于执行时期例外若没有处理,则例外会 一直往外丢,最后由JVM来处理例外, JVM所作的就是显示例外堆栈讯息
  253. 253. throw、throws • 想要自行丢出例外,可以使用"throw"关键 词,并生成指定的例外对象 try { double data = 100 / 0.0; System.out.println("浮点数零除:" + data); if(String.valueOf(data).equals("Infinity")) throw new ArithmeticException("除零例外"); } catch(ArithmeticException e) { System.out.println(e); }
  254. 254. • 在巢状的try...catch结构时,必须注意该例 外是由何者引发并由何者捕捉 try { try { throw new ArrayIndexOutOfBoundsException(); } catch(ArrayIndexOutOfBoundsException e) { …. } throw new ArithmeticException(); } catch(ArithmeticException e) { …. } catch(ArrayIndexOutOfBoundsException e) { …. }
  255. 255. throw、throws • 在方法中会有例外的发生,而您并不想在 方法中直接处理,而想要由呼叫方法的呼 叫者来处理 – 使用“throws”关键词 – java.ioBufferedReader的readLine()方法就声 明会丢出java.io.IOException private void someMethod(int[] arr) throws ArrayIndexOutOfBoundsException, ArithmeticException { //实作 }
  256. 256. 例外的继承架构 Throwable 继承自 Error Throwable LinkageError 严重的系统错 ThreadDeath 误,不用处理也 VirtualMachineError 无法处理 .... 继承自 Exception Throwable ClassNotFoundException CloneNotSupportedException Checkedexceptio IllegalAccessException n,编译程序要求 .... 您要处理 RuntimeException Uncheckedexcep ArithmeticException tion,编译程序不 ArrayStoreException 要求您要处理 ClassCastException ....
  257. 257. 例外的继承架构 • Throwable类别拥有几个取得相关例外讯息的方 法。 – getLocalizedMessage() • 取得例外对象的区域化讯息描述 – getMessage() • 取得例外对象的讯息描述 – printStackTrace() • 显示例外的堆栈讯息,这个方法在追踪例外发生的根源时相当 的有用,简单的说若A方法中呼叫了B方法,而B方法中呼叫了 C方法,C方法产生了例外,则在处理这个例外时呼叫 printStackTrace()可以得知整个方法呼叫的过程,由此得知例 外是如何被层层丢出的。
  258. 258. 例外的继承架构 • 了解例外处理的继承架构是必要的 • 如果父类别例外对象在子类别例外对象之 前被捕捉,则“catch”子类别例外对象的区 块将永远不会被执行 • 编译程序也会帮您检查这个错误
  259. 259. 例外的继承架构 try { throw new ArithmeticException("例外测試"); } catch(Exceptione) { System.out.println(e.toString()); } catch(ArithmeticException e) { System.out.println(e.toString()); }
  260. 260. 例外的继承架构 try { throw new ArithmeticException("例外测試"); } catch(ArithmeticException e) { System.out.println(e.toString()); } catch(Exception e) { System.out.println(e.toString()); }
  261. 261. 第11章 • 列举型态 – 常数设置与列举型态 – 定义列举型态
  262. 262. 常数设置 • 可使用接口来定义操作时所需的共享常数 public interface ActionConstants { public static final int TURN_LEFT = 1; public static final int TURN_RIGHT = 2; public static final int SHOT = 3; }
  263. 263. 常数设置 public void someMethod() { .... doAction(ActionConstants.TURN_RIGHT); .... } public void doAction(int action) { switch(action) { case ActionConstants.TURN_LEFT: System.out.println("向左转"); break; case ActionConstants.TURN_RIGHT: System.out.println("向右转"); break; case ActionConstants.SHOOT: System.out.println("射击"); break; } }
  264. 264. 常数设置 • 使用类别来宣告的话 public class CommandTool { public static final String ADMIN = "onlyfun.caterpillar.admin"; public static final String DEVELOPER = "onlyfun.caterpillar.developer"; public void someMethod() { // .... } } • 如果常数只是在类别内部使用的话,就宣 告其为“private”或是“protected”就可以了 – 宣告为类别外可取用的常数,通常是与类别功 能相依的常数
  265. 265. 列举型态入门 • 要定义列举型态是使用“enum”关键词 public enum Action { TURN_LEFT, TURN_RIGHT, SHOOT } • 列举型态骨子里就是一个类别,所以您编 译完成后,会产生一个Action.class档案

×