java面向對象(基礎)

對象和類

  • 類:我們叫做class。
  • 對象:我們叫做Object,instance(實例)。以後我們說某個類的對象,某個類的實例。是一樣的意思。
    • 1.對象是具體的事物;類是對對象的抽象;
    • 2.類可以看成一類對象的模板,對象可以看成該類的一個具體實例。
    • 3.類是用於描述同一類型的對象的一個抽象概念,類中定義了這一類對象所應具有的共同的屬性、方法。
類定義
// 每一個源文件必須有且只有一個public class,並且類名和文件名保持一致!
public class Car { 
}
class Teacher{ // 一個Java文件可以同時定義多個class
}
class Student {
}
  • 這是一個空類,沒有任何實際意義。所以,我們需要定義類的具體信息。對於一個類來說,一般有三種常見的成員:屬性field、方法method、構造器constructor。這三種成員都可以定義零個或多個。
  • 編寫一個簡單類
public class KkStu {
    //屬性(成員變量)
    int id;
    String name;
    int age;  
    //方法
    void study(){
        System.out.println("我正在學習!");
    }  
    //構造方法
   KkStu(){
   }
}
屬性(field,或者叫成員變量)
  • 屬性用於定義該類或該類對象包含的數據或者說靜態特徵。屬性作用範圍是整個類體。

  • 在定義成員變量時可以對其初始化,如果不對其初始化,Java使用默認的值對其初始化。

  • 屬性定義格式:
    [修飾符] 屬性類型 屬性名 = [默認值] ;

    數據類型 默認值
    整型 0
    浮點型 0.0
    字符型 ‘\u0000’
    布爾型 false
    所有引用型 null
面向對象的內存分析
  • Java虛擬機的內存可以分爲三個區域:棧stack、堆heap、方法區method area。

  • 棧的特點如下:
    - 1. 棧描述的是方法執行的內存模型。每個方法被調用都會創建一個棧幀(存儲局部變量、操作數、方法出口等)
    - 2. JVM爲每個線程創建一個棧,用於存放該線程執行方法的信息(實際參數、局部變量等)
    - 3. 棧屬於線程私有,不能實現線程間的共享!
    - 4. 棧的存儲特性是“先進後出,後進先出”
    - 5. 棧是由系統自動分配,速度快!棧是一個連續的內存空間!

  • 堆的特點如下:
    - 1. 堆用於存儲創建好的對象和數組(數組也是對象)
    - 2. JVM只有一個堆,被所有線程共享
    - 3. 堆是一個不連續的內存空間,分配靈活,速度慢!

  • 方法區(又叫靜態區)特點如下:
    - 1. JVM只有一個方法區,被所有線程共享!
    - 2. 方法區實際也是堆,只是用於存儲類、常量相關的信息!
    - 3. 用來存放程序中永遠是不變或唯一的內容。(類信息【Class對象】、靜態變量、字符串常量等)

public class KkStu {
	//屬性field
	int id;
	String name;
	int age;
	
	Computer comp;
	//方法
	void study() {
		System.out.println("學習中...使用電腦" + comp.brand);
	}
	void play() {
		System.out.println("玩耍中...");
	}
	//程序執行的入口,必須有
	public static void main(String[] args) {
		KkStu stu1 = new KkStu();
		stu1.id = 1010;
		stu1.age = 18;
		stu1.name = "kk";
		
		Computer c1 =new Computer();
		c1.brand = "聯想";
		stu1.comp = c1;
				
		
		stu1.study();
		stu1.play();
	}
}

class Computer {
	String brand;
}

對應內存情況
在這裏插入圖片描述
在這裏插入圖片描述

