第五讲 类的封装和类的继承
第五講 類的封裝和類的繼承
| 主要內(nèi)容 軟件包的創(chuàng)建和使用 Java訪問權(quán)限修飾詞 類的訪問權(quán)限修飾詞 Java中類的層次結(jié)構(gòu)和類的繼承 對象的初始化再討論 |
?
軟件包的創(chuàng)建和使用
什么是軟件包(package)
包的組成:由一組類(class)和接口(interface)組成。
Java允許把多個(gè)類收集在一起成為一組,稱作包(package)。
包的作用:包是Java提供的一種類庫的封裝機(jī)制。專有的名字空間,解決了不同包中的類同名的問題。使自己的任務(wù)和其他人提供的代碼庫相分離。
?
軟件包的建立
從示例程序理解
編譯如下程序,查看所編譯文件的位置。
package mylib.simple;
public class List{
?? public List(){
??????? System.out.println("mylib.simple.List");
?? }
}
結(jié)論:
1、包對應(yīng)著文件系統(tǒng)的目錄層次結(jié)構(gòu)。
2、編譯生成的字節(jié)碼文件將置放到包中,即包名所指定的目錄中。
?
軟件包的創(chuàng)建
package packagename;
幾個(gè)要點(diǎn):
l?package語句必須是文件中的第一條語句。
l?用“.”作為分隔符來指明包(目錄)的層次。
l?包名由小寫字母組成。
l?沒有注明放入到某個(gè)包中去的類,自動(dòng)地歸在一個(gè)無名包中
?
軟件包的使用
l?設(shè)置環(huán)境變量classpath
l?在Jcreator中添加classpath
l?使用如下兩種方法之一:
2?用import加載包中的類:import 包名; 或import 包名.類名;
2?直接用包名.類名去訪問類
?
說明:
2?import語句必須放在package語句和類的定義之間。
2?某個(gè)類若用到其他類,會(huì)優(yōu)先在所在軟件包中查找,繼而在classpath指定的路徑下查找。
?
例:創(chuàng)建一個(gè)newjw目錄,在此新目錄下創(chuàng)建如下java文件。
import mylib.simple.List;
class TestList{
?? public static void main(String[] aa){
??????? new List();
?? }
}
試用方法二改寫并編譯執(zhí)行之。
| 思考 1.?? 一個(gè)程序的首語句是package a.b.c.d;其意是? 2.?? 一個(gè)程序中可含多個(gè)類,它們可分放到不同的軟件包嗎? 3.?? 若要使用d:\java07下的軟件包,classpath如何設(shè)置? 4.?? 如何用到不同目錄下的軟件包myclass.lib1中的類? 5.?? 同一個(gè)軟件包中的類可否直接使用? 6.?? 一個(gè)類設(shè)計(jì)成可被到處使用,應(yīng)聲明為public類嗎? 7.?? 一個(gè)類用到其他類時(shí),編譯時(shí)的類查找路徑是? |
?
軟件包的操作練習(xí)
練習(xí):建立工具包,并使用之。
1.?設(shè)計(jì)一個(gè)P類置入mylib.tools包中,該P(yáng)類含rint和rintln方法,可實(shí)現(xiàn)字符串的輸出。
2.?用mylib.tools中的類P,分別輸出字符串和數(shù)字。
import ????????????????????????;
class TestP{
?? public static void main(String[] aa){
?
?
?? }
}
3. 創(chuàng)建一個(gè)Input類,含有來輸入整數(shù)或字符串的方法,以使下面的程序能正確編譯和執(zhí)行。
import mylib.tools.Input;
import mylib.tools.P;
class TestInput{
?? public static void main(String[] aa){
??????? int y=Input.aInt();
??????? P.rintln(y+"");
??????? String s=Input.aString();
??????? P.rintln(s);
?? }
}
| 練習(xí) 1. 分別構(gòu)造一個(gè)Circle類和Square類,可接受半徑(邊長),包含求面積的方法。將它們放在myclass.simple包中。 2. 利用上述類,求半徑為4.5的圓面積,邊長為4.5和6.5的矩形面積。 |
?
Java訪問權(quán)限修飾符
決定類成員的訪問權(quán)限的修飾符有:public 、protected 、private。
權(quán)限的設(shè)定對于類的封裝有著重要的意義。公開需要公開的,隱藏必須隱藏的。這樣就讓類的繼承變得簡單。
?
無權(quán)限修飾符的成員
允許本類、同一軟件包中的類訪問。即享受“包訪問權(quán)限”。
?
public成員
public描述的是一個(gè)類中可向外公開的信息(屬性和方法)。
允許本類、繼承類、同一軟件包中的類、不同軟件包中的類訪問。
示例:不同軟件包之間一個(gè)類訪問另一個(gè)類的public成員。
package mylib.lib1;??? //Base.java
public class Base{
?? public int x=5;
?? public void print(){
??????? System.out.println("base"+x);//本類訪問
?? }
}
?
package mylib.lib2;??? //Derive.java
class Derive {
?? public static void main(String args[]){
??????? mylib.lib1.Base b = new mylib.lib1.Base();
??????? b.x=5;?//不同軟件包的類訪問
??????? b.print();
?? }
}
| 思考 1.?? 程序編譯后,磁盤上新增的目錄結(jié)構(gòu)? 2.?? 在Base類中,可以公開的信息是? 3.?? public的公開范圍? 4.?? 如果Base類中的成員變量x前無public,會(huì)在何環(huán)節(jié)產(chǎn)生問題? |
?
?
private成員
private修飾的成員變量和成員方法都只能在本類中訪問。
修飾不希望被其它類訪問的變量和方法。有兩種限制:
2?其它類中的該類對象不能訪問private成員。
2?派生子類時(shí),子類不能繼承父類的private成員
class Base1{
?? private int x=1;
?? private void print(){
??????? System.out.println("base"+x);
?? }
?? void doprint(){
??????? print();
?? }
}
class Derive1{
?? public static void main(String args[]){
?? ???? Base1 b = new Base1();
??????? b.doprint();?//直接調(diào)用b.print();試試!
?? }
}
觀察JCreator中的數(shù)據(jù)視圖(ctrl+alt+c),加深對private成員的認(rèn)識(shí)。
?
假如構(gòu)造方法是private的,類就不可直接實(shí)例化成對象:
class Sundae{
?? private Sundae(){
??????? System.out.println("Here is a sundae");
?? }
?? static Sundae getASundae(){
??????? return new Sundae();
?? }
}
class TestSundae{
?? public static void main(String[] aa){
??????? Sundae s=Sundae.getASundae();
?? }
}
protected成員
這是受保護(hù)成員。其修飾的數(shù)據(jù)和方法對繼承它的子類公開。
protected成員允許本類、繼承類和同一軟件包中的類訪問。
包權(quán)限訪問
class Base1{
?? protected int x=1;
?? protected void print(){
??????? System.out.println("base"+x);
?? }
}
class Derive1{
?? public static void main(String args[]){
??????? Base1 b = new Base1();
??????? b.print();
?? }
}
繼承類對protected成員的訪問
package mylib.simple;//Cookie.java
public class Cookie{
?? public Cookie(){
??????? System.out.println("Cookie constructor");
?? }
?? protected void bite(){System.out.println("bite");}
}
?
import mylib.simple.Cookie; //Chocolatechip.java
class Chocolatechip extends Cookie{
?? Chocolatechip(){
??????? System.out.println("Chocolatechip");
?? }
?? public static void main(String[] aa){
??????? Chocolatechip c=new Chocolatechip();
??????? c.bite();????
?? }
}
| 思考 1.?? 何謂類的封裝? 2.?? 從封裝角度比較以上不同的權(quán)限修飾? 3.?? 一個(gè)public成員向誰公開信息? 4.?? 一個(gè)protected成員向誰公開信息? 5.?? 一個(gè)private成員向其它類公開信息嗎? 6.?? private有何意義? |
?
練習(xí):試填表說明不同訪問修飾符的訪問權(quán)限
| 訪問修飾符 | 本類 | 同軟件包 | 不同包中子類 | 不同包且無繼承 |
| public | ? | ? | ? | ? |
| protected | ? | ? | ? | ? |
| 無修飾詞 | ? | ? | ? | ? |
| private | ? | ? | ? | ? |
?
類的訪問權(quán)限
無訪問修飾符
即為缺省類。可以被同一個(gè)軟件包中的類訪問。
?
public類
通過import導(dǎo)入(配合classpath的設(shè)置),可以被任何其它的類訪問。
public class 類名
| 思考 假如某一程序中定義了一個(gè)public類,框架如下: package mylib.abc; public class Abc{…} ? 1.?? 該程序應(yīng)命名為? 2.?? 在另一個(gè)程序中如何能訪問到Abc類? 3.?? 如果該類有顯式的構(gòu)造方法,并允許在其它類中創(chuàng)建該類的對象,構(gòu)造方法的權(quán)限設(shè)置應(yīng)是? |
?
private類
專用于修飾內(nèi)部類,內(nèi)部類常用于處理本類中的事件。
?
類的繼承
類的層次結(jié)構(gòu)
指的是繼承關(guān)系可以層次地遞延下去。
在Java程序中創(chuàng)建的所有類都是類層次結(jié)構(gòu)的部件
每個(gè)類都有父類
如果沒有使用extends關(guān)鍵字,則Object類就是缺省的父類。
Object類包含在java.lang包中。所有的類都是從這個(gè)類繼承而來的。
Object類定義和執(zhí)行了在Java系統(tǒng)需要的所有類的行為。
?
類的層次結(jié)構(gòu)圖
?
| 思考 ? 1.?? 根據(jù)層次結(jié)構(gòu)圖,每個(gè)類都有父類嗎? 2.?? 如果類定義時(shí)無extends部分,該類的父類是? 3.?? 多個(gè)子類可以繼承自一個(gè)父類嗎? 4.?? 一個(gè)類可以同時(shí)繼承多個(gè)父類嗎? 5.?? Object類在哪個(gè)軟件包中? |
?
?
類的繼承(inheritance)
使用extends關(guān)鍵字實(shí)現(xiàn)繼承
| class SubClass extends SuperClass { ??? ClassBody } |
?
父類和子類
繼承另一個(gè)類的類稱為子類,被繼承的類稱為父類。
在Java中一個(gè)類只能直接繼承一個(gè)父類。
?
?
繼承的意義
一個(gè)類能從其它類繼承行為與屬性。
?
例:通過對Person類的繼承,定義Children類
class Person{
?int salary;
?void employed(){
?????? System.out.print("Work state:");
?????? if (salary==0) System.out.println("no job");
?????? else System.out.println("job");
?}
}
class Children extends Person{
?int age;
?void printAge(){
?????? System.out.println("Age:"+age);
?}
}
?
class Test{
?public static void main(String[] aa){
?????? Children c=new Children();
?????? c.salary=560;
?????? c.age=12;
?????? c.printAge();
?????? c.employed();
?}
}
| 思考 1.?? 一個(gè)類如何去繼承另一個(gè)類? 2.?? 示例中Children繼承了Persons類的什么? 3.?? Children的實(shí)例化對象與Persons的實(shí)例化對象區(qū)別在哪里? 4.?? 若希望父類中的某成員不被子類所繼承,如何實(shí)現(xiàn)? |
?
練習(xí):閱讀和分析程序,理解繼承。
import javax.swing.*;
class Test extends JFrame{
?public static void main(String[] aa){
?????? Test t=new Test();
?????? t.setVisible(true);
?????? t.setSize(300,200);
?}
}
?
對象的初始化再討論
基本的初始化過程
2?初始化時(shí)涉及到成員變量和構(gòu)造方法;
2?實(shí)例變量的初始化在構(gòu)造方法之前。
class Tag{
?? Tag(int m){
??????? System.out.println("Tag("+m+")");
?? }
}
class Card{
?? Tag t1=new Tag(1);
?? Card(){
??????? System.out.println("Card()");
??????? t3=new Tag(33);
?? }
?? Tag t2=new Tag(2);
?? void f(){
??????? System.out.println("f()");???????
?? }
?? Tag t3=new Tag(3);
}
class TestInit2{
?? public static void main(String[] aa){
??????? Card t=new Card();
??????? t.f();
?? }
}
?
靜態(tài)變量的初始化
類中的靜態(tài)成員變量的初始化在編譯時(shí)進(jìn)行
靜態(tài)變量只初始化一次
class Bow{
?Bow(int m){
?????? System.out.println("Bow("+m+")");
?}
?void f(int m){
?????? System.out.println("f("+m+")");??????
?}
}
class Table{
?Bow b1=new Bow(1);
?Table(){
?????? System.out.println("Table()");
?????? b2.f(1);
?}
?static Bow b2,b3;
?static{
?????? b2=new Bow(2);
?????? b3=new Bow(3);
?}???
}
class TestInit{
?public static void main(String[] aa){
?????? System.out.println("Creating new Table()");
?????? new Table();
?????? System.out.println("Creating new Table()");
?????? new Table();
?}
}
?
| 思考 1.?對象的初始化在什么時(shí)候進(jìn)行? 2.?靜態(tài)變量和實(shí)例變量的初始化時(shí)機(jī)? 3.?實(shí)例變量和構(gòu)造方法哪個(gè)先初始化? 4.?除了構(gòu)造方法外,通常的成員方法會(huì)自動(dòng)初始化嗎? 5.?類有多個(gè)成員變量,這些變量的初始化順序? |
?
帶有繼承時(shí)的初始化過程
2?靜態(tài)變量初始化
2?運(yùn)行父類的無參數(shù)構(gòu)造方法(按級(jí)別高到低)
2?本類實(shí)例變量初始化
2?運(yùn)行本類的構(gòu)造方法
class GrandParent{
?GrandParent(){
?????? System.out.println("GrandParent");
?}
}
class Parent extends GrandParent{
?Parent(){
?????? System.out.println("Parent");
?}
}
class Children extends Parent{
?Children(){
?????? System.out.println("Children");
?}
?public static void main(String[] a){
?????? new Children();
?}
}
問題:若類GrandParent類定義如下,程序運(yùn)行結(jié)果?
class GrandParent{
?GrandParent(){}
?GrandParent(String s){
?????? System.out.println("GrandParent "+s);
?}
}
| 思考 1.?對象的初始化時(shí),父類的什么樣的構(gòu)造方法能自動(dòng)執(zhí)行? 2.?父類構(gòu)造方法的執(zhí)行時(shí)機(jī)? |
?
有關(guān)對象初始化的結(jié)論
繼承時(shí),初始化的順序(包括構(gòu)造方法):
| 主類中的靜態(tài)成員初始化 | 運(yùn)行父類的默認(rèn)構(gòu)造方法 (按級(jí)別高到低的順序) | 主類中非靜態(tài)成員初始化 | 調(diào)用主類的構(gòu)造方法 |
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/baoguo/archive/2010/12/08/1899881.html
總結(jié)
以上是生活随笔為你收集整理的第五讲 类的封装和类的继承的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 京东金条有额度为什么没法借款
- 下一篇: 什么是p2p平台