java面向對象深刻

java面向對象深刻

大綱java


package與import

package

概述c++

package存在的意義是防止命名衝突形成使用不便。程序員

package相似一個文件夾,文件夾內有各類文件。package與package的附屬關係用「.」鏈接,相似父文件夾中的子文件夾。好比說 java.lang.String就是java文件夾中的lang文件夾中的String文件。java.io.InputStream則是java文件夾中的io文件夾中的InputStream文件。算法

同一個文件夾內沒法存在同名的文件,而不一樣名的文件夾裏容許存在同名文件,所以不一樣文件夾(即不一樣package中容許出現相同class名)。sql

爲了便於管理大型軟件系統中數目衆多的類,解決類的命名衝突問題,Java 引入包(package)機制,提供類的多重類命名空間。 數據庫

格式編程

通常的命名爲:公司域名倒寫+功能名|模塊名。網絡

package 語句做爲 Java 源文件的第一條語句,指明該文件中定義的類所在的包。(若缺省該語句,則指定爲無名包)。併發

<span > <span >package</span> <span >pkg1</span>[.<span >pkg2</span>[.<span >pkg3…</span>]];</span>

例:jvm

<span > <span >package</span> <span >com</span>.<span >java01</span>.<span >test</span>;</span>

Java 編譯器把包對應於文件系統的目錄管理,package 語句中,用’.’來指明包(目錄)的層次,例如使用語句: package com.java01 ,則該文件中全部的類位於.\com\java01 目錄下

注意:

  • 不要定義與 jdk 相同的包,相同的類,不然會引發不少你以爲莫名其妙的問題
  • 寫項目時都要加包,不要使用默認包。
  • com.oop和com.oop.test,這兩個包沒有包含關係,是兩個徹底獨立的包。只是邏輯上看起來後者是前者的一部分。

import

若是一個類存在包名,則在其餘包下使用該類時,必須使用全額限定名(簡稱全名或完整類名,com.java01.MyClass),編譯器才能找到該類;也可使用 import 在文件的開頭引入要使用到的類。

<span > <span >import</span> <span >java</span>.<span >util</span>.<span >Scanner</span>;
 <span >import</span> <span >java</span>.<span >io</span>.<span >*</span>; <span >//模糊匹配當前io包下全部類</span>
 <span >public</span> <span >class</span> <span >ImportDemo</span> {
     <span >public</span> <span >static</span> <span >void</span> <span >main</span>(<span >String</span>[] <span >args</span>) {
         <span >Scanner</span> <span >sc</span><span >=</span><span >new</span> <span >Scanner</span>(<span >System</span>.<span >in</span>); <span >//由於使用import關鍵字導包,可使用</span>
         <span >java</span>.<span >util</span>.<span >ArrayList</span> <span >list</span><span >=</span><span >new</span> <span >java</span>.<span >util</span>.<span >ArrayList</span>(); <span >//權限定名</span>
         <span >//導入集合 注意:導入是不要導錯包</span>
         <span >//使用*,模糊匹配</span>
         <span >File</span> <span >file</span><span >=</span><span >new</span> <span >File</span>(<span >"D://test.txt"</span>);
         <span >InputStream</span> <span >isInputStream</span><span >=</span><span >new</span> <span >FileInputStream</span>(<span >file</span>);
     }
 }</span>

不須要使用 import 的類有:

  1. 語言包 (java.lang)下的類 (String,System...)
  2. 同包下的類

靜態導入: import 語句不只能夠導入類,還增長了導入靜態方法的功能

<span > <span >//導入靜態屬性</span>
 <span >import</span> <span >static</span> <span >java</span>.<span >lang</span>.<span >Math</span>.<span >PI</span>;
 <span >import</span> <span >static</span> <span >java</span>.<span >lang</span>.<span >System</span>.<span >out</span>;
 <span >//導入靜態方法</span>
 <span >import</span> <span >static</span> <span >java</span>.<span >lang</span>.<span >Math</span>.<span >sin</span>;
 ​
 <span >public</span> <span >class</span> <span >ImportDemo</span> {
     <span >public</span> <span >static</span> <span >void</span> <span >main</span>(<span >String</span>[] <span >args</span>) {
         <span >out</span>.<span >println</span>(<span >PI</span>);
         <span >sin</span>(<span >1.1</span>);
     }
 }</span>

