1訪問控制符
Java提供了3個訪問控制符:private、protected、public,分別代表了3個訪問控制級別,另外還有一個不加任何訪問控制符的的訪問控制級別。
|
public |
protected |
default |
private |
同一類中 |
√ |
√ |
√ |
√ |
同一包中(子類與無關類) |
√ |
√ |
√ |
|
不同包的子類 |
√ |
√ |
|
|
不同包中的無關類 |
√ |
|
|
|
Private:表示私有的,表示類訪問權限。只能在本類中訪問,離開本類之後就不能訪問;
Default(缺省):表示包私有,表示包訪問權限,訪問者的包必須和當前類的包相同纔行;
Protected:表示子類訪問權限,同包中的可以訪問,即使不同包,但有繼承關係也可以訪問;
Public:全局的,公共的訪問權限,在項目的任何地方都可以訪問。
訪問控制符使用原則:
1)類裏的絕大部分成員變量都應該使用private修飾,只有一些static修飾的、類似全局變量的成員變量,纔可能考慮使用public修飾。除此之外,有些方法只用於輔助實 現該類的其他方法,這些方法被稱爲工具方法,工具方法也應該使用private修飾。
2)如果某個類主要用做其他類的父類,該類裏包含的大部分方法可能僅希望被其子類重寫,而不想被外界直接調用,則應該使用protected修飾這些方法。
3)希望暴露出來給其他類自由調用的方法應該使用public修飾。因此,類的構造器通過使用public修飾,從而允許在其他地方創建該類的實例。因爲外部類通常都希望被 其他類自由使用,所有大部分外部類都使用public修飾。
2.包的聲明與訪問
2.1 包的概念
java的包,其實就是文件夾,包裏存放的是類文件。當類文件很多的時候,通常我們會採用多個包進行存放管理他們,這種方式稱爲分包管理。
類中聲明的包必須與實際class文件所在的文件夾情況相一致,即類聲明在a包下,則生成的.class文件必須在a文件夾下,否則,程序運行時會找不到類。
2.2 包的聲明格式
通常使用公司網址反寫,可以有多層包,包名採用全部小寫字母,多層包之間用”.”連接
類中包的聲明格式:
package 包名.包名.包名…;
注意:聲明包的語句,必須寫在程序有效代碼的第一行(註釋不算),即在聲明包package後,定義所有類class前,使用導包import包名.包名.類名;
2.3 包的訪問
在訪問類時,爲了能夠找到該類,必須使用含有包名的類全名(包名.類名)。
包名.包名….類名
如:java.util.Scanner
java.util.Random
帶有包的類,創建對象格式:包名.類名變量名 = new包名.類名();
前提:包的訪問與訪問權限密切相關,這裏以一般情況來說,即類用public修飾的情況。
2.4 import導包
通過import導包的方式可以使用該類,可以避免使用全類名編寫(即,包類.類名)。
導包的格式:import 包名.類名;
import的作用:使用import可以省略寫包名;(使用import static可以連類名都省略)
Java默認爲所有源文件導入java.lang包下所有類,因此在java程序中使用String、System類時都無需使用import語句來導入這些類。
2.5 java的常用包
java.lang:該包下包含了java語言的核心類,如String、Math、System類等。使用這個包下的類無需使用import語句導入,系統會自動導入這個包下所有類;
java.util:該包下包含了java的大量工具類/接口和集合框架類/接口,如Arrays和List 、Set等;
java.net:該包下包含了一些java網絡編程相關的類/接口;
java.io:該包下包含了一些java輸入輸出編程相關的接口/類;
java.text:該包下包含了一些java格式化相關的類;
java.sql:該包下包含了java進行JDBC數據庫編程的相關類/接口;
java.awt:該包下包含了抽象窗口工具集的相關類/接口;
java.swing:該包下包含了Swing圖形用戶界面編程的相關類/接口。
3.構造器
3.1構造器概述
構造器是一個特殊的方法,這個特殊的方法用於創建對象和初始化對象數據。
構造方法的格式:
修飾符 構造方法名(參數列表)
{
}
3.2構造器的特點:
類都有一個默認構造器,當不顯示的定義構造器的時候,編譯器會在編譯的時候,提供一個默認構造器.
1):構造器的名字必須和當前所在類的類名相同.
2):不需要定義返回值類型,更加不能使用void作爲返回.構造器的目的在於創建和返回當前類的對象,即使要編寫返回類型,也應該是當前類名,如:Student Student(){}, 既然和當前類名相同,就規定統統省略.
3):構造器中不需要使用return來返回當前構造的對象.
3.3默認構造器:
1):無參數,無方法體.
2):構造器的訪問修飾符和當前類的修飾符相同(是否有public).
3):一旦在類中顯示地提供了構造器,則默認的構造器就不再提供了.
一個類至少有一個構造器(即使沒有自定義,編譯器也會創建一個默認的).但一旦程序員提供了自定義的構造器,系統就不再提供默認的構造器。
3.4方法重載與構造器重載的區別
方法的重載:在同一個類中,方法同名,但是參數列表不同.解決了相同的功能方法,因爲參數列表不同,而帶來參數名不同的問題.
構造器重載:不同類的構造器是不相同的. 對於構造器重載來說,肯定是在同一個類中,並且構造器都是和類名相同.所以在同一個類中的多個構造器就必須參數列表不同 (參數類型,參數個數,參數順序).
爲了在構造器中調用另一個構造器的初始化代碼,又不會重新創建一個java對象,可以使用this關鍵字來調用相應的構造器。使用this調用另一個重載的構造器只能在構造器中使用,而且必須作爲構造器執行體的第一條語句。使用this調用重載的構造器時系統會根據this後括號裏的實參來調用形參列表與之對應的構造器。
4.this關鍵字
4.1 this概述
this表示當前對象。當一個對象創建之後,JVM會分配一個引用自身的引用:this
this主要存在的兩個位置:
構造器中: 表示當前創建的對象.
方法中: 哪一個對象調用this所在的方法,那麼此時this就表示哪一個對象.
4.2 this調用構造方法
構造方法之間的調用,可以通過this關鍵字來完成。構造方法調用格式:this(參數列表);
構造方法的調用
class Person {
//Person的成員屬性
privateint age;
privateString name;
//無參數的構造方法
Person(){
}
//給姓名初始化的構造方法
Person(Stringnm) {
name= nm;
}
//給姓名和年齡初始化的構造方法
Person(Stringnm, int a) {
//調用其他構造方法,需要通過this關鍵字來調用
this(nm);
//給年齡初始化
age= a;
}
}
4.3 成員變量和局部變量同名問題
當在方法中出現了局部變量和成員變量同名的時候,那麼在方法中可以在成員變量名前面加上this.來區別成員變量和局部變量
class Person {
privateint age;
privateString name;
//給姓名和年齡初始化的構造方法
Person(Stringname, int age) {
this.name= name;
this.age= age;
}
publicvoid speak() {
System.out.println("name="+ this.name + ",age=" + this.age);
}
}
class PersonDemo {
publicstatic void main(String[] args) {
Personp = new Person("薛之謙", 32);
p.speak();
}
}
對於static修飾的方法而言,可以使用類來直接調用該方法,如果在static修飾的方法中使用this關鍵字,則這個關鍵字就無法指向合適的對象。所以static修飾的方法中不能使用this引用。
5.super關鍵字
5.1 super概述
Super是java提供的一個關鍵字,super用於限定該對象調用它從父類繼承得到的實例變量或方法。正如this不能出現在static修飾的方法中一樣,super也不能出現在static修飾的方法中。如果在構造器中使用super,則super用於限定該構造器初始化的是該對象從父類繼承得到的實例變量,而不是該類自己定義的實例變量。
如果子類裏沒有包含和父類同名的成員變量,那麼在子類實例方法中訪問該成員變量時,則無須顯式使用super或父類名作爲調用者。如果在某個方法中訪問名爲a的成員變量,但沒有顯式指定調用者,則系統查找a的順序爲:
1)查找該方法中是否有名爲a的局部變量;
2)查找當前類中是否包含名爲a的成員變量;
3)查找a的直接父類中是否包含名爲a的成員變量,依次上溯a的所有父類,直到java.lang.Object類,如果最終不能找到名爲a的成員變量,則系統出現編譯錯誤。
5.2子父類中構造方法的調用
在創建子類對象時,父類的構造方法會先執行,因爲子類中所有構造方法的第一行有默認的隱式super();語句。
格式:
調用本類中的構造方法
this(實參列表);
調用父類中的空參數構造方法
super();
調用父類中的有參數構造方法
super(實參列表);
子類會繼承父類中的內容,所以子類在初始化時,必須先到父類中去執行父類的初始化動作,然後纔可以使用父類中的內容。
當父類中沒有空參數構造方法時,子類的構造方法必須有顯示的super語句,指定要訪問的父類有參數構造方法。
示例:
public class Test {
publicstatic void main(String[] args) {
newZi();
}
}
class Fu{
int num ;
Fu(){
System.out.println("Fu構造方法"+num);
num =4;
}
}
class Zi extends Fu{
Zi(){
//super(); 調用父類空參數構造方法
System.out.println("Zi構造方法"+num);
}
}
執行結果:
Fu構造方法0
Zi構造方法4
5.3子類對象創建過程的細節
使用super調用父類構造器和使用this調用構造器很像,區別在於super調用的是其父類的構造器,而this調用的是同一個類中重載的構造器。因此,使用super調用父類構造器也必須出現在子類構造器執行體的第一行,所以super調用和this調用不會同時出現。
不管是否使用super調用來執行父類構造器的初始化代碼,子類構造器總會調用父類構造器一次。子類構造器調用父類構造器分如下情況:
(1)子類構造器執行體的第一行使用super顯式調用父類構造器,系統將根據super調用裏傳入的實參列表調用父類對應的構造器。
(2)子類構造器執行體的第一行代碼使用this顯式調用本類中重載的構造器,系統將根據this調用裏傳入的實參列表調用本類中的另一個構造器。執行本類中另一個構造器時即會調用父類構造器。
(3)子類構造器執行體中既沒有super調用,也沒有this調用,系統將會在執行子類構造器之前,隱式調用父類無參數構造器。
注意:
1)類中的構造方法默認第一行都有隱式的super()語句,在訪問父類中的空參數構造方法。所以父類的構造方法既可以給自己的對象初始化,也可以給自己的子類對象初始化。
2)如果默認的隱式super()語句在父類中沒有對應的構造方法,那麼必須在構造方法中通過this或者super的形式明確要調用的構造方法。
6.static關鍵字
static關鍵字是靜態修飾符,一般用來修飾類中的成員。
6.1static特點
(1)被static修飾的成員變量屬於類,不屬於這個類的某個對象。(也就是說,多個對象在訪問或修改static修飾的成員變量時,其中一個對象將static成員變量值進行了修改,其他對象中的static成員變量值跟着改變,即多個對象共享同一個static成員變量)
class Demo {
publicstatic int num = 100;
}
class Test {
publicstatic void main(String[] args) {
Demod1 = new Demo();
Demod2 = new Demo();
d1.num= 200;
System.out.println(d1.num);//結果爲200
System.out.println(d2.num);//結果爲200
}
}
(2)被static修飾的成員可以並且建議通過類名直接訪問。
訪問靜態成員的格式:
類名.靜態成員變量名
類名.靜態成員方法名(參數)
對象名.靜態成員變量名
對象名.靜態成員方法名(參數)
class Demo {
//靜態成員變量
publicstatic int num = 100;
//靜態方法
publicstatic void method(){
System.out.println("靜態方法");
}
}
class Test {
publicstatic void main(String[] args) {
System.out.println(Demo.num);
Demo.method();
}
}
static注意事項:
(1) 靜態內容是優先於對象存在,只能訪問靜態,不能使用this/super。靜態修飾的內容存於靜態區。
(2)同一個類中,靜態成員只能訪問靜態成員
(3)main方法爲靜態方法僅僅爲程序執行入口,它不屬於任何一個對象,可以定義在任意類中。
6.2定義靜態常量
開發中,我們想在類中定義一個靜態常量,通常使用public static final修飾的變量來完成定義。此時變量名用全部大寫,多個單詞使用下劃線連接。
定義格式:
publicstatic final 數據類型 變量名 = 值;
如下演示:
classCompany {
public static final String COMPANY_NAME= "演員";
public static void method(){
System.out.println("我好像在哪見過你");
}
}
當我們想使用類的靜態成員時,不需要創建對象,直接使用類名來訪問即可。
注意:
接口中的每個成員變量都默認使用public static final修飾。
所有接口中的成員變量已是靜態常量,由於接口沒有構造方法,所以必須顯示賦值。可以直接用接口名訪問。
interfaceInter {
public static final int COUNT = 100;
}
訪問接口中的靜態變量
Inter. COUNT
7.final關鍵字
final可用於修飾類、變量和方法。Final修飾變量時,表示該變量一旦獲得了初始值就不可被改變,final既可以修飾成員變量(包括類變量和實例變量),也可以修飾局部變量、形參。
7.1final的特點
(1) final修飾類不可以被繼承,但是可以繼承其他類。
class Y {}
final class Fu extendsY{} //可以繼承Y類
class Zi extends Fu{} //不能繼承Fu類
(2)final修飾的方法不可以被覆蓋,但父類中沒有被final修飾方法,子類覆蓋後可以加final。
class Fu {
// final修飾的方法,不可以被覆蓋,但可以繼承使用
public final void method1(){}
public void method2(){}
}
class Zi extends Fu {
//重寫method2方法
public final void method2(){}
}
(3)final修飾的變量稱爲常量,這些變量只能賦值一次。
final int i = 20;
i= 30; //賦值報錯,final修飾的變量只能賦值一次
(4)引用類型的變量值爲對象地址值,地址值不能更改,但是地址內的對象屬性值可以修改。
final Person p = new Person();
Person p2 = newPerson();
p = p2; //final修飾的變量p,所記錄的地址值不能改變
p.name = "小明";//可以更改p對象中name屬性值
p不能爲別的對象,而p對象中的name或age屬性值可更改。
(5)修飾成員變量,需要在創建對象前賦值,否則報錯。(當沒有顯式賦值時,多個構造方法的均需要爲其賦值。)
class Demo {
//直接賦值
finalint m= 100;
//final修飾的成員變量,需要在創建對象前賦值,否則報錯。
finalint n;
publicDemo(){
//創建對象時所調用的構造方法中,爲變量n賦值
n = 2018;
}
}
7.2 不可變類
不可變類指的是創建該類實例後,該實例的實例變量是不可改變的。Java提供的8個包裝類和java.lang.String類都是不可變類。如果需要創建自定義的不可變類,可遵守如下規則:
(1)使用private和final修飾符來修飾該類的成員變量;
(2)提供帶參數的構造器,用於根據傳入參數來初始化類裏的成員變量;
(3)僅爲該類的成員變量提供getter方法,不要爲該類的成員提供setter方法,因爲普通方法無法修改final修飾的成員變量;
(4)如果有必要,重寫Object類的hashCode和equals方法。
總結:
(1)final修飾的成員變量一旦有了初始值就不能被重新賦值,如果既沒有在定義成員變量時指定初始值,也沒有在初始化塊、構造器中爲成員變量指定初始值,那麼這些成員變量的值將由系統默認指定(java語法規定:final修飾的成員變量必須由程序員顯式的指定初始值);
(2)final修飾局部變量時既可以在定義時指定初始值,也可以不指定初始值。如果final修飾的局部變量在定義時沒有指定默認值,則在後面代碼中可以爲該final變量賦初始值,但只能一次,不能重複賦值;
(3)當使用final修飾基本類型變量時,不能對基本類型變量重新賦值,但對引用類型變量而言,它保存的僅僅是個引用,final只保證這個引用類型變量所引用的地址不會改變,即一直引用同一個對象,但這個對象完全可以改變;
8.代碼塊
8.1局部代碼塊
局部代碼塊是定義在方法或語句中
特點:
(1)以”{}”劃定的代碼區域,此時只需要關注作用域的不同即可
(2)方法和類都是以代碼塊的方式劃定邊界的
8.2構造代碼塊
構造代碼塊是定義在類中成員位置的代碼塊
特點:
(1)優先於構造方法執行,構造代碼塊用於執行所有對象均需要的初始化動作
(2)每創建一個對象均會執行一次構造代碼塊。
8.3靜態代碼塊
靜態代碼塊是定義在成員位置,使用static修飾的代碼塊。
特點:
(1) 它優先於主方法執行、優先於構造代碼塊執行,當以任意形式第一次使用到該類時執行。
(2)該類不管創建多少對象,靜態代碼塊只執行一次。
(3) 可用於給靜態變量賦值,用來給類進行初始化。