Java 面向對象基礎Day2學習

大部分內容來自 www.sxt.cn 僅供自己學習,記錄一些筆記。侵刪。

4.1面向過程和麪向對象

  1. 面向對象具有三大特徵:封裝性、繼承性和多態性,而面向過程沒有繼承性和多態性,並且面向過程的封裝只是封裝功能,而面向對象可以封裝數據和功能。所以面向對象優勢更明顯。

  2. 一個經典的比喻:面向對象是蓋澆飯、面向過程是蛋炒飯。蓋澆飯的好處就是“菜”“飯”分離,從而提高了製作蓋澆飯的靈活性。飯不滿意就換飯,菜不滿意換菜。用軟件工程的專業術語就是“可維護性”比較好,“飯” 和“菜”的耦合度比較低。

4.2對象的進化史

  1. 數據無管理時代
  2. 數組管理和企業部門制
  3. 對象和企業項目制
  4. 幾類整合比較
    在這裏插入圖片描述
    5.總結
      1.對象說白了也是一種數據結構(對數據的管理模式),將數據和數據的行爲放到了一起。
      2.在內存上,對象就是一個內存塊,存放了相關的數據集合!
      3.對象的本質就一種數據的組織方式!

4.3對象和類的概念

類可以看做是一個模版,或者圖紙,系統根據類的定義來造出對象。我們要造一個汽車,怎麼樣造?類就是這個圖紙,規定了汽車的詳細信息,然後根據圖紙將汽車造出來。
類:我們叫做class。 對象:我們叫做Object,instance(實例)。以後我們說某個類的對象,某個類的實例。是一樣的意思。

概括
1.對象是具體的事物;類是對對象的抽象;
2.類可以看成一類對象的模板,對象可以看成該類的一個具體實例。
3.類是用於描述同一類型的對象的一個抽象概念,類中定義了這一類對象所應具有的共同的屬性、方法。

4.3.1第一個類的定義

1.類的定義方式

// 每一個源文件必須有且只有一個public class,並且類名和文件名保持一致!
public class Car { 
}
class Tyre { // 一個Java文件可以同時定義多個class
}
class Engine {
}
class Seat {
}

2.簡單學生類的編寫

public class SxtStu {
    //屬性(成員變量)
    int id;
    String sname;
    int age;  
    //方法
    void study(){
        System.out.println("我正在學習!");
    }  
    //構造方法
   SxtStu(){
   }
}

3.屬性field
可以理解爲成員變量。
4.方法
方法用於定義該類或該類實例的行爲特徵和功能實現。方法是類和對象行爲特徵的抽象。方法很類似於面向過程中的函數。面向過程中,函數是最基本單位,整個程序由一個個函數調用組成。面向對象中,整個程序的基本單位是類,方法是從屬於類和對象的。


public class Sxtstu {
	//屬性field
	int id;
	String name;
	int age;
	Computer comp;
	void study() {
		System.out.println("我在認真學習!使用電腦:"+comp.brand);
	}
	void play() {
		System.out.println("我在玩遊戲!王者榮耀!");
	}
	//構造方法,用於創建這個類的對象
	Sxtstu(){
		
	}
	//程序執行的入口,必須要有
	public static void main(String[] args) {
		Sxtstu stu=new Sxtstu();//創建一個對象
		stu.id=1001;
		stu.name="TZD";
		stu.age=18;
		
		Computer c1=new Computer();
		c1.brand="聯想";
		stu.comp=c1;
		
		stu.play();
		stu.study();
	}
}
class Computer {
	String brand;
}

4.4面向對象的內存分析

在這裏插入圖片描述

4.5構造方法

要點:

1. 通過new關鍵字調用!!

2. 構造器雖然有返回值,但是不能定義返回值類型(返回值的類型肯定是本類),不能在構造器裏使用return返回某個值。

3. 如果我們沒有定義構造器,則編譯器會自動定義一個無參的構造函數。如果已定義則編譯器不會自動添加!

4. 構造器的方法名必須和類名一致!

package Sxtstu;

class Point {
    double x, y;
    //構造方法的名稱必須和類名保持一致
    public Point(double _x, double _y) {
        x = _x;
        y = _y;  
    }
    public double getDistance(Point p) {
        return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    }
}

public class TestConstructor {
    public static void main(String[] args) {
        Point p = new Point(3.0, 4.0);
        Point origin = new Point(0.0, 0.0);
        System.out.println(p.getDistance(origin));
    }
}