總結

  • 若是想將一個類放入包中,在類的源文件首行使用package
  • 必須保證該類的 class 文件位於正確的目錄下
  • 另外的類想訪問的話:

    1. 寫全名
    2. 引入

      • 模糊匹配(會將該包下全部用到的類引入進來),會下降編譯速度,可是不會影響運行速度
      • 具體類名
      • 靜態導入
    3. 同包下的類不須要導入

JDK 中經常使用的包簡單介紹:

  1. java.lang –語言包:語言中經常使用的功能,如:String、Math、System、Integer、Thread…
  2. java.util – 工具包:提供一些實用的工具類,如:容器(List、Set、Map…),日期類
  3. java.io – 輸入輸出包:提供操做讀取文件的相關類,如:File、InputStream、OutputStream…
  4. java.net – 網絡包: 操 做 遠 程 資 源 的 類 , 如:InetSocketAddress、 DatagramPacket、 ServerSocket…
  5. java.sql – 數據庫包:操做JDBC的類,Connection、Statement、ResultSet….

垃圾回收機制(gc)

概述

Garbage Collection 垃圾回收機制

每一個程序員都遇到過內存溢出的狀況,程序運行時,內存空間是有限的,那麼如何及時的把再也不使用的對象清除將內存釋放出來,這就是GC要作的事。

提及垃圾回收機制(GC),大部分人都把這項技術當作Java語言的伴生產物。事實上,GC的歷史比Java久遠,早在1960年Lisp這門語言中就使用了內存動態分配和垃圾回收技術。

程序員們知道,jvm內存結構分爲五大區域:程序計數器、虛擬機棧、本地方法棧、堆區、方法區。其中虛擬機棧、本地方法棧與程序計數器這3個區域隨線程而生、隨線程而滅,所以就不須要考慮過多內存垃圾回收問題,由於一個方法調用結束或者線程結束時,內存天然就跟隨着回收了。

咱們就把重點放在方法區與堆區,這部份內存的分配和回收是動態的,正是垃圾收集器所需關注的部分。

GC主要作了清理對象,整理內存的工做。

不一樣語言下對象空間的釋放:

  • 傳統的C/C++語言,須要程序員負責回收已經分配內存。顯式回收垃圾回收的缺點:

    1. 程序忘記及時回收,從而致使內存泄露,下降系統性能。
    2. 程序錯誤回收程序核心類庫的內存,致使系統崩潰。
  • Java語言不須要程序員直接控制內存回收,是由JRE在後臺自動回收再也不使用的內存,稱爲垃圾

    回收機制(Garbage Collection)。

    1. 能夠提升編程效率。
    2. 保護程序的完整性。
    3. 其開銷影響性能。Java虛擬機必須跟蹤程序中有用的對象,肯定哪些是無用的。

垃圾回收機制關鍵點:

  • 垃圾回收機制只回收JVM堆內存裏的對象空間。
  • 對其餘物理鏈接,好比數據庫鏈接、輸入流輸出流、Socket鏈接無能爲力
  • 如今的JVM有多種垃圾回收實現算法,表現各異。
  • 垃圾回收發生具備不可預知性,程序沒法精確控制垃圾回收機制執行。
  • 能夠將對象的引用變量設置爲null,暗示垃圾回收機制能夠回收該對象。
  • 程序員能夠經過System.gc()或者Runtime.getRuntime().gc()來通知系統進行垃圾回收,會有一些效果,可是系統是否進行垃圾回收依然不肯定。
  • 垃圾回收機制回收任何對象以前,總會先調用它的finalize方法(若是覆蓋該方法,讓一個新的引用變量從新引用該對象,則會從新激活對象)。
  • 永遠不要主動調用某個對象的finalize方法,應該交給垃圾回收機制調用。

block與debug

block

塊{},在java中自成做用域,能夠分爲

靜態代碼塊

構造代碼塊

