Java基礎知識篇02——封裝

来源:https://www.cnblogs.com/baiye123/p/18131950
-Advertisement-
Play Games

大家好,我是白夜,今天給大家聊聊面向對象的三大特征——封裝 一、包(package) 1.1、包的引入 先來看看我們之前寫的代碼結構 以上代碼存在的問題 所有類寫在一個目錄下麵,非常難管理,因為以後項目不可能只有這麼幾個類,當類數量很大的時候,就不容易管理了。 不能寫同名但是不同需求的類。 為瞭解決 ...


大家好,我是白夜,今天給大家聊聊面向對象的三大特征——封裝

一、包(package)

1.1、包的引入

先來看看我們之前寫的代碼結構

圖片01

以上代碼存在的問題

  1. 所有類寫在一個目錄下麵,非常難管理,因為以後項目不可能只有這麼幾個類,當類數量很大的時候,就不容易管理了。
  2. 不能寫同名但是不同需求的類。

為瞭解決這些問題,我們需要把不同的東西放到專門的裡面,進行分類管理。也就是通過文件夾進行管理,Java 中的文件夾就是

1.2、定義包

包命名規範:一般是公司功能變數名稱反寫.項目名.模塊名字.子模塊名;

要求:包名是全英文小寫。

例如 : itsource.cn 功能變數名稱

package cn.itsource.erp.oa.domain; 自動化辦公

package cn.itsource.erp.sa.entity; 系統管理

package cn.itsource.packagedemo;// 聲明包

/**
 * 包package
 */
public class PackageDemo {

	public static void main(String[] args) {
		new java.util.Date();
		new java.sql.Date(1L);
		System.out.println();
	}
}

1.3、導入包

當我們需要使用別人或者 JDK 中的類的時候,就需要告知 JVM 從什麼地方去載入這個類,這個過程就是導包

其實本質是導入包中的類。

導入包的語法 :

import 包名.子包名.類名

註意:

  1. 導入包的代碼應該在聲明包(就是該類所在的包)的後面,聲明類的前面。

  2. import java.util; 表示導入本包中所有會使用到的 util 包中的類,只會導入 util 包下麵直接的類型,不包括util 包的子包中的類型。

  3. java.lang是核心包,下麵的直接類型是自動導入的;

    例如:String、System類,lang 包的子包中的類型不會自動導入,需要手動導入。

  4. 在一個類中會用到同名不同包的時候必須使用全限定路徑

    例如:同時使用 java.util.Date 和 java.sql.Date

package cn.itsource.packagedemo;//聲明包
import java.util.*;// 只會導入util包下使用到的類

/**
 * 包package
 */
public class PackageDemo {

	public static void main(String[] args) {// String是java.lang核心包下的,程式會自動導入;
		// 使用Arrays類中的toString方法
//		String str = java.util.Arrays.toString(new int[]{1, 2, 3});// 每次都寫全限定類名比較麻煩
		
		// 使用Arrays類中的sort方法排序
//		java.util.Arrays.sort(new int[]{3, 2, 1});
		
		// 用自動導包可以簡化上面代碼
		String str = Arrays.toString(new int[]{1, 2, 3});// 每次都寫全限定類名比較麻煩
		System.out.println(str);
		Arrays.sort(new int[]{3, 2, 1});
		
		// 當使用同名不同包的多個類怎麼用? 必須用全限定類名
		new java.util.Date();// java.util包下
		new java.sql.Date(1L);// java.sql包下
	}
}

1.4、Java中常用的包(瞭解)

java/ javax(java 增強包)

java.lang (java 的核心包--基本包) 幫我們自動導包的

java.util(java 的工具包 --集合框架 ArrayList LinkedList)

java.io(java IO包input-output 讀寫文件)

java.net (網路編程)

java.awt/javax.swing(java的圖形化界面)

java.math 數學相關的包

java.sql 資料庫相關的包

java.text 是文本格式化相關的包

java.time 時間相關的包

二、封裝

2.1、為什麼要封裝

