-
四種權限修飾符
java 有四種權限修飾符:public > protected > (default) > private
public protected default private 同一個類(自己) yes yes yes yes 同一個包(同級) yes yes yes NO 不同包的子類(繼承) yes yes NO NO 不同包,非子類(路人) yes NO NO NO 注意事項:(default) 並不是 default 關鍵字,而是成員變量前什麼也不寫,例如:
int num = 6;
-
內部類
一個物體內部可以包含另一個物體:那麼一個類的內部也能包含另一個類
例如:電腦和CPU、汽車與發動機的關係
內部類分爲:
-
成員內部
Notice:內用外,隨便訪問;外用內,需要通過內部類對象訪問
使用成員內部類,有兩種方式:
直接:
外部類名稱.內部類名稱 對象名 = new 外部類名稱().new 內部類名稱();
間接:在外部類的方法中,使用內部類,然後 main 調用外部類的方法
public class ExteriorClass { String str = "exterior"; public void exteriorMethod(){ System.out.println("exterior method execute"); // 外部類不能訪問內部類成員變量 // System.out.println(inside); // 錯誤寫法 System.out.println(new InsideClass().num); } public class InsideClass{ int num = 6; public void insideMethod(){ System.out.println("inside method execute"); // 內部類可以訪問外部類成員變量 System.out.println(str); } } public static void main(String[] args) { ExteriorClass exterior = new ExteriorClass(); // 通過外部類方法 間接使用 內部類對象 exterior.exteriorMethod(); // exterior method execute 6 // 不能直接創建內部類 // InsideClass inside = new InsideClass(); // 錯誤寫法 ExteriorClass.InsideClass inside = new ExteriorClass().new InsideClass(); inside.insideMethod(); // inside method execute exterior } }
-
局部內部類(包含匿名內部類)
定義在方法內部的,就是局部內部類
局部:只有在當前所屬的方法中才能使用
public class Outer{ // 外部類方法 public void outerMethod(){ System.out.println("outer method execute"); // outer method execute // 局部內部類 class Inner{ int num = 6; // 內部類方法 public void innerMethod(){ System.out.println(num); } } // 在外部方法中 使用內部類 Inner inner = new Inner(); inner.innerMethod(); // 6 } public static void main(String[] args) { Outer outer = new Outer(); outer.outerMethod(); } }
Notice:如果 局部內部類對象 需要用到 方法的局部變量,那麼這個局部變量必須是 final 修飾的
從 java 8+ 開始,關鍵字 final 可以省略
原因:生命週期
-
new出來的對象保存在 堆內存 中
-
局部變量在 棧內存 中
-
方法運行結束之後,出棧,局部變量會回收;但 new 出來的對象會持續在堆內存中,直到被回收,那麼這時如果對象訪問局部變量,就會出現問題,所以這裏的局部變量是常量,會copy一份在堆內存中
public class OuterClass{ public void outerMethod(){ final String str = "johny"; // 局部變量 // str = "test"; // 錯誤寫法 class Inner{ public void innerMethod(){ System.out.println(str); // johny } } Inner inner = new Inner(); inner.innerMethod(); } public static void main(String[] args){ OuterClass outer = new OuterClass(); outer.outerMethod(); } }
-
-
匿名內部類
如果接口的實現類(或者父類的子類)只需要使用唯一一次
那麼這種情況下就可以省略該類的定義,使用匿名內部類
定義格式:
接口名稱 對象名 = new 接口名稱(){ @Override // 覆蓋重寫所有抽象方法 }; // new 代表創建對象的動作;接口名稱就是匿名內部類需要實現的接口 // { ... } 纔是匿名內部類的內容
// 接口 class interface MyInterface{ void method(); } // 外部類 public class DemoMain{ public static void main(String[] args){ // 按照常規的實現類來訪問成員方法 // MyInterface obj = new MyInterfaceImpl(); // obj.method(); // 匿名內部類的寫法 MyInterface obj = new MyInterface(){ @Override public void method(){ System.out.println("anonymity class method execute"); } }; // 使用匿名類對象訪問成員方法 obj.method(); // anonymity class method execute // 匿名內部類 + 匿名對象的寫法 new MyInterface(){ @Override public void method(){ System.out.println("anonymity object call method execute"); } }.method(); // anonymity object call method execute } }
Notice:
-
匿名內部類,在創建對象時,只能使用一次,如果要多次創建對象,需要單獨定義實現類
-
匿名對象,在調用方法時,只能調用一次
-
-
-
類作爲成員變量 / 接口作爲成員變量
用 武器類 作爲 英雄對象 的 成員變量
// 英雄類 public class Hero { private String name; private Weapon weapon; // 類當做成員變量 private Skill skill; // 接口當做成員變量 public Hero(){ } public Hero(String name, Weapon weapon, Skill skill){ this.name = name; this.weapon = weapon; this.skill = skill; } public void attack(){ if (this.skill != null){ skill.use(); } } public void setName(String name) { this.name = name; } public void setWeapon(Weapon weapon) { this.weapon = weapon; } public void setSkill(Skill skill) { this.skill = skill; } public String getName() { return name; } public Weapon getWeapon() { return weapon; } public Skill getSkill() { return skill; } }
// 武器類 public class Weapon { private String code; public Weapon(){ } public Weapon(String code){ this.code = code; } public void setCode(String code) { this.code = code; } public String getCode() { return code; } }
// 技能接口 public interface Skill { void use(); }
// 技能實現類 public class SkillImpl implements Skill { @Override public void use() { System.out.println("施放技能攻擊"); } }
// 主方法 public class DemoMain { public static void main(String[] args) { Hero hero = new Hero(); hero.setName("蓋倫"); Weapon weapon = new Weapon(); weapon.setCode("AK-47"); hero.setWeapon(weapon); System.out.println("英雄的名字:" + hero.getName()); // 英雄的名字:蓋倫 System.out.println("英雄的武器:" + hero.getWeapon().getCode()); // 英雄的武器:AK-47 // 設置英雄技能 hero.setSkill(new SkillImpl()); // 使用單獨定義的實現類 hero.attack(); // 施放技能攻擊 // 使用匿名內部類 Skill skill = new Skill() { @Override public void use() { System.out.println("內部類 施放技能攻擊"); } }; hero.setSkill(skill); hero.attack(); // 內部類 施放技能攻擊 // 使用匿名內部類 + 匿名對象 hero.setSkill(new Skill() { @Override public void use() { System.out.println("內部類 匿名對象 施放技能攻擊"); } }); hero.attack(); // 內部類 匿名對象 施放技能攻擊 } }
-
接口作爲方法的參數和返回值
import java.util.ArrayList; import java.util.List; public class DemoInterface { public static void main(String[] args) { // List 是 實現類 ArrayList 的接口 List<String> list = new ArrayList<>(); List<String> result = addElement(list); for (int i = 0; i < result.size(); i++){ System.out.println(result.get(i)); // johny anson } } public static List<String> addElement(List<String> list){ list.add("johny"); list.add("anson"); return list; } }
後續在學習實踐中再進行補充和完善。