普通語句塊

同步代碼塊

聲明位置

類中,方法外

類中,方法外

方法中

fynchronized(){}

做用

整個類進行某些初始化操做(靜態屬性賦值...)

構造代碼塊是爲對象初始化操做(爲靜態或非靜態成員屬性賦值...)

聲明一些臨時變量等..

控制併發

執行時機

類第一次加載時,只執行一次,若是多個靜態塊,從上倒下一次執行

建立對象時,執行構造器代碼以前執行,若有多個,從上倒下一次執行

跟隨方法執行

跟對方法執行

注意:

  • 類第一次被載入時先執行static代碼塊;類屢次載入時,static代碼塊只執行一次;static塊常常用來進行static變量的初始化。
  • 是在類初始化時執行,不是在建立對象時執行。
  • 靜態初始化塊中不能訪問非static成員。
  • 構造塊被被編譯到將要執行的構造器代碼以前執行

靜態塊,僅在類的第一次使用時加載。 構造塊,先於構造器執行,每建立一個對象執行一次

debug

在學習或開發過程當中,遇到bug是避免不了的,爲了可以快速調試,可使用debug調試工具。

調試一個Java程序很是簡單的,主要有設置斷點、啓動調試、單步執行、結束調試幾步。

debug界面窗口:

1)設置斷點

2)啓動調試

Eclipse提供幾種方式來啓動程序(Launch)的調試,分別是經過菜單(Run –> Debug)、圖標(「綠色臭蟲」)、右鍵->Debug As。

彈出提示,須要切換到調試(Debug)工做區,勾選「Remember my decision」,記住選擇,則下次再也不提示,而後點擊【Yes】。

3)單步執行

主要使用前面講過的幾個視圖進行調試,其中debug視圖中的幾個按鈕有快捷鍵:

Step Return(F7) : 表示退出當前方法,返回到調用層。

Step Over (F6) : 表示運行下一行代碼。

Step Into (F5) : 表示進入當前方法。

4)結束調試

經過Terminate命令終止對本地程序的調試。

面向對象-繼承性

繼承

「樹上一隻鳥樹下兩隻兔子,請問幾種動物 , 請問幾種生物?」 這裏面就存在了繼承的概念。

繼承:子承父業

繼承的本質在於抽象。類是對對象的抽象,繼承是對某一批類的抽象,從而實現對現實世界更好的建模。

繼承的做用 : 使用繼承能夠提升代碼的複用性。

如何使用繼承:

父類|超類|基類:根據一些列子類抽象,抽取像的部分,定義在父類中

子類|派生類:子類繼承父類,有權使用父類中的內容,能夠定義子類新增內容,因此說子類是父類的延續+擴展

extends 關鍵字的意思是「擴展」。子類是父類的擴展。

java 中使用 extends 關鍵字實現類的繼承機制,語法規則:

<span > <span ><</span><span >modifier</span><span >></span> <span >class</span> <span ><</span><span >name</span><span >></span> [<span >extends</span> <span ><</span><span >superclass</span><span >></span>]{} </span>

<span > <span >//父類</span>
 <span >class</span> <span >Person</span>{
     <span >public</span> <span >String</span> <span >name</span>;
     <span >public</span> <span >int</span> <span >age</span>;
     
     <span >public</span> <span >void</span> <span >sleep</span>(){
         <span >System</span>.<span >out</span>.<span >println</span>(<span >"休息"</span>);
     }
 }</span>

<span > <span >//子類</span>
 <span >//教師類</span>
 <span >class</span> <span >Teacher</span> <span >extends</span> <span >Person</span>{
     <span >public</span> <span >String</span> <span >subject</span>;
     
     <span >public</span> <span >Teacher</span>() {
     }
     
     <span >public</span> <span >void</span> <span >teach</span>(){
         <span >System</span>.<span >out</span>.<span >println</span>(<span >"傳授知識"</span>);
     }
     
 }
 ​
 <span >//學生類</span>
 <span >class</span> <span >Student</span> <span >extends</span> <span >Person</span>{
     <span >public</span> <span >String</span> <span >school</span>;
     
     <span >public</span> <span >Student</span>() {
     }
     
     <span >public</span> <span >void</span> <span >study</span>(){
         <span >System</span>.<span >out</span>.<span >println</span>(<span >"在知識的海洋暢遊!"</span>);
     }
 }</span>