來看下麵一個案例

package cn.itsource.potting1;

/**
 *	賬戶Account類
 *	封裝引入
 */
public class Account {
	/** String類型成員變數姓名name */
	protected String name;
	
	/** String類型成員變數密碼pwd */
	String pwd;
	
	/** double類型成員變數餘額money */
	double money;
	
	/** boolean類型成員變數是否是vip用戶 */
	boolean vip;
	
	/**
	 * Account類無參構造
	 */
	public Account() {}
	
	/**
	 * 有4個參數構造方法
	 * @param n
	 * @param p
	 * @param m
	 * @param v
	 */
	public Account(String n, String p, double m, boolean v) {
		name = n;// 將局部變數n賦值給成員變數name
		pwd = p;// 將局部變數p賦值給成員變數pwd
		money = m;// 將局部變數m賦值給成員變數money
		vip = v;// 將局部變數v賦值給成員變數vip
	}
	
	/**
	 * 獲取當前成員變數money的值
	 * @return
	 */
	public double getMoney() {
		return money;
	}
}

測試類:
package cn.itsource.potting1;

/**
 *	Account測試類
 *	封裝的引入
 */
public class AccountTest {

	public static void main(String[] args) {
		// 創建Account對象,調用無參構造
		Account acc1 = new Account();
		// 給acc1成員變數賦值
		acc1.name = "某菲";
		acc1.pwd = "6969";
		acc1.money = 1.0;
		acc1.vip = false;
		// 列印acc1成員變數的值
		System.out.println(acc1.name);
		System.out.println(acc1.pwd);
		System.out.println(acc1.money);
		System.out.println(acc1.vip);
		// acc1調用getMoney方法
		double money = acc1.getMoney();// 因為getMoney方法是非static修飾,並且有返回值,所以用acc1調用,用double變數接收
		System.out.println(money);
		
		// 需求:當money達到50000.00的時候,會將vip升級為true。現在,能不能沒有達到5萬就不能升級。
		acc1.vip = true;// 這裡沒有經過任何許可權判斷,直接修改了值,不安全。所以,用封裝解決這個問題。
		System.out.println(acc1.vip);// true		
	}
}

而在 Java 中是通過封裝來完成保護內部成員的目的

2.2、封裝的作用

封裝是為了保護內部數據的安全:

  1. 不希望在外部類中隨意訪問類中的成員變數
  2. 達到許可權要求的才能訪問。
  3. 只是獲取數據的時候。例如:單例模式。
  4. 我們在程式設計的時候就追求“高內聚、低耦合”:
  • 高內聚:類的內部數據操作細節自己完成,不允許外部干涉;
  • 低耦合:僅對外部暴露少量的方法用於使用。

