/*
內部類:
.在類中定義的類我們稱之爲內部類,它是外部類的一個成員。
.內部類可以直接訪問外部類的成員,但是外部類不能直接的去調用外部類的成員、
其實內部類調用外部類的成員的時候.其實是使用到了:類名.this.變量名 來訪問外部類的成員。
.在內部類中的方法可以使用this引用調用這個方法的內部類對象.
*/
class Outer
{
String name = "張三";
public void run()
{
System.out.println("Outer is Running");
}
public void show()
{
System.out.println("My name is Outer");
System.out.println(new Inner().age);
}
class Inner
{
int age = 19;
public void run()
{
System.out.println("Inner is Running");
}
public void eat()
{
this.run(); //this.代表方法所調用的對象.它的對象是inner 所以輸出的是inner
show(); //因爲創建內部類的時候.外部類的對象已經創建了. 如果虛擬機在內部類中找不到.它會到外部類去找這個show()對象.
System.out.println(Outer.this.name); //其實同等於:Outer.this.name //類名.name
System.out.println("Nnner is Eat");
}
}
}
class Demo
{
public static void main(String[] args)
{
Outer.Inner inner = new Outer().new Inner(); //類型要一致!
inner.run();
inner.eat();
}
}
/*
可以在方法中定義內部類?
System.out.println(age);爲什麼會訪問不了呢.編譯出錯/
其實:當我們在外部類調用A對象的時候.run()方法由於age是存儲在棧內存的臨時變量中的. 當我們對象調用完畢過後呢.
有可能是會被釋放調的.而當你再次調用的時候 age 的時候呢.由於虛擬機可能會被釋放.所以調用不了.
那麼:虛擬機認爲你這樣做是編譯錯誤的!
*/
class A
{
String name = "小細" ;
public void run()
{
int age = 19;
class B
{
public void run()
{
String name = "王五";
System.out.println("my name is B");
//System.out.println(age);
System.out.println(A.this.name); //通過類名.this.屬性名訪問外部類的屬性.
}
}
new B().run();
}
}
class Demo
{
public static void main(String[] args)
{
A a = new A();
a.run();
}
}
/*
匿名內部類:
*/
class Fruit
{
public void qupi()
{
}
}
class Person
{
public void eat(Fruit f)
{
f.qupi();
System.out.println("喫完啦!!");
}
}
class Demo
{
public static void main(String[] args)
{
Person p = new Person();
p.eat(new Fruit(){
public void qupi()
{
System.out.println("Apple把皮弄開!");
}
}
);
}
}
/*
static修飾的靜態內部類:
.靜態的內部類可以聲明非靜態的屬性和方法. 但是靜態的內部類是不能訪問外部類非靜態的方法.因爲外部類的屬性需要創建對象才能調用.
你內部類是不需要創建對象的.所以調用不了。
.靜態的內部類不能訪問非靜態的屬性.
*/
class Outer
{
static String name = "kudy";
String ID = "888";
static class Inner
{
int age = 19;
public void run()
{
System.out.println(age);
System.out.println("Inner is happy");
System.out.println(Outer.name); //因爲是不需要創建對象的.所以可以使用Outer.name訪問外部的靜態的方法。
// System.out.println(Outer.ID);
}
}
}
class Demo
{
public static void main(String[] args)
{
Outer.Inner inner = new Outer.Inner(); //靜態的內部類一定要靜態的去創建!
//System.out.println(inner.age);
inner.run();
}
}
/*
類的繼承
.使用extends關鍵字來聲明類的關係
.子類會自動繼承父類的屬性與方法
*/
class Person
{
String name ;
public void run()
{
System.out.println("Person is Running");
}
}
class Man extends Person
{
public void toLike()
{
System.out.println(name +"運動"); //默認會添加上this的
}
}
class Demo
{
public static void main(String[] args)
{
Man man = new Man();
man.name = "小細";
man.run();
man.toLike();
}
}
/*
類的繼承是爲了實現代碼的複用性,如果有多個類具有相同的方法.我們應該儘量把她抽出一個類來
*/
class Person
{
String name ;
int age;
public void eat()
{
System.out.println(name+"喫飯"+",年齡爲:"+age); //this.name this.age
}
public void run()
{
System.out.println("需要運動");
}
}
class Student extends Person
{
public void eat()
{
System.out.println("喫一口飯");
super.eat(); //調用父類的方法、。
System.out.println("看一下作業");
}
}
class Teacher extends Person
{
public void eat()
{
System.out.println("抽一根");
super.eat();
System.out.println("再來一根");
}
}
class Demo
{
public static void main(String[] args)
{
Student student = new Student();
student.name = "小細";
student.age = 19;
student.eat();
student.run();
}
}
/*
父類型的引用指向子類型的對象.也就是想上類型轉換.不需要強制轉換
強制轉換的要求: 父類型的引用指向子類型的對象。
.把父類當做子類來使用是不行的,因爲子類有的.父類型不一定有
.當做子類當做父類來用時,只能使用父類型所擁有的方法。
如果調用子類擁有的方法.編譯器會報錯!所以需要強制轉換.但在強制轉換的前提下我們要知道父類型的引用是否是指向了子類型的對象
強制轉換之前需要判斷一下.
注意:
.當你父類型的引用指向子類型的對象的時候.你必須要清楚的就是:你訪問的屬性是會是父類的.而不是子類的.
因爲java在屬性方法是做了靜態的綁定.誰是我的類型.我就去誰的類型去找.而方法就剛好相反.
方法就是:誰指向誰.我就調用誰的方法.。 因爲是做了動態的綁定。
*/
class Typist
{
String name = "小細";
public void type()
{
System.out.println("typeing");
}
}
class Coder extends Typist
{
String name = "王五";
public void type()
{
System.out.println("tepeing slowly!!!");
}
public void code()
{
System.out.println("Codeing");
}
}
class Demo
{
public static void main(String[] args)
{
//向上類型轉換: 父類型的引用指向子類型的對象.
Typist typist = new Coder();
//typist.type(); 因爲你是指向了子類型的引用.所以java做了動態綁定.也就是說你綁定了一個子類型的方法。
System.out.println(typist.name);
/*
爲什麼輸出小細呢.因爲java在檢查的時候.屬性是不做動態綁定的.也就是說.類型是誰.他就會找類型裏面的屬性.
*/
/*
Code code = new Typist();
子類型的引用不能指向父類的對象.因爲子類有的.父類型不一定有.
*/
Coder coder;
if(typist instanceof Coder) //父類型的引用指向子類型的對象纔可以搶走轉換!
{
coder = (Coder)typist; //強制轉換成子類
System.out.println(coder.name);
}
}
}
/*
因爲java的屬性在父類型的引用指向子類型的情況是做了靜態的綁定的.所以我們可以這麼做!
*/
class Person
{
private String name = "無名氏";
public String getName()
{
return name;
}
public void eat()
{
System.out.println("eating");
}
}
class A extends Person
{
private String name = "小細";
public String getName()
{
return name;
}
}
class B extends Person
{
String name = "kudy";
}
class Demo
{
public static void main(String[] args)
{
Person p = new A();
/*
因爲java的父類型的引用指向子類型的對象的時候.方法使用了動態.而屬性只使用了靜態.也就是說:類型是那個.屬性就是從
那裏去找
*/
System.out.println(p.getName());//這樣就是調用了子類型的屬性啦~~
}
}
/*
什麼情況下使用子類當做父類來使用
匿名內部類:new一個父類對象,後面跟一個花括號,這時不需要創建父類的實例
*/
class Person
{
String name = "無名氏";
public void eat()
{
//每個人的愛好不同!
}
}
class Restaurant
{
public void run(Person p)
{
p.eat();
}
}
class Chinese extends Person
{
public void eat()
{
String name = "中國人"; //在方法裏面是動態調用的哦。
System.out.println(name+"我是拿筷子喫的!");
}
}
class American extends Person
{
public void eat()
{
String name = "美國人";
System.out.println(name+"我只喫漢堡包!");
}
}
class Demo
{
public static void main(String[] args)
{
Restaurant r = new Restaurant();
//r.run(new American());
r.run(new Chinese());
/*
內部類:
class JB extends Person
{
public void eat()
{
System.out.println("我是喫垃圾的!");
}
}
r.run(new JB());
*/
r.run(getIndia());
}
static Person getIndia()
{
String name = "印度菜";
Person p = new Person(){ //我創建了一個子類.子類裏面有eat方法重寫啦.之後呢.再把這個重寫好的對象返回來.也就是說:父類型的引用指向子類型的對象
public void eat()
{
System.out.println(this.name+"印度菜");
}
};
return p;
}
}
class A
{
String name = "小三";
public String getName()
{
return name;
}
public void run()
{
System.out.println(name);
}
}
class B extends A
{
private String name = "小四";
public String getName()
{
return name;
}
public void run()
{
System.out.println(name);
}
public void show()
{
System.out.println("我是子類!");
}
}
class Demo
{
public static void main(String[] args)
{
A a = new B(); //父類型的引用指向子類型的對象. 就可以使用子類型與父類型所共同擁有的方法.但是子類出來的就不行。
// a.show();
/*
System.out.println(a.name);
如果這樣寫出來是小三,而不是小四,但是在方法裏面輸出來的就是小四.因爲她的屬性在方法裏面運行啦.所以是動態的.
而你單獨如果想輸出它的屬性的話,它是根據了靜態綁定來進行操作.也就是輸出了類型裏面屬性的內容!
那方法就是: 給所有的變量私有化.給他開一個public方法.返回屬性!!因爲方法是可以轉換爲動態的.
有的人可能會問?不相同可以嗎? 如果不相同的話.前面已經說過: 就是子類型所特有的.你父類型是不可以調用.除非需要強制轉換!
*/
String name = a.getName(); //這時候方法已經給重寫
System.out.println(name); //輸出的會是小四
}
}
/*
對象的比較:
對象的比較不能使用 == 這樣比較的是比較地址. 應該用equals方法
因爲所有的類都是默認的繼承與Object! 我們可以重寫它裏面的equals比較方法。
*/
class Person
{
private String name ;
private int age ;
public Person(String name ,int age)
{
this.name = name ;
this.age = age ;
}
@Override //告訴編譯器我重寫父類型的方法! 大寫的O
//重寫父類的方法!
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj instanceof Person) //如果你父類型的引用是指向了子類型的對象的.那麼就判斷.
{
//因爲是按照了父類型的引用是指向了子類型的對象.首先我們要判斷一下.強制類型轉換.要不然我們是調用不了子類型的內容
Person p =(Person)obj;
if(this.name.equals(p.name)&&this.age == age)
return true;
}
return false;
}
}
class Demo
{
public static void main(String[] args)
{
Person p1 = new Person("張三",19); //p1就是當前對象!
Person p2 = new Person("張三",19);
System.out.println(p1.equals(p2));
}
}
class Person
{
String name ;
public void eat()
{
}
}
class Restaurant
{
public void show(Person p)
{
p.eat();
}
}
class Chinese extends Person
{
String name = "中國人";
public void eat()
{
System.out.println(name+"我喫中國菜!");
}
}
class Test
{
public static void main(String[] args)
{
Restaurant r = new Restaurant();
r.show(new Chinese());
/*
匿名內部類的第一種用法!
*/
r.show(new Person(){
public void eat()
{
System.out.println("日本人喫日本菜!");
}
}
);
r.show(getUSA());
}
public static Person getUSA()
{
Person p = new Person(){
public void eat()
{
String name = "美國人";
System.out.println(name+"喫美國菜!");
}
};
return p;
}
}
使用Java的文檔註釋
文檔註釋以“/**”開始,以“*/”標誌結束,相應的信息和批註所對應的位置很重要! 類的說明應在類定義之前,方法的說明應在方法的定義之前。
批註參數來標記一些特殊的屬性及其相應的說明 。
@author<作者姓名>
@version<版本信息>
@param<參數名稱><參數說明>
@return<返回值說明>
生成文檔的命令
javadoc -d Engineer -version -author Engineer.java
心得:
我要向前衝,想前衝。