注意:

  • 子類繼承父類的成員變量和成員方法,但不繼承父類的構造方法
  • java中只有單繼承 ,沒有像c++那樣的多繼承。多繼承會引發混亂,使得繼承鏈過於複雜,系統難於維護。就像咱們現實中,若是你有多個父母親,那是一個多麼混亂的世界啊。多繼承,就是爲了實現代碼的複用性,卻引入了複雜性,使得系統類之間的關係混亂。
  • java中的多繼承,能夠經過接口來實現
  • 若是定義一個類時,沒有調用extends,則它的父類是:java.lang.Object。

繼承的特色:

優勢:

  • 經過繼承能夠簡化類的定義,實現代碼的重用|提升代碼複用性
  • 能夠更好的擴展程序
  • 子類一旦繼承父類,能夠有權使用父類中的成員,也能夠擴展定義子類獨有內容
  • java是單繼承繼承,實現簡單

缺點:

  • 子類與父類之間緊密耦合(耦合度高),子類依賴於父類的實現,子類缺少獨立性。
  • 不便於後期維護
  • 單繼承一個子類只能有一個父類,不夠靈活,不便於後期維護

super關鍵字

super

super是指向父類的引用。

super能夠在子類構造器中調用父類某個構造器

若是構造方法沒有顯示地調用父類的構造方法,那麼編譯器會自動爲它加上一個默認的super()方法調用。若是父類由沒有默認的無參構造方法,編譯器就會報錯,super()語句必須是構造方法的第一個子句。

super能夠用來區分子父類中同名成員

若是不存在同名問題,能夠直接在子類中調用父類內容,super默認省略

若是存在同名問題,在子類中調用同名成員,默認this.恆源 調用當前子類同名成員,先要調用父類同名成員,必須定義爲super.成員

<span > <span >//父類</span>
 <span >public</span> <span >class</span> <span >Animal</span> {
     <span >int</span> <span >eye</span> <span >=</span> <span >2</span>;
     <span >public</span> <span >Animal</span>(){
         <span >super</span>();
         <span >System</span>.<span >out</span>.<span >println</span>(<span >"動物"</span>);
     }
     
     <span >public</span> <span >void</span> <span >run</span>(){
         <span >System</span>.<span >out</span>.<span >println</span>(<span >"動物有不一樣走路方式"</span>);
     }
     
     <span >public</span> <span >static</span> <span >void</span> <span >main</span>(<span >String</span>[] <span >args</span>) {
         <span >Bird</span> <span >b</span> <span >=</span> <span >new</span> <span >Bird</span>();
         <span >b</span>.<span >run</span>();
     }
 }
 <span >//子類</span>
 <span >class</span> <span >Bird</span> <span >extends</span> <span >Animal</span>{
     <span >public</span> <span >Bird</span>(){
         <span >super</span>();
         <span >System</span>.<span >out</span>.<span >println</span>(<span >"鳥類"</span>);
     }
 ​
     <span >public</span> <span >void</span> <span >run</span>() {
         <span >super</span>.<span >run</span>(); <span >// 經過super能夠用父類方法和屬性</span>
         <span >System</span>.<span >out</span>.<span >println</span>(<span >"鳥是飛飛飛飛飛飛"</span>);
         <span >System</span>.<span >out</span>.<span >println</span>(<span >"鳥類有"</span><span >+</span><span >super</span>.<span >eye</span><span >+</span><span >"隻眼睛"</span>);
     }
    
 }</span>

Bird--> Animal --> Object 圖形分析以下

構造方法調用順序:

  • 根據super的說明,構造方法第一句 老是:super(…)來調用父類對應的構造方法。
  • 先向上追溯到Object,而後再依次向下執行類的初始化塊和構造方法,直到當前子類爲止。

this和super之間的區別