2.3、封裝的使用

  1. 如何控製程序中的訪問 ?

    通過給類中的成員(欄位,方法,構造方法)添加訪問許可權修飾符來實現封裝(訪問控制)。

  2. 什麼是訪問許可權:簡單的認為訪問許可權就是不同級別的人能夠乾不同級別的事,不同級別的人能看到的頁面是不同的。

    例子:比如做一個系統,不同人登錄進去的訪問許可權不一樣;

  3. 訪問許可權修飾符:

    public 最大許可權,被其修飾的成員,在任意目錄下,都可以訪問到 (所有類)

    protected 在同包類和子類中都可以訪問

    預設不寫 只能在同包類中訪問

    private 只能在當前類中訪問

    圖片02

  4. 封裝的步驟:

    1. 將類的屬性設置為 private,這樣外部就不能直接訪問。
    2. 提供公共的 getter 方法用於獲取屬性值,通常是 public 的。
    3. 提供公共的 setter 方法用於設置屬性值,也是 public 的,並可以在其中添加邏輯檢查。
    4. 提供一個無參構造,有參構造根據需求確定是否要寫。
    5. 該類用 public 修飾。

    圖片03

    public class Account {// 5. 該類用 public 修飾
    	//1. 私有化成員變數(用 private 修飾成員變數)
    	private String name;
    	
    	private String pwd;
    	
    	// 4. 提供一個無參構造
    	public Account() {}
    	
    	// 有參構造根據實際需求,決定是否要寫
    	public Account(String n, String p) {
    		name = n;// 將局部變數賦值給成員變數
    		pwd = p;	
    	}
    	
    	/**
    	 *  2. 為每一個成員變數提供合理的 public void setName(String n) 方法
    	 * 	給成員變數name賦值方法
    	 * @param n
    	 */
    	public void setName(String n) {
    		// 可以寫判斷條件
    		name = n;// 將局部變數n賦值給成員變數 name
    	}
    		
    	public void setPwd(String p) { pwd = p; }
    	
    	/**
    	 * 2. 為每一個成員變數提供合理的	public String getName() 方法
    	 * 獲取成員變數 name 的值
    	 * @return
    	 */
    	public String getName() {
    		// 可以寫判斷條件
    		return name;// 直接返回成員變數 name
    	}
    	
    	public String getPwd() { return pwd; }	
    }
    
    /**
     *	Account 測試類
     *	封裝的引入
     */
    public class AccountTest {
    	public static void main(String[] args) {
    		// 創建Account對象,調用無參構造
    		// Account acc1 = new Account();
    		// 給 acc1 成員變數賦值
    		/*
    		 * 因為 private 修飾成員變數後,不能在其他類中使用了。
    		acc1.name = "小七";
    		acc1.pwd = "6969";
    		*/
    		// 使用有參構造賦值
    		Account acc1 = new Account("小七", "6969");
    		
    		// 列印acc1成員變數的值
    //		System.out.println(acc1.name);// 因為 private 修飾成員變數後,不能在其他類中使用了。
    //		System.out.println(acc1.pwd);
    		
    		// 因為封裝了,所以只能調用:public 返回值 getXxx() 獲取成員變數的值
    		String name = acc1.getName();// acc1 調用 getName 方法獲取成員變數 name 的值
    		String pwd = acc1.getPwd();// acc1 調用 getPwd 方法獲取成員變數 pwd 的值
    		// 列印上面獲取的值
    		System.out.println(name);
    		System.out.println(pwd);
    		
    		// 當需要修改創建好的對象的成員變數值,用 set 方法賦值
    		acc1.name("小八");	
    		String name2 = acc1.getName();
    		System.out.println(money2);		
    	}
    }
    

    2.4、 封裝的註意事項

    1. 不是只有 private 才叫封裝,private 只是最大限度的封裝而已。
    2. get 和 set 方法都是只能獲取或者賦值一個成員變數,**不能 **set(String n, double m, boolean v) 賦值3個成員變數。
    3. 單一職能原則:功能最小化,不要想著一個方法寫完所有的功能,因為代碼復用率高。

    2.5、封裝的好處

    • 增強安全性:隱藏數據和方法的實現細節,防止外部直接訪問,降低因錯誤使用而導致的風險。
    • 提高復用性:封裝後的代碼更容易被其他程式或模塊復用,因為它們的實現細節對於使用者來說是透明的。
    • 便於維護:封裝使得代碼修改時影響範圍局限,提高了代碼的可維護性。

三、this關鍵字

this 的概念:

​ this 指代當前對象,即,哪個對象調用就指代哪個對象

3.1、this 的使用

1.   解決局部變數和成員變數的二義性【set 方法和有參構造中形參跟成員變數同名不同義】

public Account(String name,String pwd) {
	// 要解決二義性問題,就需要用到this,加上this,就會直接從成員變數位置找name
	this.name = name;
	this.pwd = pwd;
}

1.   本類中構造方法之間的相互調用,但是必須是構造方法內的第一句。

package cn.itsource.task.topic02;