4.6構造方法的重載

package Sxtstu;

public class Sxtstu {
    int id; // id
    String name; // 賬戶名
    String pwd; // 密碼
    public Sxtstu() {
 
    }
    public Sxtstu(int id, String name) {
        super();//構造方法的第一句總是super()
        this.id = id;//this 表示創建好的對象
        this.name = name;
    }
    public Sxtstu(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }
    public static void main(String[] args) {
    	Sxtstu u1 = new Sxtstu();
    	Sxtstu u2 = new Sxtstu(101, "高小七");
    	Sxtstu u3 = new Sxtstu(100, "高淇", "123456");     
    }
}

4.7垃圾回收機制

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

4.7.1 垃圾回收原理和算法

·垃圾回收過程
  任何一種垃圾回收算法一般要做兩件基本事情:
  1. 發現無用的對象
  2. 回收無用對象佔用的內存空間。
  垃圾回收機制保證可以將“無用的對象”進行回收。無用的對象指的就是沒有任何變量引用該對象。Java的垃圾回收器通過相關算法發現無用對象,並進行清除和整理。

·垃圾回收相關算法
  1. 引用計數法
  堆中每個對象都有一個引用計數。被引用一次,計數加1. 被引用變量值變爲null,則計數減1,直到計數爲0,則表示變成無用對象。優點是算法簡單,缺點是“循環引用的無用對象”無法別識別。
  s1和s2互相引用對方,導致他們引用計數不爲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;
    }
}

2. 引用可達法(根搜索算法)
  程序把所有的引用關係看作一張圖,從一個節點GC ROOT開始,尋找對應的引用節點,找到這個節點以後,繼續尋找這個節點的引用節點,當所有的引用節點尋找完畢之後,剩餘的節點則被認爲是沒有被引用到的節點,即無用的節點。

4.7.2 通用的分代垃圾回收機制

·Minor GC:

用於清理年輕代區域。Eden區滿了就會觸發一次Minor GC。清理無用對象,將有用對象複製到“Survivor1”、“Survivor2”區中(這兩個區,大小空間也相同,同一時刻Survivor1和Survivor2只有一個在用,一個爲空)

·Major GC:

用於清理老年代區域。

·Full GC:

用於清理年輕代、年老代區域。 成本較高,會對系統性能產生影響。

垃圾回收過程

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)

4.7.3 JVM調優和Full GC

在對JVM調優的過程中,很大一部分工作就是對於Full GC的調節。有如下原因可能導致Full GC:

1.年老代(Tenured)被寫滿

2.持久代(Perm)被寫滿

3.System.gc()被顯式調用(程序建議GC啓動,不是調用GC)

4.上一次GC之後Heap的各域分配策略動態變化

4.7.4 開發中容易造成內存泄露的操作

暫時不學

4.8 this關鍵字

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();
    }
}
public class TestThis {
    int a, b, c;
 
    TestThis() {
        System.out.println("正要初始化一個Hello對象");
    }
    TestThis(int a, int b) {
        // TestThis(); //這樣是無法調用構造方法的!
        this(); // 調用無參的構造方法,並且必須位於第一行!
        a = a;// 這裏都是指的局部變量而不是成員變量
// 這樣就區分了成員變量和局部變量. 這種情況佔了this使用情況大多數!
        this.a = a;
        this.b = b;
    }
    TestThis(int a, int b, int c) {
        this(a, b); // 調用帶參的構造方法,並且必須位於第一行!
        this.c = c;
    }
 
    void sing() {
    }
    void eat() {
        this.sing(); // 調用本類中的sing();
        System.out.println("你媽媽喊你回家喫飯!");
    }
 
    public static void main(String[] args) {
        TestThis hi = new TestThis(2, 3);
        hi.eat();
    }
}

4.9 static 關鍵字

在類中,用static聲明的成員變量爲靜態成員變量,也稱爲類變量。 類變量的生命週期和類相同,在整個應用程序執行期間都有效。它有如下特點:

1. 爲該類的公用變量,屬於類,被該類的所有實例共享,在類被載入時被顯式初始化。

2. 對於該類的所有對象來說,static成員變量只有一份。被該類的所有對象共享!!

3. 一般用“類名.類屬性/方法”來調用。(也可以通過對象引用或類名(不需要實例化)訪問靜態成員。)

4. 在static方法中不可直接訪問非static的成員。

核心要點
static修飾的成員變量和方法,從屬於類。
普通變量和方法從屬於對象的。


