封裝是物件導向的三大特性之一;物件導向程式三大特性:封裝、繼承、多態。
封裝:將資料和操作資料的方法進行有機結合,隱藏物件的屬性和實作細節,僅對外公開介面來和物件進行互動(簡單來說就是套殼屏蔽細節)。
用生活中的實體來理解封裝,例如電腦:
對於電腦這樣一個複雜的設備,提供給使用者的就只是:開關機、透過鍵盤輸入,顯示器,USB插孔等,讓使用者來和電腦互動,完成日常事務。
但實際上:電腦真正運作的卻是CPU、顯示卡、記憶體等一些硬體元件。對於電腦使用者而言,不用關心內部核心零件,例如主機板上線路是如何佈局的,CPU內部是如何設計的等,使用者只需要知道,怎麼開機、怎麼透過鍵盤和滑鼠與電腦互動即可。因此電腦廠商在出廠時,在外部套上殼子,將內部實現細節隱藏起來,僅僅對外提供開關機、滑鼠以及鍵盤插孔等,讓使用者可以與電腦互動即可。
Java中主要透過類別和存取權限來實現封裝:類別可以將資料以及封裝資料的方法結合在一起,更符合人類對事物的認知,而存取權限用來控制類別或類別中方法或欄位能否直接在類別外使用。 Java中提供了四種存取限定符:
public:公開的,可以理解為一個人的外貌特徵,誰都可以看得出
# protected:受保護的,涉及到繼承中的知識,繼承博客中詳細介紹
default: 什麼都不寫時的默認權限,對於自己家族中(同一個包中)不是什麼秘密,對於其他人來說就是隱私了
private:私有的,只有自己知道,其他人都不知道
透過下面給出的程式碼範例來理解封裝:
class Person { private String name; //private修饰的成员变量只能在本类中访问 private int age; String sex; //这里不加修饰符即为默认权限,默认是default权限 public String getName() { return name; } //在其他类中不能直接访问name和age, //但可以在本类中提供公开的(public修饰)访问方法和外界进行交互 //这里就是对成员变量进行了封装 public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void show() { System.out.println("姓名:"+name+" 年龄: "+age); } } public class Test { public static void main(String[] args) { Person person = new Person(); //person.name = "bit";//不能直接进行访问 person.setName("XIN-XIANG荣"); person.setAge(21); //通过提供Person类中提供的方法间接进行访问 System.out.println(person.getName()+" => "+person.getAge()); } }
一般情況下成員變數設定為private,成員方法設定為public,透過這個例子就可以很好的理解封裝了,這裡對類別內部的實作細節進行了隱藏/封裝,對外只提供一些公開的方法供其他使用者存取。
【存取限定符的使用情境】:
#我們希望類別要盡量做到「封裝」, 即隱藏內部實作細節,只暴露出必要的資訊給類別的呼叫者.
因此我們在使用的時候應該盡可能的使用比較嚴格的存取權限;例如如果一個方法能用private, 就盡量不要用public.
另外, 還有一種簡單粗暴的做法: 將所有的字段設為private, 將所有的方法設為public. 不過這種方式屬於是對存取權限的濫用, 不過最好寫程式碼的時候思考該類別提供的字段方法到底給「誰」 使用(是類別內部自己用, 還是類別的呼叫者使用, 還是子類別使用)
在物件導向系統中,提出了一個軟體套件的概念,即:為了更好的管理類,把多個類別收集在一起成為一組,稱為軟體包。有點類似目錄。例如:為了更好的管理電腦中的圖片,一個好的方式就是將相同屬性的圖片放在相同文件下,也可以對某個資料夾下的圖片進行更詳細的分類 。
在Java中也引入了包,包是對類別、介面等的封裝機制的體現,是一種對類別或介面等的很好的組織方式,例如:一個套件中的類別不想被其他套件中的類別使用。套件還有一個重要的作用:在同一個工程中允許存在相同名稱的類,只要處在不同的套件中即可。
Java 中已經提供了許多現成的類別供我們使用. 例如Date類別:可以使用 java.util.Date
導入java.util 這個套件中的Date類別.
public class Test1 { public static void main(String[] args) { java.util.Date date = new java.util.Date(); // 得到一个毫秒级别的时间戳 System.out.println(date.getTime()); } }
但是這種寫法比較麻煩一些, 可以使用import語句導入套件
import java.util.Date; public class Test1 { public static void main(String[] args) { Date date = new Date(); // 得到一个毫秒级别的时间戳 System.out.println(date.getTime()); } }
#如果需要使用java.util 中的其他類別, 可以使用import java.util.*
,這裡可以導入java.util這個套件中的所有類,但要注意不是一下子將所有類別都導進來,在程式碼中用到誰就會導入誰。
import java.util.*; public class Test1 { public static void main(String[] args) { Date date = new Date(); // 得到一个毫秒级别的时间戳 System.out.println(date.getTime()); } }
但是更建議明確的指定要匯入的類別名稱. 否則還是容易出現衝突的情況.
import java.util.*; import java.sql.*; public class Test1 { public static void main(String[] args) { // util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错 Date date = new Date(); System.out.println(date.getTime()); } } // 编译出错 //Error:(5, 9) java: 对Date的引用不明确 //java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配
在这种情况下需要使用完整的类名
import java.util.*; import java.sql.*; public class Test1 { public static void main(String[] args) { java.util.Date date = new java.util.Date(); System.out.println(date.getTime()); } }
import static java.lang.Math.*; public class Test { public static void main(String[] args) { double x = 30; double y = 40; // 静态导入的方式写起来更方便一些. // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); double result = sqrt(pow(x, 2) + pow(y, 2)); System.out.println(result); } } //对比正常的导入和使用 import java.lang.Math; public class Test1 { public static void main(String[] args) { double x = 30; double y = 40; double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); System.out.println(result); } }
在文件的最上方加上一个 package 语句指定该代码在哪个包中.
包名需要尽量指定成唯一的名字, 通常会用公司域名的颠倒形式(例如com.bat.demo1 ).
包名要和代码路径相匹配. 例如创建 com.bat.demo1 的包, 那么会存在一个对应的路径 com/bat/demo1 来存储代码
如果一个类没有 package 语句, 则该类被放到一个默认包中
在 IDEA 中先新建一个包: 右键 src -> 新建 -> 包
在弹出的对话框中输入包名, 例如 com.bat.demo1 ,敲入回车即可
在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名回车即可.
此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了
同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句
Computer类位于com.bat.demo1包中,TestComputer位置com.bat.demo2包中
package com.bat.demo1; public class Computer { private String cpu; // cpu private String memory; // 内存 public String screen; // 屏幕 String brand; // 品牌 public Computer(String brand, String cpu, String memory, String screen) { this.brand = brand; this.cpu = cpu; this.memory = memory; this.screen = screen; } public void Boot() { System.out.println("开机~~~"); } public void PowerOff() { System.out.println("关机~~~"); } public void SurfInternet() { System.out.println("上网~~~"); } }
注意:如果去掉Computer类之前的public修饰符,Computer类为默认权限,只能在同一包中访问,代码也会编译失败
java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
java.lang.reflect:java 反射编程包;
java.net:进行网络编程开发包。
java.sql:进行数据库开发的支持包。
java.util:是java提供的工具程序包;(集合类等) 非常重要
java.io:I/O编程开发包。
以上是Java中如何使用存取限定符和套件實現封裝?的詳細內容。更多資訊請關注PHP中文網其他相關文章!