相信大家都會發現很多面向對象的編程語言中都有比較多的訪問修飾符,拿Java來說,當我們在類作爲模型創建對象之後可以訪問對象擁有的屬性或者方法。這些方法的使用卻是大有區別。這裏對常見的幾種修飾符、重載重寫的方法、靜態成員的使用方法簡單進行一下說明。
一、Java中的幾種訪問修飾符
Java作爲一門優秀的面對對象編程語言,強大在於Java非常靈活、涵蓋面廣、可移植性高等等優點,這裏對Java中的幾種訪問修飾符做一下說明。
public:
作爲一種公有性質的訪問修飾符,它的使用面非常廣,在創建項目的時候我們可以發現,public訪問修飾符在任意的位置都可以訪問。
private:
作爲一種私有屬性的訪問修飾符,它的使用面最窄,除了本類中可以進行訪問之外都不能進行對於私有變量的修改或者是私有成員方法的使用。但是相對應的,該種訪問修飾符的適用面越窄,它的安全性越高。
protected:
作爲一種受保護的訪問修飾符,它的使用面在public和private之間。使用的方法顧名思義,它在項目中的使用的時候除了在一個project下的同一個package以外的類和父類下的子類中都不能進行跨包訪問。
默認:
很多情況下,程序員會提前想好需求再動手,不排除很多老手們想到哪裏就寫到哪裏。默認形態下的訪問修飾符就給了很大的空間。默認類型的訪問修飾符只在當前的package下可以進行訪問。
總結:
訪問修飾符 | public | private | protected | 默認 |
---|---|---|---|---|
訪問範圍 | 任意位置 | 本類 | 在當前類、同包子類/非子類、跨包子類調用;跨包非子類不允許 | 允許在當前類、同包子類/非子類調用;跨包子類/非子類不允許調用 |
上面的總結想必已經言簡意賅的說明了常用訪問修飾符的訪問方式。
這裏我們用代碼實驗一下對於不同訪問修飾符的使用場景。
People.java:
/* final class:該類沒有子類 public final class \ final public class
* final 方法:該方法不允許被子類重寫,但是可以正常被子類繼承使用
* final 方法內局部變量:只要在具體被使用之前進行賦值即可,一旦賦值不允許被修改
* 類中成員屬性:賦值過程:1、定義直接初始化 2、構造方法 3、構造代碼塊
*/
public class People{
/*
* 公有的訪問修飾符:public
* 私有的訪問修飾符:private
* 受保護的訪問修飾符:protected
* 默認
*
* private:本類
* 默認:本類、同包
* protected:本類、同包、子類
* public:本類、同包、子類、其他
* 訪問範圍自上而下依次擴大,限制能力自下而上依次增強
*/
/*
* private:只允許在本類中進行訪問
* public:允許在任意位置訪問
* protected:允許在當前類、同包子類/非子類、跨包子類調用;跨包非子類不允許
* 默認:允許在當前類、同包子類/非子類調用;跨包子類/非子類不允許調用
*/
private String name = "妮妮";// 暱稱
protected int month;// 年齡
String species = "中國人";// 人種
public final static int temp = 12;// 可在子類定義和父類重名的屬性
static {
System.out.println("我是父類的靜態代碼塊");
}
public static int st2 = 23;
private static int st1 = 22;
{
// temp=12;
System.out.println("我是父類的構造代碼塊");
}
// 父類的構造不允許被繼承、不允許被重寫,但是會影響子類對象的實例化
public Animal() {
month = 2;
// temp=20;
System.out.println("我是父類的無參構造方法");
}
public Animal(String name, int month) {
this.name = name;
this.month = month;
System.out.println("我是父類的帶參構造方法");
}
public String getName() {
// this.temp=22;
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
// 喫東西
public void eat() {
System.out.println(this.getName() + "在喫東西");
}
public void eat(String name) {
System.out.println(name + "在喫東西");
}
}
Boy.java:
/**
* 繼承是一種類與類之間的關係
* 使用已經存在的類的定義作爲基礎建立新的類
* 新類的定義可以增加新的數據或者新的功能,也可以使用父類的功能,但不能選擇性地繼承父類
* 父類(基類) 子類(派生類) extends表示繼承
* @author Administrator
*/
public class Boy extends People {
private double weight;// 體重
public int temp=300;
public static int st3 = 44;
static {
System.out.println("我是子類的靜態代碼塊");
}
{
System.out.println("我是子類的構造代碼塊");
}
public Boy() {
// People temp=new Peole();
// private的屬性不能在類外進行訪問使用
// temp.name;
// public的屬性可以允許在任意的位置訪問
// this.temp=12;
// this.month=23;
// this.species="";
System.out.println("我是子類的無參構造方法");
}
public Boy(String name, int month) {
/*
* 子類構造默認調用父類無參構造方法 可以通過super()
* 調用父類允許被訪問的其他構造方法 super()
* 必須放在子類構造方法有效代碼第一行
*/
super(name, month); // this
System.out.println("我是子類的帶參構造方法");
}
public static void say() {
// this.weight=20;
// super.name="aa";
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
// 跑動的方法
public void run() {
// super();
// eat();
// People();
System.out.println(this.getName() + "是一個" + this.getSpecies() + ",它在快樂的奔跑");
}
}
二、重寫和重載的區別在哪裏?
方法重載:
1、同一個類中
2、方法名相同,參數列表不同(參數順序、個數、類型)
3、方法返回值、訪問修飾符任意
4、與方法的參數名無關
方法重寫:
1、有繼承關係的子類中
2、方法名相同,參數列表相同(參數順序、個數、類型)
3、方法返回值相同,訪問修飾符,訪問範圍需要大於等於父類的訪問範圍
(如果在使用方法重寫的時候用小於父類的訪問範圍,報錯:不能降低父類當中的成員方法的可見性)
4、與方法的參數名無關
三、靜態方法和非靜態方法的執行順序?在子類和父類中又有何區別?
靜態方法和最終方法不能被重寫;
但靜態方法在子類中可以通過隱藏父類方法的方式重新實現。
重寫方法的返回值應該與父類方法相同或者是父類方法返回值的子類; 重寫方法訪問權限必須大於等於父類方法。
先執行父類的靜態成員再執行子類的靜態成員; 初始化父類的屬性再訪問父類構造代碼塊之後訪問父類無參構造方法;
最後依次初始化子類屬性訪問子類構造代碼塊,無參構造方法;
繼承後的初始化順序:
父類靜態–子類靜態–父類普通代碼塊–父類構造代碼塊–子類普通代碼塊–子類構造代碼塊