Java 面向对象知识扩展

四种权限修饰符

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、汽车与发动机

扫描二维码关注公众号,回复: 7576162 查看本文章

内部类分为:成员内部类 和 局部内部类

1)成员内部

注意事项:

  1. 内用外,随便访问,外用内,需要通过内部类对象访问
  2. 使用成员内部类,有两种方式:
    • 直接:外部类名称.内部类名称 对象名 = 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 可省略

原因:声明周期

  1. new出来的对象保存在 堆内存 中
  2. 局部变量在 栈内存 中
  3. 方法运行结束之后,出栈,局部变量会回收;但 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
    }
}

注意事项:

  1. 匿名内部类,在创建对象时,只能使用一次,如果要多次创建对象,需要单独定义实现类
  2. 匿名对象,在调用方法时,只能调用一次

类作为成员变量 / 接口作为成员变量

用武器类、技能接口作为英雄对象的成员变量的例子:

// 英雄类
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 ~

猜你喜欢

转载自www.cnblogs.com/kaichenkai/p/10549844.html