Mais conteúdo relacionado Semelhante a Java Jdk6学习笔记[Ppt] (20) Java Jdk6学习笔记[Ppt]3. 什么是Java
• Java是面向对象(Object-Oriented)程序
语言,具有更高的跨平台可能性
• 在今日,更多时候代表了软件开发的架构
• 开发者版本发表时是以Java
DevelopmentKits名称发表,简称JDK
• J2SE 5.0(Java 2 Platform Standard
Edition5.0)时的JDK称为J2SE
Development Kit 5.0
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. Java的特性
• 语言特性
– 简单(Simple)
– 面向对象(Object-oriented)
– 网络(Network-savvy)
– 解译(Interpreted)
– 坚固(Robust)
– 安全(Secure)
– 可携(Portable)
– 高效能(High-performance)
6. Java的特性
• 应用平台
– Java SE
• Java Platform, Standard Edition
– Java EE
• Java Platform, Enterprise Edition
– Java ME
• Java Platform, Micro Edition
8. Java Platform, Standard Edition
(Java SE)
• JVM
– Java虚拟机(Java Virtual Machine,JVM)
• JRE
– Java执行环境(Java SE Runtime
Environment,JRE)
• JDK
• Java语言
9. Java Platform, Enterprise Edition
(Java EE)
• 以JavaSE的基础,定义了一系列的服务、
API、协定等
• 适用于开发分布式、多层式(Multi-
tiered)、以组件为基础、以Web为基础的
应用程序
• 技术像是JSP、Servlet、Enterprise
JavaBeans(EJB)、Java Remote
Method Invocation(RMI)等
10. Java Platform, Micro Edition
(Java ME)
• 作为小型数字设备上开发及部署应用程序
的平台,像是消费性电子产品或嵌入式系
统等
• 最为人所熟悉的设备如手机、PDA、股票
机等
11. 活跃的社群与丰富的资源
• 开发工具
• 开放原始码的组件
• 容器
• 测试工具
• 各式各样的软件专案
• 各个社群所支持的讨论区
• 取之不尽的文件
13. 如何学习Java
• 使用搜索引擎
– http://www.google.com/
• 加入社群参与讨论
– http://www.javaworld.com.tw/
• 学习地图
– http://java.sun.com/developer/onlineTraining/n
ew2java/javamap/intro.html
14. 第2章
• 入门准备
– 下载、安装、瞭解JDK
– 设定Path与Classpath
– 第一个Java程序
– 选择开发工具
19. 了解JDK
JDK的JRE有server选项
20. 了解JDK
• JDK的安装目录
– 「bin」目录
• JDK的工具程序
– 「demo」目录
• 范例程序
– 「jre」目录
• JDK自己附带的JRE
– 「db」目录
• ApacheDerby数据库,纯Java所撰写的数据库
21. 了解JDK
• JDK的安装目录
– 「lib」目录
• 工具程序实际上会使用的Java工具类别
– JDK中的工具程序,大多也是由Java所撰写而
成
– bin文件夹下的工具程序,不过是个包装器
(Wrapper)
– 执行javac.exe等程序时,最后会呼叫lib目录中
tools.jar中的对应类别
24. 设定Path
• 必须告诉操作系统,应该到哪些目录下尝
试找到您所想使用的工具程序
– 直接设定目前的环境变量包括Path变数
set Path= C:Program FilesJavajdk1.6.0bin;%Path%
• Windows下安装JRE时,会将java.exe复制
至「C:WindowsSystem32」路径之下,
而这个路径在Path变量中是默认的路径
26. 设定Classpath
• JDK6默认会到现行工作目录,以及JDK的
「lib」目录中寻找Java程序
• javac -classpath classpath1;classpath2 …
• 对于Windows操作系统来说,Path是让操
作系统可以找到“.exe”执行档的存在
• 对于Java执行环境来说,ClassPath就是让
JVM可以找到".class"执行档的存在
29. 第一个Java程序
• Java的源文件必须以扩展名.java作结束
• 主档名与类别名称必须一致
• 注意每个字母的大小写
• 空白只能是半型空格符或是Tab字符
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
– 类别名称与主档名不符
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. 选择开发工具
• 从简单的文字编辑辅助工具开始
– 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/)
35. 第一个Java程序
• 定义类别(Class)
• 定义区块(Block)
• 定义main()方法(Method)
• 撰写陈述(Statement)
public class HelloJava {
public static void main(String[] args) {
System.out.println("嗨!我的第一个Java程序!");
}
}
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. 为程序加入批注
• 原始码档案中被标注为批注的文字,编译
程序不会去处理它
/*作者:良葛格 * 功能:示范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);
}
}
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. 使用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. 标准输入输出串流
• System类别中的静态物件out
– 提供标准输出串流(Stream)输出
– 通常对应至显示输出(终端机输出)
– 可以将输出重新导向至一个档案
– java HelloJava > HelloJavaResult.txt
• System标准输入串流in
– 在程序开始之后它会自动开启,对应至键盘或
其它的输入来源
42. 标准输入输出串流
• 标准错误输出串流err
– 在程序执行后自动开启,将指定的字符串输出
至显示设备或其它指定的装置
– err会立即显示错误讯息
– err输出串流的讯息不会被重新导向
System.out.println("使用out输出讯息");
System.err.println("使用err输出讯息");
java ErrDemo > ErrDemoResult.txt
使用err输出讯息
43. 输出格式控制
控制字符 作用
反斜杠
' 单引号'
" 双引号"
uxxxx 以16进位数指定Unicode字符输出
xxx 以8进位数指定Unicode字符输出
b 倒退一个字符
f 换页
n 换行
r 游标移至行首
t 跳格(一个Tab键)
System.out.println("u0048u0065u006Cu006Cu006F");
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. 输出格式控制
• 可以在输出浮点数时指定精度
– System.out.printf("example:%.2f%n", 19.234);
– example:19.23
• 可以指定输出时,至少要预留的字符宽度
– System.out.printf("example:%6.2f%n", 19.234);
– example: 19.23
– 补上一个空白在前端
47. 基本的数据型态(Primitivetype)
• 整数
– 短整数(short)(占2个字节)
– 整数(int)(占4个字节)
– 长整数(long)(占8个字节)
• 字节
– 专门储存位数据
– 占一个字节
• 浮点数
– 浮点数(float)(占4个字节)
– 倍精度浮点数(double)(占8个字节)
48. 基本的数据型态(Primitivetype)
• 字符
– 采Unicode编码
– 前128个字符编码与ASCII编码兼容
– 每个字符数据型态占两个字节
– 可储存的字符范围由'u0000'到'uFFFF'
• 布尔数
– 占内存2个字节
– 可储存true与false两个数值
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. 变数、常数
• 在Java中要使用变量,必须先宣告变量名
称与数据型态
int age; //宣告一个整数变量
double scope; //宣告一个倍精度浮点数变量
• 使用int、float、double、char等关键词来宣
告变量名称并指定其数据型态
– 不可以使用数字作为开头
– 不可以使用一些特殊字符,像是*&^%之类
– 不可以與Java内定的关键词同名
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);
54. 算术运算
• 加(+)、减(-)、乘(*)、除(/)、余
除运算符(%)
– System.out.println(1 + 2 * 3);
– System.out.println(1+2+3 / 4);
– System.out.println((double)(1+2+3) / 4);
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. 算术运算
• 将精确度大的值指定给精确度小的变量
时,由于在精确度上会有遗失,编译程序
会认定这是一个错误
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
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. 比较、条件运算
• 条件运算符
条件式?成立传回值:失败传回值
System.out.println("该生是否及格? " +
(scoreOfStudent >= 60 ? '是' : '否'));
System.out.println("是否为奇數? " +
(number%2 != 0 ? '是' : '否'));
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. 逻辑、位运算
• 左移(<<)、右移(>>)、>>>运算符
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. 递增、递减运算
• 递增、递减运算符
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. 递增、递减运算
• 将递增或递减运算符撰写在变量之前或变
量之后
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. 递增、递减运算
指定运算符 范 例 结 果
+= 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. if条件式
• 语法 if(条件式)
陈述句一;
else
陈述句二;
• 复合陈述句 if(条件式) {
陈述句一;
陈述句二;
}
else {
陈述句三;
陈述句四;
}
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. if条件式
• if中再设定执行的条件
if(条件式一) {
陈述句一;
if(条件式二)
陈述句二;
陈述句三;
}
if(条件式一) { if(条件式一) {
陈述句一; 陈述句一;
//其它陈述句 //其它陈述句
} else } else if(条件式二)
if(条件式二) 陈述句二;
陈述句二;
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(不及格)");
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. 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. 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. 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. 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. 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);
}
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. 使用对象
• 字符串就是对象,是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. 使用对象
• 简单的用户登入程序
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 +
"您好,输入的登入数据有误,请重新输入!");
}
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));
86. 自动装箱、拆箱
Integer data1 = 10;
Integer data2 = 20;
//转为double值再除以3
System.out.println(data1.doubleValue() / 3);
//进行两个值的比较
System.out.println(data1.compareTo(data2));
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. 小心使用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. 小心使用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. 小心使用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");
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为数组对象的属性成员
95. 一维数组对象
数据型态 初始值
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char u0000
boolean false
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();
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. 二维数组对象
• 二维数组使用「名称」与「两个索引」来
指定存取数组中的元素
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];
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. 二维数组对象
• 使用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. 不规则数组
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. 进阶的数组操作
• 一维数组的参考名称之宣告
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. 进阶的数组操作
• 将同一个对象指定给两个参考名称
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();
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. 数组复制
• 使用循环作数组复制
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. 数组复制
• 使用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. Arrays类别
名 称 说 明
sort() 帮助您对指定的数组排序,所使用的是快速排序法
binarySearch() 让您对已排序的数组进行二元搜寻,如果找到指定的值就
传回该值所在的索引,否则就传回负值
fill() 当您配置一个数组之后,会依数据型态来给定默认值,例
如整数数组就初始为 0,您可以使用Arrays.fill()方法来将所
有的元素设定为指定的值
equals() 比较两个数组中的元素值是否全部相等,如果是将传回
true,否则传回 false
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. 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. 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. 对象数组
• 以下产生几个对象?
int[] arr = new int[3];
• 以下的宣告产生几个对象?
int[][] arr = new int[2][3];
• 以下产生几个对象?
Integer[] arr = new Integer[3];
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. String类别
• 将输入的字符串转换为整数、浮点数等
方 法 说 明
Byte.parseByte(字符串) 将字符串剖析为位
Short.parseShort(字符串) 将字符串剖析为short整数
Integer.parseInt(字符串) 将字符串剖析为int整数
Long.parseLong(字符串) 将字符串剖析为long整数
Float.parseFloat(字符串) 将字符串剖析为float浮点数
Double.parseDouble(字符串) 将字符串剖析为double浮点数
• 指定的字符串无法剖析为指定的数据型态数值,
则会发生NumberFormatException例外
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. 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("");
126. 不可变(immutable)字符串
• 对于一些可以共享的字符串对象,会先在
String池中查找是否存在相同的String内容
String str1 = "flyweight";
String str2 = "flyweight";
System.out.println(str1 == str2);
• 当您直接在程序中使用""来包括一个字符串
时,该字符串就会在String池中
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);
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));
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));
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. 分离字符串
• 使用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();
}
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. 使用正则表示式
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. 使用正则表示式
• 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. 使用正则表示式
• Greedy quantifiers
范 例 作 用
X? X可出现一次或完全没有
X* X可出现零次或多次
X+ X可出现一次或多次
X{n} X可出现n次
X{n,} X可出现至少n次
X{n, m} X可出现至少n次,但不超过m次
X? X可出现一次或完全没有
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. 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();
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. 使用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. 使用class定义类别
• 可根据类别来建构对象
Account account1= newAccount();
Account account2 =newAccount("123-4567", 100.0);
• 要透过公开成员来操作对象或取得对象信
息的话,可以在对象名称后加上「.」运算
符来进行
account1.getBalance();
account1.deposit(1000.0);
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());
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. 类别成员(Class member)
• 信息的最小化
– 如果数据成员能不公开就不公开
• 透过公开方法存取私用成员的好处
– 如果存取私用成员的流程有所更动,只要在公
开方法中修改就可以了
public double withdraw(double money) {
if(balance – money < 0) {
return 0;
}
else {
balance -= money;
return money;
}
}
159. 关于this
• 使用参考名称来呼叫对象的方法成员时,
程序会将对象的参考告知方法成员
• 在方法中所撰写的每一个数据成员其实会
隐含一个this参考名称
• this名称参考至呼叫方法的对象
public double getBalance() {
return this.balance;
}
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. 关于this
• this还有一种可以带自变量的用法,主要是
用于呼叫建构方法
public class Ball {
private String name;
public Ball() {
this(“No name”); //会使用Ball(“No name”)来建构
}
public Ball(String name) {
this.name = name;
....
}
}
162. 关於static
• 被宣告为“static”的数据成员,又称「静态
数据成员」
• 静态成员是属于类别所拥有,而不是个别
的对象
• 可以将静态成员视为每个对象实例所共享
的数据成员
public class Ball {
public static double PI = 3.14159; //宣告static资料
...
}
163. 关于static
• 属于类别所拥有,可以在不使用名称参考
下,直接使用类别名称加上‘.’运算符来存取
• 同样遵守“public”、“protected”与“private”的
存取限制
• 设定为“public”成员的话就可以如下存取
System.out.println("PI = " + Ball.PI);
• 下面的方式是不被鼓励的
Ball ball = new Ball();
System.out.println("PI = " + ball.PI);
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. 关于static
• 静态方法中不会有this参考名称
• 静态方法中不允许使用非静态成员
non-static variable test cannot be referenced from a static context
• 在静态方法中不能呼叫非静态方法
non-static method showHello() cannot be referenced from a static context
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. 重载(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. 重载(Overload)方法
• 返回值型态不可用作为方法重载的区别根
据,以下是不正确的
public class SomeClass {
public int someMethod(int i) {
// ...
return 0;
}
public double someMethod(int i) {
// ...
return 0.0;
}
}
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版本被呼叫");
}
172. 不定长度自变量
• J2SE5.0之后开始支持「不定长度自变量」
(Variable-lengthArgument)
public static int sum(int... nums) { //使用...宣告参数
int sum = 0;
for(int num : nums) {
sum += num;
}
return sum;
}
• 实际上nums是一个数组
173. 不定长度自变量
• 宣告的参数必须设定在参数列的最后一
个,下面的方式是合法的
public void someMethod(int arg1, int arg2, int... varargs) {
// ....
}
• 下面的方式是不合法的
public void someMethod(int... varargs, int arg1, int arg2) {
// ....
}
174. 不定长度自变量
• 没办法使用两个以上的不定长度自变量,
下面的方式是不合法的
public void someMethod(int... varargs1, int... varargs2) {
// ....
}
• 如果使用对象的不定长度自变量,宣告的
方法相同
public void someMethod(SomeClass... somes) {
// ....
}
175. 递归方法
• 在方法中呼叫自身同名方法,而呼叫者本
身会先被置入内存「堆栈」(Stack)中
• 堆栈是一种「先进后出」(First in,
lastout)的数据结构
private static int gcd(int m, int n) {
if(n == 0)
return m;
else
return gcd(n, m % n);
}
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 + "被回收");
}
}.
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. 扩充(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. 扩充(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();
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;
}
}
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);
}
....
}
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
193. 重新定义(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方法
197. 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;
}
199. 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;
}
}
200. 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());
201. final关键词
• “final”关键词使用在变量宣告时,表示该变
量设定之后,就不可以再改变该变量的值
final double PI = 3.14159;
• 如果在定义方法成员时使用"final",表示该
方法成员在无法被子类别重新定义
public class Ball {
private double radius;
publicfinal double getRadius() {
return radius;
}
// ....
}
204. 多型导论
• 定义了两个execute()方法来分别操作
Class1与Class2的实例
public void execute(Class1 c1) {
c1.doSomething();
}
public void execute(Class2 c2) {
c2.doSomething();
}
• execute()分别依赖了Class1与Class2两个
类别
207. 抽象类(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());
}
}
208. 抽象类(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();
}
209. 抽象类(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());
}
}
210. 抽象类(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();
}
}
211. 抽象类应用
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();
}
212. 抽象类应用
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();
}
}
213. 抽象类应用
• 藉由在抽象类中先定义好程序的执行流
程,并将某些相依方法留待子类别中执行
AbstractGuessGame guessGame = new TextModeGame();
guessGame.setNumber(50);
guessGame.start();
214. 界面(Interface)
• 继承某抽象类的类别必定是该抽象类的一
个子类
• 实作某接口的类别并不被归属于哪一类
– 一个对象上可以实作多个接口
• 接口的宣告是使用"interface"关键词
[public] interface接口名称{
权限设定 传回型态 方法(参数列);
权限设定 传回型态 方法(参数列);
// ....
}
216. 界面(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);
}
}
217. 界面(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();
}
218. 界面(Interface)
• 在Java中您可以一次实作多个接口
public class类别名称implements界面1,界面2,界面3 {
//界面实作
}
• 必要时必须作「接口转换」,如此程序才
知道如何正确的操作对象
ISomeInterface1 obj1 = (ISomeInterface1) someObject;
obj1.doSomeMethodOfISomeInterface1();
ISomeInterface2 obj2 = (ISomeInterface2)
someObject;obj2.doSomeMethodOfISomeInterface2();
224. 匿名内部类别
• 内部匿名类别可以是继承某个类别或是实
作某个接口
new[类别或接口()] {
//实作
}
Object obj =
new Object() {
public String toString() { //重新定义toString()
return"匿名类别物件";
}
};
System.out.println(obj);
225. 匿名内部类别
• 注意如果要在内部匿名类别中使用外部的
局部变量,变量在宣告时必须為"final"
....
public void someMethod() {
finalint x = 10; //宣告final
Object obj =
new Object() {
public String toString() {
return String.valueOf(x); //x可在匿名类别中使用
}
};
System.out.println(obj);
}
....
226. 匿名内部类别
• 局部变量x并不是真正被拿来于内部匿名类
别中使用
• x会被匿名类别复制作为数据成员来使用
• 编译程序会要求您加上“final”关键词,这样
您就知道不能在内部匿名类别中改变x的值
• 内部匿名类别在编译完成之后会产生「外
部类别名称$编号.class」,编号为1、2、
3...n,每个编号n的档案对应于第n个匿名
类别
228. 设定套件(package)
• javac -d . UsePackage.java
• 在目前的工作位置中会出现onlyfun目录,
之下会有个caterpillar目录,而当中有個
PackageDemo.class档案
• “package”的设定会成为类别名称的一部份
– 完整类别名onlyfun.caterpillar.PackageDemo
– java onlyfun.caterpillar.PackageDemo
229. 设定套件(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
230. 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());
}
}
231. 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());
}
}
232. 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
233. 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
234. 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"设定权限,则预设为「套件存取范围」
236. public与套件
• 类别上的权限设定会约束类别成员上的权
限设定 package onlyfun.caterpillar;
class SomeClass {
// ...
public void someMethod() {
// ....
}
}
• 效果等同于 package onlyfun.caterpillar;
class SomeClass {
// ...
void someMethod() {
// ....
}
}
237. public与套件
• 定义一个类别,但没有定义建构方法时,
编译程序会自动帮您产生一个预设建构方
法
package onlyfun.caterpillar;
public class Test {
....
}
package onlyfun.caterpillar;
public class Test {
public Test() {
}
....
}
238. public与套件
• 如果您自行定义建构方法,则编译程序就
不会帮您加上预设建构方法
package onlyfun.caterpillar;
public class Test {
public Test(int i) {
...
}
....
}
• 在建构时,就必须指明使用哪个建构方法
239. public与套件
• 建议即使没有用到,在定义自己的建构方法的同
时,也加上个没有参数的建构方法
package onlyfun.caterpillar;
public class Test {
public Test() { //即使没用到,也先建立一个空的建构方法
}
public Test(int i) {
...
}
....
}
• 没有使用super()指定要使用父类别的哪个建构方
法,则预设会寻找父类别中无参数的建构方法
241. public与套件
• 如果是以下的话
package onlyfun.caterpillar;
class Test {}
• 则预设建构方法访问权限为套件访问权
限,也就是编译程序会自动为您扩展为
package onlyfun.caterpillar;
class Test {
Test() { }
}
242. public与套件
存取修饰 同一类别 同一套件 子类别 全局
private OK
(default) OK OK
protected OK OK OK
public OK OK OK OK
243. 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 + " ");
}
}
}
247. 例外处理入门
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();
}
}
}
249. 例外处理入门
• 以下应用例外处理的方式就不适当
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]);
}
250. 受检例外、执行时期例外
• 在某些情况下例外的发生是可预期的
– 例如使用输入输出功能
• 错误是可预期发生的这类例外称之为「受
检例外」(Checked Exception)
• 受检例外编译程序会要求您进行例外处理
– 在使用java.io.BufferedReader的readLine()方
法取得使用者输入时,编译程序会要求您于程
序代码中明确告知如何处理
java.io.IOException
251. 受检例外、执行时期例外
• 如果您不在程序中处理的话,例如将
IOException的"catch"区块拿掉
CheckedExceptionDemo.java:9: unreported exception
java.io.IOException; must be caught or declared to be
thrown
252. 受检例外、执行时期例外
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("输入必须为整數");
}
254. 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);
}
255. • 在巢状的try...catch结构时,必须注意该例
外是由何者引发并由何者捕捉
try {
try {
throw new ArrayIndexOutOfBoundsException();
}
catch(ArrayIndexOutOfBoundsException e) {
….
}
throw new ArithmeticException();
}
catch(ArithmeticException e) {
….
}
catch(ArrayIndexOutOfBoundsException e) {
….
}
256. throw、throws
• 在方法中会有例外的发生,而您并不想在
方法中直接处理,而想要由呼叫方法的呼
叫者来处理
– 使用“throws”关键词
– java.ioBufferedReader的readLine()方法就声
明会丢出java.io.IOException
private void someMethod(int[] arr) throws
ArrayIndexOutOfBoundsException,
ArithmeticException {
//实作
}
257. 例外的继承架构
Throwable 继承自
Error Throwable
LinkageError
严重的系统错 ThreadDeath
误,不用处理也 VirtualMachineError
无法处理
.... 继承自
Exception Throwable
ClassNotFoundException
CloneNotSupportedException
Checkedexceptio IllegalAccessException
n,编译程序要求 ....
您要处理
RuntimeException
Uncheckedexcep
ArithmeticException tion,编译程序不
ArrayStoreException 要求您要处理
ClassCastException
....
258. 例外的继承架构
• Throwable类别拥有几个取得相关例外讯息的方
法。
– getLocalizedMessage()
• 取得例外对象的区域化讯息描述
– getMessage()
• 取得例外对象的讯息描述
– printStackTrace()
• 显示例外的堆栈讯息,这个方法在追踪例外发生的根源时相当
的有用,简单的说若A方法中呼叫了B方法,而B方法中呼叫了
C方法,C方法产生了例外,则在处理这个例外时呼叫
printStackTrace()可以得知整个方法呼叫的过程,由此得知例
外是如何被层层丢出的。
260. 例外的继承架构
try {
throw new ArithmeticException("例外测試");
}
catch(Exceptione) {
System.out.println(e.toString());
}
catch(ArithmeticException e) {
System.out.println(e.toString());
}
261. 例外的继承架构
try {
throw new ArithmeticException("例外测試");
}
catch(ArithmeticException e) {
System.out.println(e.toString());
}
catch(Exception e) {
System.out.println(e.toString());
}
263. 常数设置
• 可使用接口来定义操作时所需的共享常数
public interface ActionConstants {
public static final int TURN_LEFT = 1;
public static final int TURN_RIGHT = 2;
public static final int SHOT = 3;
}
264. 常数设置
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;
}
}
265. 常数设置
• 使用类别来宣告的话
public class CommandTool {
public static final String ADMIN = "onlyfun.caterpillar.admin";
public static final String DEVELOPER =
"onlyfun.caterpillar.developer";
public void someMethod() {
// ....
}
}
• 如果常数只是在类别内部使用的话,就宣
告其为“private”或是“protected”就可以了
– 宣告为类别外可取用的常数,通常是与类别功
能相依的常数