四种权限修饰符
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 |
Notice:(default) 并不是 default 关键字, 而是成员变量 / 方法前什么也不写, 例如: int num = 6;
内部类
一个物体内部可以包含另一个物体: 那么一个类的内部也能包含另一个类, 例如 电脑和 CPU, 汽车与发动机
内部类分为: 成员内部类 和 局部内部类
1) 成员内部
注意事项:
内用外, 随便访问, 外用内, 需要通过内部类对象访问
使用成员内部类, 有两种方式:
直接: 外部类名称. 内部类名称 对象名 = 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
- }
- }
2) 局部内部类 (包含匿名内部类)
定义在方法内部的, 就是局部内部类; 局部, 就是只有在当前所属的方法中才能使用
- 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();
- }
- }
注意事项: 如果局部内部类对象需要用到方法的局部变量, 那么这个局部变量必须是 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();
- }
- }
3) 匿名内部类
如果接口的实现类 (或者父类的子类) 只需要使用唯一一次
那么这种情况下就可以省略该类的定义, 使用匿名内部类
定义格式:
接口名称 对象名 = new 接口名称 (){
- @Override
- // 覆盖重写所有抽象方法
- };
- // new 代表创建对象的动作; 接口名称就是匿名内部类需要实现的接口
- // { ... } 才是匿名内部类的内容
demo:
- // 接口
- 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
- }
- }
注意事项:
匿名内部类, 在创建对象时, 只能使用一次, 如果要多次创建对象, 需要单独定义实现类
匿名对象, 在调用方法时, 只能调用一次
类作为成员变量 / 接口作为成员变量
用武器类, 技能接口作为英雄对象的成员变量的例子:
- // 英雄类
- 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;
- }
- }
后续在学习实践中再进行补充和完善.
ending ~
来源: http://www.bubuko.com/infodetail-3255230.html