/**
 * 測試static關鍵字的用法
 * @author 高淇
 *
 */
public class User2 {
    int id; // id
    String name; // 賬戶名
    String pwd; // 密碼
     
    static String company = "北京尚學堂"; // 公司名稱
     
     
    public User2(int id, String name) {
        this.id = id;
        this.name = name;
    }
     
    public void login() {
        printCompany();
        System.out.println(company); 
        System.out.println("登錄:" + name);
    }
     
    public static void printCompany() {
//         login();//調用非靜態成員,編譯就會報錯
        System.out.println(company);
    }
     
    public static void main(String[] args) {
        User2 u = new User2(101, "高小七");
        User2.printCompany();
        User2.company = "北京阿里爺爺";
        User2.printCompany();
    }
}

4.10靜態初始化

構造方法用於對象的初始化!靜態初始化塊,用於類的初始化操作!在靜態初始化塊中不能直接訪問非static成員。

注意事項:
  靜態初始化塊執行順序(學完繼承再看這裏):
  1. 上溯到Object類,先執行Object的靜態初始化塊,再向下執行子類的靜態初始化塊,直到我們的類的靜態初始化塊爲止。
  2. 構造方法執行順序和上面順序一樣!!

public class User3 {
    int id;        //id
    String name;   //賬戶名
    String pwd;   //密碼
    static String company; //公司名稱
    static {
        System.out.println("執行類的初始化工作");
        company = "北京尚學堂";
        printCompany();
    }  
    public static void printCompany(){
        System.out.println(company);
    }  
    public static void main(String[] args) {
        User3  u3 = new User3();
    }
}

4.11 參數傳值機制

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

· 基本數據類型參數的傳值
  傳遞的是值的副本。 副本改變不會影響原件。

· 引用類型參數的傳值
  傳遞的是值的副本。但是引用類型指的是“對象的地址”。因此,副本和原參數都指向了同一個“地址”,改變“副本指向地址對象的值,也意味着原參數指向對象的值也發生了改變”。

/**
 * 測試參數傳值機制
 * @author 高淇
 *
 */
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, "高小七");
         
        u1.testParameterTransfer01(u1); 
        System.out.println(u1.name);
 
        u1.testParameterTransfer02(u1);
        System.out.println(u1.name);
    }
}
/*輸出結果
高小八 
高小八
*/

4.12 包

包機制是Java中管理類的重要手段。 開發中,我們會遇到大量同名的類,通過包我們很容易對解決類重名的問題,也可以實現對類的有效管理。 包對於類,相當於文件夾對於文件的作用。

4.13 package

我們通過package實現對類的管理,package的使用有兩個要點:

1. 通常是類的第一句非註釋性語句。

2. 包名:域名倒着寫即可,再加上模塊名,便於內部管理類。
  
注意事項:

  1. 寫項目時都要加包,不要使用默認包。

  2. com.gao和com.gao.car,這兩個包沒有包含關係,是兩個完全獨立的包。只是邏輯上看起來後者是前者的一部分。

package cn.sxt;
public class Test {
    public static void main(String[] args) {
        System.out.println("helloworld");
    }
}

4.13.1 JDK中的主要包

在這裏插入圖片描述

4.13.2 導入類import

如果我們要使用其他包的類,需要使用import導入,從而可以在本類中直接通過類名來調用,否則就需要書寫類的完整包名和類名。import後,便於編寫代碼,提高可維護性。

  1. Java會默認導入java.lang包下所有的類,因此這些類我們可以直接使用。
  2. 如果導入兩個同名的類,只能用包名+類名來顯示調用相關類:
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);    
    }
}

4.13.3 靜態導入

靜態導入(static import)是在JDK1.5新增加的功能,其作用是用於導入指定類的靜態屬性,這樣我們可以直接使用靜態屬性。

package cn.sxt;
 //以下兩種靜態導入的方式二選一即可
import static java.lang.Math.*;//導入Math類的所有靜態屬性
import static java.lang.Math.PI;//導入Math類的PI屬性
 
public class Test2{
    public static void main(String [] args){
        System.out.println(PI);
        System.out.println(random());
    }
}
/*
輸出結果
3.141592653589793
0.66487.....
*/

總結

  1. 面向對象可以幫助我們從宏觀上把握、從整體上分析整個系統。 但是具體到實現部分的微觀操作(就是一個個方法),仍然需要面向過程的思路去處理。

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

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

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

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

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

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

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

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

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