Java復(fù)用類
組合與繼承
- 組合:在新的類中產(chǎn)生現(xiàn)有類的對象彤钟。
- 繼承:按照現(xiàn)有類的類型來創(chuàng)建新類,無需改變現(xiàn)有類的形式曹体,采用現(xiàn)有類的形式并在其中添加新的代碼扳缕。
組合:
public class TestDemo1 {
public static void main(String[] args) {
A a = new A();
a.f1();
}
}
class A{
public void f1(){
B b = new B("哈登");//組合
b.f2();
System.out.println(b);// 如果不覆寫B(tài)類中的toString(),那么就會輸出b對象的地址
}
}
class B{
private int age;
private String name ;
public B(String name){
this.name = name;
this.age=28;
}
public void f2(){
System.out.println("姓名為:"+name+" ,年齡為:"+age);
}
@Override
public String toString() {
return name;
}
}
打印結(jié)果
這里在B類的構(gòu)造方法中初始化了age的值,如果將this.age=28注釋掉举畸,那么年齡為0.
關(guān)于初始化
1.類中域為基本類型時查排,默認(rèn)自動初始化為0
2.類中域為引用類型時,默認(rèn)自動初始化為null
初始化位置
1.在定義對象的地方抄沮。意味著在調(diào)用構(gòu)造器之前進(jìn)行初始化
2.在類的構(gòu)造器中
3.實(shí)例初始化
4.延遲初始化(惰性初始化)在使用對象之前
看一下具體代碼
public class ChuShiHua {
public static void main(String[] args) {
Student student = new Student("Messi");
System.out.println(student);
}
}
class Student {
//1.在定義對象的地方跋核。意味著在調(diào)用構(gòu)造器之前進(jìn)行初始化
private String name1="Ronaldo";
private String name2,name3,name4;
//2.在類的構(gòu)造器中
public Student(String name2){
this.name2 = name2;
}
// 3.實(shí)例初始化
{
name3="Alice";
}
// 4.延遲初始化(惰性初始化)在使用對象之前
@Override
public String toString() {
if(name4==null){
name4="Peter";
}
return name1+" "+name2+" "+name3+ " "+ name4;
}
}
繼承
class Fu{
public Fu(){
System.out.println("這是父類構(gòu)造");
}
}
class Son extends Fu{
public Son(){
System.out.println("這是子類構(gòu)造");
}
}
public class JiCheng {
public static void main(String[] args) {
new Son();
}
}
這里Son類繼承了Fu類。關(guān)鍵字是extends.無論如何叛买,父類構(gòu)造總是先被初始化砂代,然后再初始化子類構(gòu)造。
子類默認(rèn)調(diào)的是父類的無參構(gòu)造率挣,如果想要調(diào)用父類的有參構(gòu)造刻伊,那么在子類構(gòu)造的第一句話寫上super(..)
class Fu{
int age;
public Fu(){
System.out.println("aaa");
}
public Fu(int age){
this.age = age;
System.out.println("這是父類構(gòu)造"+this.age);
}
}
class Son extends Fu{
int i;
public Son(int i){
**super(20);**
this.i = i ;
System.out.println("這是子類構(gòu)造"+ i);
}
}
public class JiCheng {
public static void main(String[] args) {
new Son(10);
}
}
protected關(guān)鍵字
- 對于類的用戶而言,是私有的
- 對于其子類或者同一包的類而言椒功,是可以訪問的
在F類中定義了一個protected修飾的方法捶箱,在Z類中可以訪問的。
向上轉(zhuǎn)型
繼承的最大用處并不是復(fù)用類动漾,而是多態(tài)丁屎。多態(tài)又是基于繼承的。
class Instrument{
static void play(Instrument e){
System.out.println("通過向上轉(zhuǎn)型"+e);
}
}
public class Wind extends Instrument{
public static void main(String[] args) {
Wind wind = new Wind();
Instrument.play(wind);
}
}
在play()方法中谦炬,將Wind對象傳入到父類Instrument的play()方法中悦屏,照樣能夠打印出Wind對象。用父類的引用去接收子類的對象键思,其指向的是子類對象础爬。
final關(guān)鍵字
final所描述的對象是無法改變的。主要用在類吼鳞,方法看蚜,數(shù)據(jù)中。
數(shù)據(jù)
告知編譯器這塊數(shù)據(jù)是無法改變的赔桌。
1.一個永不改變的編譯時常量---減輕了運(yùn)行時的負(fù)擔(dān)
2.一個運(yùn)行時被初始化的值供炎,而你并不需要它被改變
3.一個即是static 又是 final 的數(shù)據(jù)描述的是只占據(jù)一塊不能改變的存儲空間
4.當(dāng)final作用在基本類型的時候渴逻,指的是數(shù)值無法改變。當(dāng)fianl作用于對象的引用時音诫,指的是對象的引用不變惨奕,但對象本身還是可以改變的。
class FinalData{
int num = 1;
public final int age1 =20;
/*
* 1.用static final 修飾的變量應(yīng)該字母全部大寫
* 2.用public可以無限制被訪問
* 3.static:強(qiáng)調(diào)只有一份
* 4.final: 說明它是一個常量
*
* */
public static final int AGE = 10;
}
public class FinalTest {
public static void main(String[] args) {
FinalData fd = new FinalData();
System.out.println(fd.age1);//輸出20
// fd.age1=30; 由于age是final所修飾的基本類型竭钝,數(shù)值不能被改變梨撞。
final FinalData fdFinal = new FinalData();
fdFinal.num=30;
System.out.println(fdFinal.num);//打印30
//無法編譯,因為fdFinal的引用是不能被改變的
// fdFinal = new FinalData();
}
}
final參數(shù)
class FinalData{
public void fun(final int i){
// i++;無法編譯香罐,因為i是final類型卧波,值無法改變
}
public void fun2(final FinalData f){
f.fun(1);
// f = new FinalData(); 無法編譯,因為f的引用不可變
}
}
public class FinalTest {
public static void main(String[] args) {
}
}
final方法
作用:
- 把方法鎖定庇茫,防止任何繼承類修改它的含義
- 效率
類中所以的private方法都是final類型的港粱,由于無法取用private方法,所以也就無法覆蓋它旦签。
class GrandFather{
private final void fun(){
System.out.println("11");
}
}
class Father extends GrandFather{
private final void fun(){
System.out.println("22");
}
}
class Son extends Father{
public final void fun(){
System.out.println("33");
}
}
public class FinalMethodTest {
public static void main(String[] args) {
Son s = new Son();
s.fun();//打印33
GrandFather f = s;
//f.fun(); 無法編譯
}
}
類內(nèi)所有 private 方法都自動成為 final查坪。由于我們不能訪問一個 private 方法,所以它絕對不會被其他方
法覆蓋(若強(qiáng)行這樣做宁炫,編譯器會給出錯誤提示)咪惠。可為一個 private 方法添加 final 指示符淋淀,但卻不能為
那個方法提供任何額外的含義遥昧。
final類
final類描述的是該類沒有子類,無法被繼承朵纷。
可以看到上面代碼報錯炭臭,無法編譯,原因是父類被聲明為final類型袍辞。
在一個類中如果被聲明為final類型鞋仍,那么該類的方法隱式的都被聲明為final類型。
初始化及類的加載
class Fu {
private int age =70;
private String name;
public static String address = "崇明島";
static {
System.out.println("這是父類的static靜態(tài)塊");
}
public Fu(){
System.out.println("這是父類構(gòu)造");
}
public void fu(){
System.out.println(age+name+address);
}
}
class Zi extends Fu{
private int age=30 ;
private String name;
public static String address = "海南島";
static {
System.out.println("這是子類的static靜態(tài)塊");
}
public Zi(){
System.out.println("這是子類構(gòu)造");
}
public void zi(){
System.out.println(age+name+address);
}
}
public class CSHTest extends Zi{
private int age=10 ;
private String name;
public static String address = "臺灣島";
static {
System.out.println("這是孫類的static靜態(tài)塊");
}
public CSHTest(){
System.out.println("這是孫類構(gòu)造");
}
public void test(){
System.out.println(age+name+address);
}
public static void main(String[] args) {
CSHTest t = new CSHTest();
t.test();
}
}
首先執(zhí)行CSHTEST類的main方法搅吁,類加載器查找CSHTEST編譯后的代碼.class威创,發(fā)現(xiàn)其有一個父類Zi,于是加載Zi,發(fā)現(xiàn)它又有一個父類,于是再加載Fu谎懦,此時肚豺,根基類中的static初始化(static修飾符描述的方法只執(zhí)行一次),然后是下一個導(dǎo)出類界拦,以此類推吸申。此種方式很重要。因為導(dǎo)出類初始化有可能依賴于父類的初始化。
此時類已經(jīng)加載完畢了〗夭辏現(xiàn)在可以創(chuàng)建對象了梳侨。首先,對象中的基本類型都被初始化為0日丹,對象的引用都被初始化為null,然后走哺,基類的構(gòu)造器就被調(diào)用,在本例中哲虾,是默認(rèn)調(diào)用的割坠,默認(rèn)調(diào)用super(),如果想指定調(diào)用有參構(gòu)造妒牙,那么自己寫super(Type Args).
總結(jié)就是:加載父類的靜態(tài)塊--->加載子類靜態(tài)塊---->加載父類的構(gòu)造--->加載子類構(gòu)造
聲明
所寫內(nèi)容是《Thinking In Java》讀書筆記