構造方法
  • 構造器也叫構造方法(constructor),用於對象的初始化。構造器是一個創建對象時被自動調用的特殊方法,目的是對象的初始化。構造器的名稱應與類的名稱一致。Java通過new關鍵字來調用構造器,從而返回該類的實例,是一種特殊的方法。
  • 聲明格式
    [修飾符] 類名(形參列表){ //n條語句}
  • 要點:
    - 1. 通過new關鍵字調用!!
    - 2. 構造器雖然有返回值,但是不能定義返回值類型(返回值的類型肯定是本類),不能在構造器裏使用return返回某個值。
    - 3. 如果我們沒有定義構造器,則編譯器會自動定義一個無參的構造函數。如果已定義則編譯器不會自動添加!
    - 4. 構造器的方法名必須和類名一致!
構造方法重載
  • 造方法也是方法,只不過有特殊的作用而已。與普通方法一樣,構造方法也可以重載。
  • 示例
public class User {
    int id; // id
    String name; // 賬戶名
    String pwd; // 密碼
    public User() {
 
    }
    public User(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }
    public static void main(String[] args) {
        User u1 = new User();
        User u2 = new User(101, "天使");
        User u3 = new User(100, "天使", "123456");     
    }
}
垃圾回收機制(Garbage Collection)
  • Java引入了垃圾回收機制,令C++程序員最頭疼的內存管理問題迎刃而解。Java程序員可以將更多的精力放到業務邏輯上而不是內存管理工作上,大大的提高了開發效率。
垃圾回收原理和算法
  • 內存管理
    • Java的內存管理很大程度指的就是對象的管理,其中包括對象空間的分配和釋放。
    • 對象空間的分配:使用new關鍵字創建對象即可
    • 對象空間的釋放:將對象賦值null即可。垃圾回收器將負責回收所有”不可達”對象的內存空間。
  • 垃圾回收過程
    • 任何一種垃圾回收算法一般要做兩件基本事情:
      - 1. 發現無用的對象
      - 2. 回收無用對象佔用的內存空間。
    • 垃圾回收機制保證可以將“無用的對象”進行回收。無用的對象指的就是沒有任何變量引用該對象。Java的垃圾回收器通過相關算法發現無用對象,並進行清除和整理。
  • 垃圾回收相關算法
    - 1. 引用計數法: 堆中每個對象都有一個引用計數。被引用一次,計數加1. 被引用變量值變爲null,則計數減1,直到計數爲0,則表示變成無用對象。優點是算法簡單,缺點是“循環引用的無用對象”無法別識別。
    - 循環引用示例
    public class Student {
        String name;
        Student friend;
         
        public static void main(String[] args) {
            Student s1 = new Student();
            Student s2 = new Student();
             
            s1.friend = s2;
            s2.friend = s1;        
            s1 = null;
            s2 = null;
        }
    }
    
    s1和s2互相引用對方,導致他們引用計數不爲0,但是實際已經無用,但無法被識別。
    - 2. 引用可達法(根搜索算法): 程序把所有的引用關係看作一張圖,從一個節點GC ROOT開始,尋找對應的引用節點,找到這個節點以後,繼續尋找這個節點的引用節點,當所有的引用節點尋找完畢之後,剩餘的節點則被認爲是沒有被引用到的節點,即無用的節點
通用的分代垃圾回收機制
  • 分代垃圾回收機制,是基於這樣一個事實:不同的對象的生命週期是不一樣的。因此,不同生命週期的對象可以採取不同的回收算法,以便提高回收效率。我們將對象分爲三種狀態:年輕代、年老代、持久代。JVM將堆內存劃分爲 Eden、Survivor 和 Tenured/Old 空間。
    在這裏插入圖片描述
  • 垃圾回收過程:
    • 1、新創建的對象,絕大多數都會存儲在Eden中,
    • 2、當Eden滿了(達到一定比例)不能創建新對象,則觸發垃圾回收(GC),將無用對象清理掉, 然後剩餘對象複製到某個Survivor中,如S1,同時清空Eden區
    • 3、當Eden區再次滿了,會將S1中的不能清空的對象存到另外一個Survivor中,如S2,同時將Eden區中的不能清空的對象,也複製到S1中,保證Eden和S1,均被清空。
    • 4、重複多次(默認15次)Survivor中沒有被清理的對象,則會複製到老年代Old(Tenured)區中,
    • 5、當Old區滿了,則會觸發一個一次完整地垃圾回收(FullGC),之前新生代的垃圾回收稱爲(minorGC)
JVM調優和Full GC
  • 在對JVM調優的過程中,很大一部分工作就是對於Full GC的調節。有如下原因可能導致Full GC:
    • 1.年老代(Tenured)被寫滿
    • 2.持久代(Perm)被寫滿
    • 3.System.gc()被顯式調用(程序建議GC啓動,不是調用GC)
    • 4.上一次GC之後Heap的各域分配策略動態變化
開發中容易造成內存泄露的操作
  • 創建大量無用對象

    • 比如,我們在需要大量拼接字符串時,使用了String而不是StringBuilder。
    String str = "";
    for (int i = 0; i < 10000; i++) {   
        str += i;     //相當於產生了10000個String對象
    }
    
  • 靜態集合類的使用

    • 像HashMap、Vector、List等的使用最容易出現內存泄露,這些靜態變量的生命週期和應用程序一致,所有的對象Object也不能被釋放。
  • 各種連接對象(IO流對象、數據庫連接對象、網絡連接對象)未關閉

    • IO流對象、數據庫連接對象、網絡連接對象等連接對象屬於物理連接,和硬盤或者網絡連接,不使用的時候一定要關閉。
  • 監聽器的使用

    • 釋放對象時,沒有刪除相應的監聽器。
  • 要點
    - 1. 程序員無權調用垃圾回收器。
    - 2. 程序員可以調用System.gc(),該方法只是通知JVM,並不是運行垃圾回收器。儘量少用,會申請啓動Full GC,成本高,影響系統性能。
    - 3. finalize方法,是Java提供給程序員用來釋放對象或資源的方法,但是儘量少用。

this 關鍵字
  • 對象創建的過程和this的本質
    • 構造方法是創建Java對象的重要途徑,通過new關鍵字調用構造器時,構造器也確實返回該類的對象,但這個對象並不是完全由構造器負責創建。創建一個對象分爲如下四步:
    •   - 1. 分配對象空間,並將對象成員變量初始化爲0或空
        - 2. 執行屬性值的顯示初始化
        - 3. 執行構造方法
        - 4. 返回對象的地址給相關的變量
      
  • this的本質就是“創建好的對象的地址”! 由於在構造方法調用前,對象已經創建。因此,在構造方法中也可以使用this代表“當前對象” 。
    • this最常的用法:
      - 1. 在程序中產生二義性之處,應使用this來指明當前對象;普通方法中,this總是指向調用該方法的對象。構造方法中,this總是指向正要初始化的對象。
      - 2. 使用this關鍵字調用重載的構造方法,避免相同的初始化代碼。但只能在構造方法中用,並且必須位於構造方法的第一句。
      - 3. this不能用於static方法中。
      public class User {
      int id;        //id
      String name;   //賬戶名
      String pwd;   //密碼
      
      public User() {
      }
      public User(int id, String name) {
          System.out.println("正在初始化已經創建好的對象:"+this);
          this.id = id;   //不寫this,無法區分局部變量id和成員變量id
          this.name = name;
      }
      public void login(){
          System.out.println(this.name+",要登錄!");  //不寫this效果一樣
      }  
       
      public static void main(String[] args) {
          User  u3 = new User(101,"天使");
          System.out.println("打印高天使對象:"+u3);
          u3.login();
      }
      
    }
    ```
    結果如圖
    在這裏插入圖片描述
static 關鍵字
  • 在類中,用static聲明的成員變量爲靜態成員變量,也稱爲類變量。 類變量的生命週期和類相同,在整個應用程序執行期間都有效。它有如下特點:
    - 1. 爲該類的公用變量,屬於類,被該類的所有實例共享,在類被載入時被顯式初始化。
    - 2. 對於該類的所有對象來說,static成員變量只有一份。被該類的所有對象共享!!
    - 3. 一般用“類名.類屬性/方法”來調用。(也可以通過對象引用或類名(不需要實例化)訪問靜態成員。)
    - 4. 在static方法中不可直接訪問非static的成員。
  • 核心要點:
    static修飾的成員變量和方法,從屬於類。
    普通變量和方法從屬於對象的。
靜態初始化塊
  • 構造方法用於對象的初始化!靜態初始化塊,用於類的初始化操作!在靜態初始化塊中不能直接訪問非static成員。
  • 注意事項:
    • 靜態初始化塊執行順序(學完繼承再看這裏):
      - 1. 上溯到Object類,先執行Object的靜態初始化塊,再向下執行子類的靜態初始化塊,直到我們的類的靜態初始化塊爲止。
      - 2. 構造方法執行順序和上面順序一樣!!
  • 示例 - static初始化塊
    public class User3 {
        int id;        //id
        String name;   //用戶名
        String pwd;   //密碼
        static String major; //專業名稱
        static {
            System.out.println("執行類的初始化...");
            major = "網絡工程";
            printCompany();
        }  
        public static void printCompany(){
            System.out.println(major);
        }  
        public static void main(String[] args) {
            User3  u3 = new User3();
        }
    }
    
  • 執行結果
    在這裏插入圖片描述
參數傳值機制
  • Java中,方法中所有參數都是“值傳遞”,也就是“傳遞的是值的副本”。 也就是說,我們得到的是“原參數的複印件,而不是原件”。因此,複印件改變不會影響原件。
  • 基本數據類型參數的傳值
    • 傳遞的是值的副本。 副本改變不會影響原件。
  • 引用類型參數的傳值
    • 傳遞的是值的副本。但是引用類型指的是“對象的地址”。因此,副本和原參數都指向了同一個“地址”,改變“副本指向地址對象的值,也意味着原參數指向對象的值也發生了改變”。
  • 示例 - 多個變量指向同一個對象
    
    public class User4 {
        int id;        //id
        String name;   //用戶名
        String pwd;   //密碼
        
        public User4(int id, String name) {
        	this.id = id;
        	this.name = name;
    	}
        public   void   testParameterTransfer01(User4  u){
            u.name="李四";
        }
         
        public   void   testParameterTransfer02(User4  u){
            u  =  new  User4(200,"王五");
        }
      
        public static void main(String[] args) {
            User4  u1 = new User4(100, "張三");
            System.out.println(u1.name);
            
            u1.testParameterTransfer01(u1);
            System.out.println(u1.name);
            
            u1.testParameterTransfer02(u1);
            System.out.println(u1.name);
        }
        
    }
    
  • 執行結果
    在這裏插入圖片描述
  • 包機制是Java中管理類的重要手段。 開發中,我們會遇到大量同名的類,通過包我們很容易對解決類重名的問題,也可以實現對類的有效管理。 包對於類,相當於文件夾對於文件的作用。
package
  • 我們通過package實現對類的管理,package的使用有兩個要點:
    - 1. 通常是類的第一句非註釋性語句。
    - 2. 包名:域名倒着寫即可,再加上模塊名,便於內部管理類。
  • 示例 - package的命名舉例
    com.sun.test;
    com.oracle.test;
    cn.kk.dao.test;
    cn.kk.dao.view;
    cn.kk.dao.view.model;
    
  • 注意事項:
    - 1. 寫項目時都要加包,不要使用默認包。
    - 2. com.dao和com.dao.car,這兩個包沒有包含關係,是兩個完全獨立的包。只是邏輯上看起來後者是前者的一部分。
JDK中的主要包
Java中的常用包 說明
java.lang 包含一些Java語言的核心類,如String、Math、Integer、System和Thread,提供常用功能。
java.awt 包含了構成抽象窗口工具集(abstract window toolkits)的多個類,這些類被用來構建和管理應用程序的圖形用戶界面(GUI)。
java.net 包含執行與網絡相關的操作的類。
java.io 包含能提供多種輸入/輸出功能的類。
java.util 包含一些實用工具類,如定義系統特性、使用與日期日曆相關的函數。
導入類import
  • 如果我們要使用其他包的類,需要使用import導入,從而可以在本類中直接通過類名來調用,否則就需要書寫類的完整包名和類名。import後,便於編寫代碼,提高可維護性。
  • 注意要點:
    - 1. Java會默認導入java.lang包下所有的類,因此這些類我們可以直接使用。
    - 2. 如果導入兩個同名的類,只能用包名+類名來顯示調用相關類:
    java.util.Date date = new java.util.Date();
  • 示例 - 導入同名類的處理
import java.sql.Date;
import java.util.*;//導入該包下所有的類。會降低編譯速度,但不會降低運行速度。
 
public class Test{
    public static void main(String[] args) {
        //這裏指的是java.sql.Date
        Date now; 
        //java.util.Date因爲和java.sql.Date類同名,需要完整路徑
        java.util.Date  now2 = new java.util.Date();
        System.out.println(now2);      
        //java.util包的非同名類不需要完整路徑
        Scanner input = new Scanner(System.in);    
    }
}
靜態導入
  • 靜態導入(static import)是在JDK1.5新增加的功能,其作用是用於導入指定類的靜態屬性,這樣我們可以直接使用靜態屬性。
     import static java.lang.Math.*;//導入Math類的所有靜態屬性
    import static java.lang.Math.PI;//導入Math類的PI屬性
總結
  1. 面向對象可以幫助我們從宏觀上把握、從整體上分析整個系統。 但是具體到實現部分的微觀操作(就是一個個方法),仍然需要面向過程的思路去處理。

  2. 類可以看成一類對象的模板,對象可以看成該類的一個具體實例。

  3. 對於一個類來說,一般有三種常見的成員:屬性field、方法method、構造器constructor。

  4. 構造器也叫構造方法,用於對象的初始化。構造器是一個創建對象時被自動調用的特殊方法,目的是對象的初始化。構造器的名稱應與類的名稱一致。

  5. Java引入了垃圾回收機制,令C++程序員最頭疼的內存管理問題迎刃而解。Java程序員可將更多的精力放到業務邏輯上而不是內存管理工作,大大提高開發效率。

  6. this的本質就是“創建好的對象的地址”! this不能用於static方法中。

  7. 在類中,用static聲明的成員變量爲靜態成員變量,也稱爲類變量。類變量的生命週期和類相同,在整個應用程序執行期間都有效。在static方法中不可直接訪問非static的成員。

  8. Java方法中所有參數都是“值傳遞”,也就是“傳遞的是值的副本”。也就是說,我們得到的是“原參數的複印件,而不是原件”。因此,複印件改變不會影響原件。

  9. 通過package實現對類的管理;如果我們要使用其他包的類,需要使用import導入,從而可以在本類中直接通過類名來調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章