-
四种权限修饰符
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; } }
后续在学习实践中再进行补充和完善。