Java?SE封裝、包、static關鍵字和代碼塊示例詳解
1.封裝
1.1封裝的概念
面向對象程序三大特性:封裝、繼承、多態(tài)。而類和對象階段,主要研究的就是封裝特性。何為封裝呢?簡單來說
就是套殼屏蔽細節(jié)。
封裝:將數(shù)據(jù)和操作數(shù)據(jù)的方法進行有機結合,隱藏對象的屬性和實現(xiàn)細節(jié),僅對外公開接口來和對象進行交互
1.2封裝之訪問限定符
一般我們封裝用到的訪問限定符:pritave
class Student { private String name; private int age; public void exam() { System.out.println(this.name+"正在考試中"); } } public class Main { public static void main(String[] args) { Student student = new Student(); student.name = "zhangsan"; } }
運行報錯:
為什么會出現(xiàn)這個情況,因為name這個成員變量在Student類中是被pritave修飾的。這樣就體現(xiàn)出了封裝性。
如果直接調用,那是不被允許的,那我們應該怎么去調用這個成員變量呢?
我們可以在類中定義一個成員方法,然后再調用這個成員方法去訪問成員變量,這是被允許的。這屬于間接去訪問,怎么實現(xiàn)呢?我們代碼實現(xiàn)一下:
public String getName() { return name; } public void setName(String name) { this.name = name; }
setName方法是修改也可以賦值成員變量:
public class Main { public static void main(String[] args) { Student student = new Student(); student.setName("zhangsan"); } }
通過調試可以看到Student類中被private修飾的成員變量由null被賦為"zhangsan"
getName這個方法是可以訪問到被private修飾的成員變量。
public class Main { public static void main(String[] args) { Student student = new Student(); student.setName("zhangsan"); System.out.println(student.getName()); } }
通過調試看到可以通過這個方法訪問到被private修飾的成員變量。
通過調用這兩個成員方法可以去訪問類中被pritave修飾的成員變量。
在idea中寫兩個方法有一個快捷鍵:
單擊右鍵之后:
2.包
2.1包的概念
在面向對象體系中,提出了一個軟件包的概念,即:為了更好的管理類,把多個類收集在一起成為一組,稱為軟件包。
在Java中也引入了包,包是對類、接口等的封裝機制的體現(xiàn),是一種對類或者接口等的很好的組織方式,比如:一個包中的類不想被其他包中的類使用。包還有一個重要的作用:在同一個工程中允許存在相同名稱的類,只要處在不同的包中即可。
2.2導入包中的類
在代碼中,如果我們有需要要用到的類的時候,可以直接導入這個類的包。
public class Test { public static void main(String[] args) { java.util.Date data = new java.util.Date(); } }
這么導會很麻煩,也會顯得代碼不夠簡潔,也比較生澀難懂,可以使用 import語句導入包。
import java.util.Date; public class Test { public static void main(String[] args) { Date date = new Date(); //java.util.Date data = new java.util.Date(); } }
如果你不想只需要這一個類,而是想要這個包所有的類,你可以這樣import java.util.*
import java.util.*; public class Test { public static void main(String[] args) { Date date = new Date(); //java.util.Date data = new java.util.Date(); } }
這樣只要是java.util包中的類都可以用了,我們可以看看這個包中還有什么其他類:
但是我們更建議顯式的指定要導入的類名. 否則還是容易出現(xiàn)沖突的情況。因為在一個類不僅僅在一個包中,有時候這個類在另一個包中內容是不一樣的,為了讓編譯器可以更好的為我們服務,我們盡量定義詳細的類名,而不是一個籠統(tǒng)的類。
import java.util.*; import java.sql.*; public class Test { public static void main(String[] args) { Date date = new Date(); //java.util.Date data = new java.util.Date(); } }
在這里Date類就編譯報錯了,所有我們還是將類的名字詳細點比較好。
可以使用import static導入包中靜態(tài)的方法和字段。
import static java.lang.Math.*; public class Test { public static void main(String[] args) { double x = 30; double y = 40; // 靜態(tài)導入的方式寫起來更方便一些. // 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 和 C++ 的 #include 差別很大. C++ 必須 #include 來引入其他文件內容, 但是 Java 不需要.
import 只是為了寫代碼的時候更方便. import 更類似于 C++ 的 namespace 和 using。
2.3自定義包
基本規(guī)則
在文件的最上方加上一個 package 語句指定該代碼在哪個包中.
包名需要盡量指定成唯一的名字, 通常會用公司的域名的顛倒形式(例如 com.bao.www )
包名要和代碼路徑相匹配. 例如創(chuàng)建 com.bao.www 的包, 那么會存在一個對應的路徑 com.bao.www 來存儲
代碼.
如果一個類沒有 package 語句, 則該類被放到一個默認包中.
操作步驟:
在 IDEA 中先新建一個包: 右鍵 src -> 新建 -> 包:
在彈出的對話框中輸入包名, 例如:com.bao.www
在包中創(chuàng)建類, 右鍵包名 -> 新建-> 類, 然后輸入類名即可.
4.此時可以看到我們的磁盤上的目錄結構已經被 IDEA 自動創(chuàng)建出來了:
5.同時我們也看到了, 在新創(chuàng)建的 Test.java 文件的最上方, 就出現(xiàn)了一個 package 語句:
2.4常見的包
java.lang:系統(tǒng)常用基礎類(String、Object),此包從JDK1.1后自動導入。
- java.lang.reflect:java 反射編程包;
- java.net:進行網(wǎng)絡編程開發(fā)包。
- java.sql:進行數(shù)據(jù)庫開發(fā)的支持包。
- java.util:是java提供的工具程序包。(集合類等) 非常重要
- java.io:I/O編程開發(fā)包。
3.static成員
public class Student{ // ... public static void main(String[] args) { Student s1 = new Student("Li leilei", "男", 18, 3.8); Student s2 = new Student("Han MeiMei", "女", 19, 4.0); Student s3 = new Student("Jim", "男", 18, 2.6); } }
在Student類中定義的成員變量,每個對象中都會包含一份(稱之為實例變量),因為需要使用這些信息來描述
具體的學生。而現(xiàn)在要表示學生上課的教室,這個教室的屬性并不需要每個學生對象中都存儲一份,而是需要讓所有的學生來共享。在Java中,被static修飾的成員,稱之為靜態(tài)成員,也可以稱為類成員,其不屬于某個具體的對象,是所有對象所共享的。
3.2static修飾成員變量
static修飾的成員變量,稱為靜態(tài)成員變量,靜態(tài)成員變量最大的特性:不屬于某個具體的對象,是所有對象所共享的,是屬于類的。
【靜態(tài)成員變量特性】
- 不屬于某個具體的對象,是類的屬性,所有對象共享的,不存儲在某個對象的空間中
- 既可以通過對象訪問,也可以通過類名訪問,但一般更推薦使用類名訪問
- 類變量存儲在方法區(qū)當中
- 生命周期伴隨類的一生(即:隨類的加載而創(chuàng)建,隨類的卸載而銷毀)
3.3 static修飾成員方法
一般類中的數(shù)據(jù)成員都設置為private,而成員方法設置為public,那設置之后,Student類中classRoom屬性如何
在類外訪問呢?
public class Student{ private String name; private String gender; private int age; private double score; private static String classRoom = "Bit306"; // ... } public class TestStudent { public static void main(String[] args) { System.out.println(Student.classRoom); } } 編譯失敗: Error:(10, 35) java: classRoom 在 extend01.Student 中是 private 訪問控制
那static屬性應該如何訪問呢?
Java中,被static修飾的成員方法稱為靜態(tài)成員方法,是類的方法,不是某個對象所特有的。靜態(tài)成員一般是通過靜態(tài)方法來訪問的。
【靜態(tài)方法特性】
- 不屬于某個具體的對象,是類方法
- 可以通過對象調用,也可以通過類名.靜態(tài)方法名(…)方式調用,更推薦使用后者
- 不能在靜態(tài)方法中訪問任何非靜態(tài)成員變量
- 靜態(tài)方法中不能調用任何非靜態(tài)方法,因為非靜態(tài)方法有this參數(shù),在靜態(tài)方法中調用時候無法傳遞this引用
3.4static成員變量初始化
注意:靜態(tài)成員變量一般不會放在構造方法中來初始化,構造方法中初始化的是與對象相關的實例屬性靜態(tài)成員變量的初始化分為兩種:就地初始化 和 靜態(tài)代碼塊初始化。
就地初始化
就地初始化指的是:在定義時直接給出初始值
public class Student{ private String name; private String gender; private int age; private double score; private static String classRoom = "Bit306"; // ... }
4.代碼塊
4.1代碼塊概念以及分類
使用 {} 定義的一段代碼稱為代碼塊。根據(jù)代碼塊定義的位置以及關鍵字,又可分為以下四種:
- 普通代碼塊
- 構造塊
- 靜態(tài)塊
- 同步代碼塊(后續(xù)講解多線程部分再談)
4.2普通代碼塊
普通代碼塊:定義在方法中的代碼塊.
public class Main{ public static void main(String[] args) { { //直接使用{}定義,普通方法塊 int x = 10 ; System.out.println("x1 = " +x); } int x = 100 ; System.out.println("x2 = " +x); } }
4.3構造代碼塊
構造塊:構造塊:定義在類中的代碼塊(不加修飾符)。也叫:實例代碼塊。構造代碼塊一般用于初始化實例成員變量
public class Student{ //實例成員變量 private String name; private String gender; private int age; private double score; public Student() { System.out.println("I am Student init()!"); } //實例代碼塊 { this.name = "bit"; this.age = 12; this.sex = "man"; System.out.println("I am instance init()!"); } public void show(){ System.out.println("name: "+name+" age: "+age+" sex: "+sex); } } public class Main { public static void main(String[] args) { Student stu = new Student(); stu.show(); } }
4.4靜態(tài)代碼塊
使用static定義的代碼塊稱為靜態(tài)代碼塊。一般用于初始化靜態(tài)成員變量。
public class Student{ private String name; private String gender; private int age; private double score; private static String classRoom; //實例代碼塊 { this.name = "bit"; this.age = 12; this.gender = "man"; System.out.println("I am instance init()!"); } // 靜態(tài)代碼塊 static { classRoom = "bit306"; System.out.println("I am static init()!"); } public Student(){ System.out.println("I am Student init()!"); } public static void main(String[] args) { Student s1 = new Student(); Student s2 = new Student(); } }
4.5關于靜態(tài)代碼塊和實例化代碼塊還有構造方法的執(zhí)行順序:
class Student { public String name; static { System.out.println("Student::static"); } { System.out.println("實例化代碼實現(xiàn)"); } public Student(String name) { this.name = name; System.out.println("構造方法實現(xiàn)"); } } public class Test { public static void main(String[] args) { Student student = new Student("xiaowang"); } }
先實現(xiàn)靜態(tài)代碼塊,然后是實例化代碼塊,最后是構造方法。
再實例化一個對象,再實現(xiàn)一次:
class Student { public String name; static { System.out.println("Student::static"); } { System.out.println("實例化代碼實現(xiàn)"); } public Student(String name) { this.name = name; System.out.println("構造方法實現(xiàn)"); } } public class Test { public static void main(String[] args) { Student student = new Student("xiaowang"); System.out.println("================"); Student student1 = new Student("wangss"); } }
靜態(tài)代碼塊沒有執(zhí)行,因為靜態(tài)代碼塊只執(zhí)行一次。
注意事項
- 靜態(tài)代碼塊不管生成多少個對象,其只會執(zhí)行一次
- 靜態(tài)成員變量是類的屬性,因此是在JVM加載類時開辟空間并初始化的
- 如果一個類中包含多個靜態(tài)代碼塊,在編譯代碼時,編譯器會按照定義的先后次序依次執(zhí)行(合并)
- 實例代碼塊只有在創(chuàng)建對象時才會執(zhí)行
總結
到此這篇關于Java SE封裝、包、static關鍵字和代碼塊的文章就介紹到這了,更多相關JavaSE封裝包static關鍵字和代碼塊內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Lombok中@Builder和@SuperBuilder注解的用法案例
@Builder?是?lombok?中的注解,可以使用builder()構造的Person.PersonBuilder對象進行鏈式調用,給所有屬性依次賦值,這篇文章主要介紹了Lombok中@Builder和@SuperBuilder注解的用法,需要的朋友可以參考下2023-01-01Spring MVC 基于URL的映射規(guī)則(注解版)
這篇文章主要介紹了Spring MVC 基于URL的映射規(guī)則(注解版) ,詳細的介紹了幾種方式,有興趣的可以了解一下2017-05-05