public class People {
    private String name;
    private boolean sex;
    private int age;
    private int weight;
    public People(){

    }
    public People(String name, boolean sex, int age, int weight){
        this(name, sex, age);
        this.weight = weight;
    }
    public People(String name, boolean sex, int age){
        this(name, sex);
        this.age = age;
    }
    public People(String name, boolean sex){
        this(name);
        this.sex = sex;
    }
    public People(String name){
        this.name = name;
    }

    public String getName() { return name; }

    public void setName(String name) { this.name = name; }

    public boolean isSex() { return sex; }

    public void setSex(boolean sex) { this.sex = sex; }

    public int getAge() { return age; }

    public void setAge(int age) { this.age = age; }

    public int getWeight() { return weight; }

    public void setWeight(int weight) { this.weight = weight; }
}

四、構造方法和set方法的區別

  • 構造方法可以為多個成員變數賦值,set只能對一個進行賦值;
  • 構造方法由JVM自動調用,set需要手動調用;
  • 構造方法針對同一個對象只能調用一次,set方法針對同一個對象可以調用多次;
  • 構造方法用於給變數賦值,set可以給變數賦值或者修改值;
  • 構造可以使代碼更加簡潔,set方法靈活性更高。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JS解混淆 最近在整理之前和一些同伴的分享資料,發現時間已經過了好久,特此整理一些有價值的分享記錄。 JS混淆 學習js混淆可以逆向分析混淆和加密過程,實戰可用於爬蟲和滲透信息獲取 本文檔用於初步介紹js混淆的基礎概念以及如何解混淆、調試,便於幹掉反爬蟲和滲透信息收集思路拓展 概念解釋 混淆/加密 ...
  • 前言 我們已經介紹了radash的相關信息和部分Array相關方法,詳情可前往主頁查看; 本篇我們繼續介紹radash中Array的相關方法; 下期我們將介紹解析radash中剩餘的 Array相關方法,並整理出Array方法使用目錄,包括文章說明和腦圖說明。 Radash的Array相關方法詳解 ...
  • 大家好,我是 Java陳序員。 今天,給大家介紹一個基於 Vue 全家桶實現的“網易雲”播放器。 關註微信公眾號:【Java陳序員】,獲取開源項目分享、AI副業分享、超200本經典電腦電子書籍等。 項目介紹 YesPlayMusic —— 一款高顏值的第三方網易雲播放器,支持 Windows / ...
  • 本文分享自華為雲社區《3月閱讀周·你不知道的JavaScript | ES6生成器,看似同步的非同步流程式控制製表達風格》,作者: 葉一一。 生成器 打破完整運行 JavaScript開發者在代碼中幾乎普遍依賴的一個假定:一個函數一旦開始執行,就會運行到結束,期間不會有其他代碼能夠打斷它並插入其間。 ES ...
  • 目錄一、爬取目標1.1 效果截圖1.2 演示視頻1.3 軟體說明二、代碼講解2.1 爬蟲採集模塊2.2 軟體界面模塊2.3 日誌模塊三、獲取源碼及軟體 一、爬取目標 用python開發的xhs爬蟲採集軟體,可自動抓取小紅書評論數據,並且含二級評論數據。 為什麼有了源碼還開發界面軟體呢?方便不懂編程代 ...
  • 1、 Pythonic - 很Python 寫一段代碼生成1到100之間的數字的平方的列表,答案是: 1, 4, 9, 16... 如果你這樣寫,你就不Pythonic了: 解釋 nums = [] for i in range(1, 101): nums.append(i*i) print(num ...
  • 拓展閱讀 MySQL View MySQL truncate table 與 delete 清空表的區別和坑 MySQL Ruler mysql 日常開發規範 MySQL datetime timestamp 以及如何自動更新,如何實現範圍查詢 MySQL 06 mysql 如何實現類似 oracl ...
  • C++ 解引用 獲取記憶體地址和值 在上一頁的示例中,我們使用了指針變數來獲取變數的記憶體地址(與引用運算符 & 一起使用)。但是,你也可以使用指針來獲取變數的值,這可以通過使用 * 運算符(解引用運算符)來實現: string food = "Pizza"; // 變數聲明 string* ptr = ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...