第 7章
封装
– 定义类别( Class)
– 关于方法以对象思考问题
有一个帐户,帐户中有存款余额,您可以对帐户进行存款与提款的动作,并可以查询以取得存款余额。
– 识别问题中的对象与属性
– 识别对象上的方法以对象思考问题使用 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;
}

定义类别定义建构方法使用 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;
}
}
定义成员使用 class定义类别
可根据类别来建构对象
要透过公开成员来操作对象或取得对象信息的话,可以在对象名称后加上「,」运算符来进行
Account account1= newAccount();
Account account2 =newAccount("123-4567",100.0);
account1.getBalance();
account1.deposit(1000.0);
使用 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());
类别成员( Classmember)
类别成员可用的访问权限修饰词有,public”、
,protected”、,private”三个
在宣告成员时不使用存取修饰词,则预设以「套件」( package)为存取范围类别成员( Classmember)
数据成员被宣告为,private”,表示它是
「私用成员」 ( Privatemember),私用成员只能在类别中被使用
方法被宣告为 "public",表示这些方法可以藉由对象的参考名称加上 "."直接呼叫存取修饰 传回值型态 方法名称 (参数列 ) {
//实作 return传回值 ;
}
类别成员( Classmember)
方法区块中可以宣告变量( Variable),参数在方法区块执行结束后就会自动清除
方法中的相同变量名称会暂时覆盖数据成员的作用范围
可以使用 "this"关键词来特别指定类别成员( 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;
}
}
类别成员( Class member)
信息的最小化
– 如果数据成员能不公开就不公开
透过公开方法存取私用成员的好处
– 如果存取私用成员的流程有所更动,只要在公开方法中修改就可以了
public double withdraw(double money) {
if(balance – money < 0) {
return 0;
}
else {
balance -= money;
return money;
}
}
建构方法( Constructor)
建构方法是与类别名称相同的公开方法成员,且没有传回值
public class SafeArray {
//,.
public SafeArray() { //建构方法
//,..,
}
public SafeArray(参数列 ) {//建构方法
//,...
}
}
建构方法( Constructor)
public class SafeArray {
private int[] arr;
public SafeArray() {
this(10); //预设 10个元素
}
public SafeArray(int length) {
arr = new int[length];
}

}
关于 this
方法成员在内存中会只有一份关于 this
使用参考名称来呼叫对象的方法成员时,
程序会将对象的参考告知方法成员
在方法中所撰写的每一个数据成员其实会隐含一个 this参考名称
this名称参考至呼叫方法的对象
public double getBalance() {
return this.balance;
}
关于 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;
}
关于 this
this还有一种可以带自变量的用法,主要是用于呼叫建构方法
public class Ball {
private String name;
public Ball() {
this(“No name”); //会使用 Ball(“No name”)来建构
}
public Ball(String name) {
this.name = name;
....
}
}
关於 static
被宣告为,static”的数据成员,又称「静态数据成员」
静态成员是属于类别所拥有,而不是个别的对象
可以将静态成员视为每个对象实例所共享的数据成员
public class Ball {
public static double PI = 3.14159; //宣告 static资料
...
}
关于 static
属于类别所拥有,可以在不使用名称参考下,直接使用类别名称加上‘,’运算符来存取
同样遵守,public”、,protected”与
,private”的存取限制
设定为,public”成员的话就可以如下存取
下面的方式是不被鼓励的
System.out.println("PI = " + Ball.PI);
Ball ball = new Ball();
System.out.println("PI = " + ball.PI);
关于 static
可以宣告方法成员为 "static"方法,又称
「静态方法」
public class Ball {
...
public static double toRadian(double angle) {
return 3.14159 / 180 * angle;
}
}
System.out.println("角度 90等于径度 " + Ball.toRadian (90));
关于 static
静态方法中不会有 this参考名称
静态方法中不允许使用非静态成员
在静态方法中不能呼叫非静态方法
non-static variable test cannot be referenced from a static context
non-static method showHello() cannot be referenced from a static context
关于 static
可以使用,static”定义一个静态区块,并在当中撰写类别载入时的初始化动作
在类别被加载时,默认会先执行静态区块中的程序代码,且只会执行一次
public class Ball {
static {
//一些初始化程序代码
}
....
}
重载( 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)
重载( 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) {
//,..
}
}
重载( Overload)方法
返回值型态不可用作为方法重载的区别根据,以下是不正确的
public class SomeClass {
public int someMethod(int i) {
//,..
return 0;
}
public double someMethod(int i) {
//,..
return 0.0;
}
}
重载( 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版本被呼叫 ");
}
重载( Overload)方法
注意到 autoboxing,unboxing的问题
– 找寻在还没有装箱动作前可以符合自变量个数与型态的方法
– 尝试装箱动作后可符合自变量个数与型态的方法
– 尝试设有「不定长度自变量」并可以符合的方法
– 编译程序找不到合适的方法,回报编译错误不定长度自变量
J2SE5.0之后开始支持「不定长度自变量」
( Variable-lengthArgument)
实际上 nums是一个数组
public static int sum(int..,nums) { //使用,..宣告参数
int sum = 0;
for(int num,nums) {
sum += num;
}
return sum;
}
不定长度自变量
宣告的参数必须设定在参数列的最后一个,
下面的方式是合法的
下面的方式是不合法的
public void someMethod(int arg1,int arg2,int..,varargs) {
//,...
}
public void someMethod(int..,varargs,int arg1,int arg2) {
//,...
}
不定长度自变量
没办法使用两个以上的不定长度自变量,
下面的方式是不合法的
如果使用对象的不定长度自变量,宣告的方法相同
public void someMethod(int..,varargs1,int..,varargs2) {
//,...
}
public void someMethod(SomeClass..,somes) {
//,...
}
递归方法
在方法中呼叫自身同名方法,而呼叫者本身会先被置入内存「堆栈」( Stack)中
堆栈是一种「先进后出」 ( First in,lastout)
的数据结构
private static int gcd(int m,int n) {
if(n == 0)
return m;
else
return gcd(n,m % n);
}
垃圾收集
Java提供垃圾收集机制
在适当的时候,Java执行环境会自动检查对象,看看是否有未被参考的对象
如果有的话就清除对象、回收对象所占据的内存空间
在程序执行的空闲时候,您可以建议执行环境进行垃圾收集,但也仅止于建议垃圾收集
finalize()会在对象被回收时执行
因为不知道对象资源何时被回收,所以也就不知道 finalize()真正被执行的时间垃圾收集
public class GcTest {
private String name;
public GcTest(String name) {
this.name = name;
System.out.println(name + "建立 ");
}
//对象回收前执行
protected void finalize() {
System.out.println(name + "被回收 ");
}
}.
垃圾收集
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); //不断执行程序