相同點:

  1. this和super都能用來調動其餘共構造器,都要在首行出現
  2. this和super均可以用來區分同名問題,不區分同名時候能夠省略
  3. this和super都指的是對象,因此,均不能夠在static環境中使用。包括:static變量,static方法,static語句

塊。

不一樣點:

  1. this(參數)構造器第一行調用本類中其餘構造器,super(參數)構造器第一行調用父類中某個構造器
  2. this用來區分紅員和局部同名問題,super用來區分子父類中同名問題

注意:

  • this和super不能同時出如今一個構造函數裏面,由於this必然會調用其它的構造函數,其它的構造函數必然也會有super語句的存在,因此在同一個構造函數裏面有相同的語句,就失去了語句的意義,編譯器也不會過。
  • 從本質上講,this是一個指向本對象的指針, 然而super是一個Java關鍵字

重寫與final關鍵字

重寫Override

父類的功能實現不知足子類的要求,能夠在子類中按需改寫,這就是方法的重寫。

實現重寫的三個條件:

  • 不一樣的兩個類
  • 繼承關係|實現關係
  • 方法簽名相同

@Override:註解,強制檢查是否爲重寫方法

注意:

  • 子類重寫的方法會對父類的方法進行屏蔽。
  • 當子類對象調用時,會調用子類中重寫的方法,子類沒有找父類。
<span >public class OverrideTest {
    public static void main(String[] args) {
        Sicong sicong=new Sicong();
        sicong.getMoney(); //調用子類中重寫方法
    }
}
//父類
class Jianlin{
    public void getMoney(){
        System.out.println("先定一個小目標,賺他個一個億");
    }
}
//子類
class Sicong extends Jianlin{
    @Override  //強制檢查是否爲重寫方法
    public void getMoney(){
        super.getMoney();//在父類的原賺錢方法上擴展新功能,老功能不變
        System.out.println("我認識的人都沒我有錢");
    }
}
</span>

重寫的三個"=" : 「==」:方法名、形參列表相同。

「≤」:拋出的異常類型與返回值類型,返回值類型若是爲基本類型必須相同,引用數據類型子類小於等於父類。

「≥」:訪問權限,子類大於等於父類。

如下修飾符、修飾的內容不能重寫:

  1. private修飾的方法不能被重寫
  2. final修飾的方法不能被重寫
  3. static修飾的方法不能被重寫(子類若是出現和父類靜態方法同名狀況,那麼子類中的方法也必須爲靜態的)

final關鍵字

final 表示最終的。

final能夠用來修飾變量,方法,類。

修飾變量:變量一旦被初始化便不可改變,至關定義了一常量。

<span >final int x=3;
//x=4; 常量不能改變
</span>

修飾方法 : final方法是在子類中不能被覆蓋的方法

<span >final void eat() { … }
</span>

修飾類,表示該類不能被繼承

<span >final class Person{ … }
</span>

Object類

Object 類是全部 Java 類的根基類

若是在類的聲明中未使用 extends 關鍵字指明其基類,則默認基類爲 Object 類

toString(): 當打印對象的引用時,默認調用toString()方法

  • 默認返回:包名+類名+@+哈希碼(根據對象的內存地址生成,惟一不重複)
  • 能夠重寫,實現義字符串的形式返回對對象(打印對象全部成員屬性的值)
<span >User p1=new User("張三",20);
System.out.println(p1);
//至關於
System.out.println(p1.toString());
</span>

equals:比較相等是否相等**

  • 默認地址比較(」第一個盒子的比較」)
  • 重寫能夠是實現比較兩對象的內容是否一致
<span > object1.equals(object2) 
 如 : p1.equals(p2)
• 比較所指對象的內容是否同樣,具體看equals的方法重寫
 object1 == object2
 如:p1==p2
• 比較p1和p2的值即內存地址是否相等,便是否是指向同一對象。
</span>

注意:自定義類須重寫equals(),不然沒法實現比較其內容

<span >class User{
    String name;
    int age;
    public User() {
        // TODO Auto-generated constructor stub
    }
    public User(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    //重寫toString
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
    //重寫equals
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}
</span>

相關文章
相關標籤/搜索