您好,登錄后才能下訂單哦!
這篇文章運用簡單易懂的例子給大家介紹java面向對象的意思是什么,代碼非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
11、子類訪問父類和方法覆寫
子類不能直接訪問父類的私有成員;
但是子類可以調用父類中的非私有方法來間接訪問父類的私有成員。
Person類中有私有字段name,Student繼承Person
new Sudent().name; ×
new Student().getName(); √
子類拓展父類(子類是父類的一種特殊情況)
主要是以父類為基礎,然后添加屬于自己的字段和方法。
方法覆寫產生原因:
當父類中某個方法不適合于子類時,子類出現父類一模一樣的方法.
判斷必殺技:子類方法前加上@Override能編譯通過,表明是方法的覆寫。
調用被覆蓋的父類方法:使用super.方法名(實參);
方法覆寫時應遵循的原則(一同兩小一大):
(一同):
方法簽名必須相同;
(兩小):
子類方法的返回值類型比父類方法的返回值類型更小或相等
子類方法聲明拋出的異常應比父類方法申明拋出的異常更小或相等;
(一大):子類方法的訪問權限應比父類方法更大或相等;
子類需要覆寫父類方法。
當父類的某個方法不適合于子類本身的特征行為時就當覆寫父類中應當改變的方法。
12、super關鍵字和調用父類構造方法
表示父類對象的默認引用
如果子類要調用父類被覆蓋的實例方法,可用super作為調用者調用父類被覆蓋的實例方法。
使用super調用父類方法
使用super調用父類的構造方法
調用構造方法
本類中調用另一個重載構造方法用this(參數列表)
子類構造方法調用父類構造方法用super(參數列表)
子類調用父類的構造方法時:
super必須放在第一句
Java在執行子類的構造方法前會先調用父類無參的構造方法,其目的是為了對繼承自父類的成員做初始化操作。
子類在創建對象的時候,默認調用父類的無參構造方法,要是子類構造方法中顯示指定調用父類其他構造方法,就調用指定的父類構造方法,取消調用父類無參構造方法。
Eg: package reviewDemo; class A{ String name; A(){ System.out.println("父類默認隱式的構造方法!"); } A(String name){ System.out.println("父類顯式的構造方法!"); } } class B extends A{ B(){ super(null); System.out.println("子類默認隱式的構造方法!"); } } public class Demo10 { public static void main(String[] args) { new B(); } }
13、面向對象之多態
多態:指同一個實體同時具有多種形式
好比,你去面館吃面,說我要吃面,那么;老板給我牛肉面,雞蛋面等都可以,
這就是說"面"有多種形態,也就是說實體有多種形態;
編譯時的類型由聲明該變量時使用的類型決定,運行時的類型由實際賦給變量的對象決定。
如果編譯時類型和運行時類型不同,就出現多態。
Eg:
前提:Student extends Person:
Person p = new Person()
;
Student s = new Student()
;
Person p = new Student()
;//多態
引用關系:父類變量指向子類實例對象
實現多態的機制:
父類的引用變量可以指向子類的實例對象,而程序調用的方法在運行期才動態綁定,就是引用變量所指向的真正實例對象的方法,也就是內存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法。
多態的作用:
把不同的子類對象都當作父類來看,可以屏蔽不同子類對象之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化。
只修改方法的實現,不必修改方法的聲明
繼承是多態產生的前提條件;
分類:
編譯時多態:方法重載
運行時多態:方法覆寫
Eg: package test; class Dog{ void eat(){ System.out.println("一般的狗吃一般的狗糧!"); } } class HashDog extends Dog{ void eat(){ System.out.println("哈士奇吃哈士奇的狗糧!"); } } class ZangAoDog extends Dog{ void eat(){ System.out.println("藏獒吃藏獒的狗糧!"); } } //定義一個動物園喂的方法 class Zoo{ void feed(Dog d){ d.eat(); } } public class Demo11 { public static void main(String[] args) { Dog hd = new HashDog(); Dog zd = new ZangAoDog(); Zoo z = new Zoo(); z.feed(hd); z.feed(zd); } }
輸出:
哈士奇吃哈士奇的狗糧!
藏獒吃藏獒的狗糧!
14、引用變量類型轉換
向上轉型(子類→父類):(自動完成)
父類名稱 父類對象 = 子類實例 ;
向下轉型(父類→子類):(強制完成)
子類名稱 子類對象 = (子類名稱)父類實例 ;
對象名 instanceof 類
判斷指定的變量名此時引用的真正類型是不是當前給出的類或子類;
我的總結:對象的類型和類必須有繼承關系
Eg: class A extends B{} B b = new A(); If(b instanceof A){ ... }
2、面向對象(2)
1、基本數據類型的包裝類
引言:Java提倡的萬物皆對象,但是數據類型的劃分出現了基本數據類型和引用數據類型,那么我們怎么能把基本數據類型稱為對象呢?
除了Integer和Character定義的名稱和對應的基本類型差異大,其他六種都是將首字母大寫就可以了。
Integer,Byte,Float,Double,Short,Long都是Number類的子類。(Number類后面講);
Character和Boolean都是Object直接子類;
8個類都是final修飾的(不可被繼承)。
2、基本數據類型和包裝類相互轉換
把基本數據類型 → 包裝類:
通過對應包裝類的構造方法實現
除了Character外,其他包裝類都可以傳入一個字符串參數構建包裝類對象。
包裝類 → 基本數據類型
包裝類的實例方法xxxValue(); // xxx表示包裝類對應的基本數據類型
Eg: boolean bool = false; Boolean b2 = new Boolean(bool); Integer i = new Integer(3); int i2 = i.intValue(); Boolean b1 = new Boolean("TRue");//true boolean b2 = b1.booleanValue(); Float f = new Float("3.14");//3.14 Integer i2 = new Integer("123s");//NumberFormatException
備注:
自動裝箱&自動拆箱
jdk1.5開始出現的特性:
自動裝箱:可把一個基本類型變量直接賦給對應的包裝類對象或則Object對象
自動拆箱:允許把 包裝類對象直接賦給對應的基本數據類型
Eg: Integer i = 3;//裝箱 int i2 = i;//拆箱 Object flag = new Boolean(false); if(flag instanceof Boolean){ Boolean b = (Boolean)flag; boolean b2 = b; }
3、基本類型和String之間的轉換
String → 基本類型,除了Character外所有的包裝類提供parseXxx(String s)靜態方法,用于把一個特定的字符串轉換成基本類型變量;
基本類型 → String,String 類有靜態方法valueOf(),用于將基本類型的變量轉換成String類型。
String str = "17"; int i = Integer.parseInt(str);//String --> 基本類型 String s1 = String.valueOf(i);//基本類型 --> String
4、Object類
所有類的公共父類,一旦一個類沒有顯示地繼承一個類則其直接父類一定是Object。
一切數據類型都可用Object接收
class OOXX extends Object{}等價于class ooXX {}
常見方法
public boolean equals(Object obj)
:對象比較
public int hashCode()
:取得該對象的Hash碼
public String toString()
:對象描述
Object類的 toString()方法:“對象的描述”
建議所有類都覆寫此方法
直接打印輸出對象時,會調用該對象的toString()方法。//可以不寫出來
打印對象的時候,實際調用的對象實際指向的類的自我描述;
全限定類名+@+十六進制的hashCode值,等價于
全限定類名+@+IntegertoHexString(該對象.hashCode)
equals也是判斷是否指向同一個對象
沒有實際意義,有必要可以重寫
public boolean equals(Object obj) {}
String 覆寫了 Object的equals方法:只比較字符的序列是否相同
==用于判斷兩個變量是否相等
基本類型:
引用類型:必須指向同一個對象,才true
只能比較有父子或平級關系的兩個對象
new String("1") == new String("1"); ?
5、代碼塊
代碼塊指的是使用"{}"括起來的一段代碼,根據代碼塊存在的位置可以分為4種:
普通代碼塊;
構造代碼塊;
靜態代碼塊;
同步代碼塊(線程同步的時候講解)。
代碼塊里變量的作用域:
只在自己所在區域(前后的{})內有效;
普通代碼塊:
普通代碼塊就是直接定義在方法或語句中定義的代碼塊:
public void show(){
普通代碼塊
}
構造代碼塊:
直接寫在類中的代碼塊:
優先于構造方法執行,每次實例化對象之前都會執行構造代碼塊。
Eg: public class Demo { { System.out.println("我是構造代碼塊"); } public Demo(){ System.out.println("我是構造方法"); } public static void main(String[] args) { Demo d1 = new Demo(); Demo d2 = new Demo(); } }
靜態代碼塊
使用static 修飾的構造代碼塊:
優先于主方法執行,優先于構造代碼塊執行,不管有創建多少對象,靜態代碼塊只執行一次,可用于給靜態變量賦值;
Eg: package reviewDemo; /** * 測試各代碼塊的優先級 * 優先級順序:靜態代碼塊 > 構造代碼塊 > 普通代碼塊 * 備注:無論創建幾個對象,靜態代碼塊只執行一次! */ public class Demo13 { Demo13(){ System.out.println("我是構造方法!"); } { System.out.println("我是構造代碼塊!");//實例化對象的時候才會去調用! } static{ System.out.println("我是靜態代碼塊!"); } public static void main(String[] args) { new Demo13(); new Demo13();//再次創建對象,證明無論創建幾次對象,靜態代碼塊都只執行一次 System.out.println("我是普通代碼塊!"); } }
輸出:
我是靜態代碼塊!
我是構造代碼塊!
我是構造方法!
我是構造代碼塊!
我是構造方法!
我是普通代碼塊!
6、構造方法的私有化
有的時候我們為了避免外界創建某類的實例,就將某類的構造方法私有化,即將它的構造方法用private修飾:
外界如何用到?
提供get方法!不提供的話外界就沒法創建對象!(對反射無效)
Eg:package reviewDemo; class Stu{ //將構造方法私有化 private Stu(){ } } public class Demo15 { public static void main(String[] args) { Stu s = new Stu(); } }
Singleton模式(單例模式) 餓漢式和懶漢式
目的:整個應用中有且只有一個實例,所有指向該類型實例的引用都指向這個實例。
好比一個國家就只有一個皇帝(XXX),此時每個人叫的“皇帝”都是指叫的XXX本人;
常見單例模式類型:
餓漢式單例:直接將對象定義出來
懶漢式單例:只給出變量,并不將其初始化;
我的總結:
餓漢式,static修飾,隨著類的加載而加載,會損耗性能,但是方法相對簡單
懶漢式 第一次用的時候相對較慢,因為需要加載!線程,不安全!
package reviewDemo; //單例模式 //餓漢式,直接把對象構造出來 class SingleDemo{ private static SingleDemo s1 = new SingleDemo(); private SingleDemo(){ //提供私有化的構造方法,那么外界就不能構造對象了! } public static SingleDemo getS1() { return s1; } } //懶漢式,先定義,但是不創建對象 class SingleDemo2{ private static SingleDemo2 s3 ; private SingleDemo2(){ //提供私有化的構造方法,那么外界就不能構造對象了! } public static SingleDemo2 getS3() {//這是一個方法,返回值為創建的對象! if(s3 == null){ s3 = new SingleDemo2(); }//和餓漢式的區別,此時才來創建對象! return s3; } } public class Demo14 { public static void main(String[] args) { SingleDemo s1 = SingleDemo.getS1(); SingleDemo s2 = SingleDemo.getS1(); SingleDemo2 s3 = SingleDemo2.getS3(); SingleDemo2 s4 = SingleDemo2.getS3(); System.out.println(s1 == s2); System.out.println(s3 == s4); } } 輸出:true true 備注:枚舉更加安全些 package reviewDemo; enum Stu{ jake; //將構造方法私有化起來,反射也不能創建對象,安全 private Stu(){ } } public class Demo15 { public static void main(String[] args) { } }
8、final 關鍵字
final可以修飾類,方法,變量。
final修飾類不可以被繼承,但是可以繼承其他類。
final修飾的方法不可以被覆寫,但可以覆寫父類方法。
final修飾的變量稱為常量,這些變量只能賦值一次。
內部類在局部時,只可以訪問被final修飾的局部變量。
final修飾的引用類型變量,表示該變量的引用不能變,而不是該變量的值不能變;
Eg: package reviewDemo; final class Name{ } class NewName extends Name{//ERROR,報錯,因為Name有final修飾 } public class Demo15 { public static void main(String[] args) { } }
9、抽象類
當編寫一個類時,我們往往會為該類定義一些方法,這些方法是用來描述該類的行為方式,那么這些方法都有具體的方法體。
但是有的時候,某個父類只是知道子類應該包含怎么樣的方法,但是無法準確知道子類如何實現這些方法。
抽象方法的定義:通過abstract關鍵字來修飾的類稱為抽象類;
總結:抽象類用private修飾,里面可以有用private修飾的方法(沒有方法體),強制子類進行覆寫;
可以理解為:具有某些公共方法的一個總結類。
可以定義被abstract修飾的抽象方法
抽象方法只有返回類型和方法簽名,沒有方法體。
備注:
抽象類可以含有普通方法
抽象類不能創建實例對象(不能new)
需要子類覆蓋掉所有的抽象方法后才可以創建子類對象,否則子類也必須作為抽象類
列舉常見的幾個抽象類:
流的四個基本父類
InputStream,OutputStream,Reader,Writer
我的總結:
抽象類是類的一種特殊情況:據有類的一切特點,但是不能實例化;一般的都得帶有抽象方法。
抽象類不可以實例化,有時看到的近似實例化是多態機制的體現,并不是真正的實例化。
Eg: Socket s = new Socket(); OutputStream os = s.getOutputStream(); 左邊是OutputStream類型變量的聲明,右邊是獲取抽象類OutputStream的一個實例對象! package testDemo2; abstract class Person{ } class Student extends Person{ } public class Demo2 { public static void main(String[] args) { Person p = new Student();//體現的是多態,父類聲明實例化子類對象。而不是抽象類實例化 } }
abstract方法
分析事物時,發現了共性內容,就出現向上抽取。會有這樣一種特殊情況,就是功能聲明相同,但功能主體不同。
那么這時也可以抽取,但只抽取方法聲明,不抽取方法主體。那么此方法就是一個抽象方法。
abstract [非private訪問修飾符] 返回值類型 方法名稱(參數列表);
抽象方法要存放在抽象類中。
抽象方法也可以存在于接口中
Eg: package reviewDemo; abstract class Person3{ abstract void show(); abstract void inof(); void turn(){ } } class NewP extends Person3{ @Override void show() { } @Override void inof() { } //不覆寫的話會報錯 } public class Demo15 { public static void main(String[] args) { //new Person3();報錯!因為抽象類不可以實例化 } }
10、抽象類的體現-模板模式
抽象類是多個具體子類抽象出來的父類,具有高層次的抽象性;以該抽象類作為子類的模板可以避免子類設計的隨意性;
抽象類的體現主要就是模板模式設計,抽象類作為多個子類的通用模板,子類在抽象類的基礎上進行拓展,但是子類在總體上大致保留抽象類的行為方式;
編寫一個抽象父類,該父類提供了多個子類的通用方法,并把一個或多個抽象方法留給子類去實現,這就是模板設計模式;
模板模式應用的簡單規則:
1.抽象父類可以只定義需要使用的某些方法,其余留給子類去實現;
2.父類提供的方法只是定義了一個通用算法,其實現必須依賴子類的輔助;
我的總結:
如果父類的方法不想被子類覆寫,那么可以在前面加上final關鍵字修飾。
Eg: package reviewDemo; //模板模式 //抽象類中包含很多的抽象方法,子類必須去覆寫! abstract class Method{ abstract double mul();//返回值類型如果是void的話,下面報錯,因為沒有返回值,無法引用! abstract double divid(); void show(){ System.out.println("面積是:"+mul());//周長 System.out.println("面積是:"+divid());//面積 } } class Square extends Method{ double d; public Square(double d) { super(); this.d = d; } @Override double mul() { return d * d; } @Override double divid() { return 4 * d; } } class Cirle extends Method{ double r; public Cirle(double r) { super(); this.r = r; } @Override double mul() { return 2 * 3.14 * r; } @Override double divid() { return 3.14 * r * r; } } public class Demo16 { public static void main(String[] args) { Square s = new Square(5); s.show(); Cirle c = new Cirle(4); c.show(); } }
關于java面向對象的意思是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。