JAVA网络爬虫
HttpClient

导航

 

内部类—相关操作

  1. 成员内部类

    • Body类

      package cn.xiaoge.day11.demo03;
      
      public class Body { // 外部内
      
          public class Heart { // 成员内部类
      
              // 内部类的方法
              public void beat() {
                  System.out.println("心脏跳动: 蹦蹦蹦! ");
                  System.out.println("我叫: " + name); // 正确写法!
              }
      
          }
      
          // 外部类的成员变量
          private String name;
      
          // 外部类的方法
          public void methodBody() {
              System.out.println("外部类的方法");
              new Heart().beat();
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      }
      
    • 执行路口

      package cn.xiaoge.day11.demo03;
      
      /*
      如果一个事物的内部包含另一个事物, 那么这就是一个类内部包含另一个类.
      例如: 身体和心脏的关系. 又如: 汽车和发动机的关系.
      
      分类:
      1. 成员分类
      2. 局部内部类(包含匿名内部类)
      
      成员内部类的定义格式:
      修饰符 class 外部类名称{
          修饰符 class 内部类名称{
              // ...
          }
          // ...
      }
      
      注意: 内用外, 随意访问; 外用内, 需要内部类对象.
      
      ===============================
      如何使用成员内部类?有两种方式:
      1. 间接方式: 在外部类的方法当中, 使用内部类: 然后main只是调用外部类的方法.
      2. 直接方式: 公式:
      类名称 对象名 = new 类名称();
      [外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();]
       */
      
      public class Demo01InnerClass {
      
          public static void main(String[] args) {
              Body body = new Body(); // 外部类对象
      
              // 通过外部类的对象, 调用外部类的方法, 里面间接在使用内部类Heart
              body.methodBody();
              System.out.println("======================");
      
              // 按照公式写
              Body.Heart heart = new Body().new Heart();
              heart.beat();
          }
      
      }
      
      // 运行结果
      外部类的方法
      心脏跳动: 蹦蹦蹦! 
      我叫: null
      ======================
      心脏跳动: 蹦蹦蹦! 
      我叫: null
      
  2. 内部类访问外部类的成员变量

    • Outer类

      package cn.xiaoge.day11.demo03;
      
      // 如果出现个了重名现象, 那么格式是: 外部类名称.this.外部类成员变量名
      public class Outer {
      
          int num = 10;   // 外部类的成员变量
      
          public class Inner {
      
              int num = 20;   // 内部类的成员变量
      
              public void methodInner() {
                  int num = 30;  // 内部类方法的局部变量
                  System.out.println(num); // 30 局部变量, 就近原则
                  System.out.println(this.num); // 20 内部类的成员变量
                  System.out.println(Outer.this.num); // 10 外部类的成员变量
              }
      
          }
      
      }
      
    • 执行路口

      package cn.xiaoge.day11.demo03;
      
      public class Demo02InnerClass {
      
          public static void main(String[] args) {
              // 外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
              Outer.Inner inner = new Outer().new Inner();
              inner.methodInner();
          }
      
      }
      
      // 运行结果
      30
      20
      10
      
  3. 局部内部类

    • Outer类

      package cn.xiaoge.day11.demo04;
      
      /*
      如果一个类是定义在一个方法内部的, 那么这就是一个局部内部类.
      "局部": 只有当前所属的方法才能使用它, 除了这个方法外面就不能使用了.
      
      定义格式:
      修饰符 class 外部类名称 {
          修饰符 返回值类型 外部类方法名称(参数列表) {
              class 局部内部类名称 {
                  // ...
              }
          }
      }
      
      小节一个类的权限修饰符: public > protected > (default) > private
      定义一个类的时候, 权限修饰符规则:
      1. 外部类:     public / (default)
      2. 成员内部类:   public / protected / (default) / private
      3. 局部内部类:   什么都不能写
      */
      
      public class Outer {
      
          public void methodOuter() {
              class Inner { // 局部内部类
                  int num = 10;
                  public void methodInner() {
                      System.out.println(num); // 10
                  }
              }
      
              Inner inner = new Inner();
              inner.methodInner();
          }
      
      }
      
    • 执行路口

      package cn.xiaoge.day11.demo04;
      
      public class DemoMain {
      
          public static void main(String[] args) {
              Outer obj = new Outer();
      
              obj.methodOuter();
      
          }
      
      }
      
      // 运行结果
      10
      
  4. 局部内部类访问方法的局部变量

    • 必须是有效的final成员变量

      package cn.xiaoge.day11.demo04;
      
      /*
      局部内部类, 如果希望访问所在方法的局部变量, 那么这个局部变量必须是[有效final的].
      
      备注: 从Java 8+开始, 只要局部变量数值不变, 那么final关键字可以省略.
      
      原因:
      1. new出来的对象在堆内存当中.
      2. 局部变量是跟着方法走的, 在栈内存当中.
      3. 方法运行结束之后, 立刻出栈, 局部变量就会立刻消失.
      4. 但是new出来的对象会在堆当中持续存在, 直到垃圾回收消失.
       */
      
      public class MyOuter {
      
          public void methodOuter() {
              // num变量只能赋值一次, 再次赋值时 下面的局部内部类引用的num就会报错
              int num = 10;
      
              class MyInner {
                  public void methodInner() {
                      System.out.println(num);
                  }
              }
      
          }
      
      }
      
  5. 匿名内部类

    • MyInterface接口

      package cn.xiaoge.day11.demo05;
      
      public interface MyInterface {
      
          public abstract void method1(); // 抽象方法
      
          public abstract void method2(); // 抽象方法
      
      }
      
    • MyInterfacImpl实现类

      package cn.xiaoge.day11.demo05;
      
      public class MyInterfacImpl implements MyInterface {
      //    @Override
      //    public void method() {
      //        System.out.println("实现类覆盖重写了方法! ");
      //    }
      
          @Override
          public void method1() {
              System.out.println("111111111111111");
          }
      
          @Override
          public void method2() {
              System.out.println("222222222222222");
          }
      }
      
    • 执行路口

      package cn.xiaoge.day11.demo05;
      
      /*
      如果接口的实现类 (或者是父类的子类) 只需要使用唯一的一次.
      那么这种情况下就可以省略掉该类的定义, 而改为使用[匿名内部类].
      
      匿名内部类的定义格式:
      接口名称 对象名 = new 接口名称() {
          // 覆盖重写所有抽象方法
      }
      
      对格式"new 接口名称() {...}"进行解析:
      1. new代表创建对象的动作
      2. 接口名称就是匿名内部类需要实现那个接口
      3. {...}这才是匿名内部类的内容
      
      另外还要注意几点问题:
      1. 匿名内部类, 在[创建对象]的时候, 只能使用唯一一次.
      如果希望多次创建对象, 而且类的内容一样的话, 那么就必须单独定义实现类了.
      
      2. 匿名对象, 在[调用方法]的时候, 只能调用唯一一次.
      如果希望同一对象, 调用多次方法, 那么必须给对象起个名字.
      
      3. 匿名内部类是省略了[实现类/子类名称], 但是匿名对象是省略了[对象名称]
      强调: 匿名内部类和匿名对象不是一回事!!!
       */
      
      public class DemoMain {
      
          public static void main(String[] args) {
              // MyInterface obj = new MyInterfacImpl();
              // obj.method();
      
              // MyInterface some = new MyInterface();  // 错误写法
      
              // 使用匿名内部类, 但不是匿名对象, 对象名称就叫objA
              MyInterface objA = new MyInterface() {
                  @Override
                  public void method1() {
                      System.out.println("匿名内部类实现了方法! 111-A");
                  }
      
                  @Override
                  public void method2() {
                      System.out.println("匿名内部类实现了方法! 222-A");
                  }
              };
      
              objA.method1();
              objA.method2();
              System.out.println("=================================");
      
              // 使用匿名内部类, 而且省略了对象名称, 也是匿名对象.
              new MyInterface() {
                  @Override
                  public void method1() {
                      System.out.println("匿名内部类实现了方法! 111-B");
                  }
      
                  @Override
                  public void method2() {
                      System.out.println("匿名内部类实现了方法! 222-B");
                  }
              }.method1();
      
              // 因为匿名对象无法调用第二次方法, 所以需要在创建一个匿名内部类的匿名对象.
              new MyInterface() {
                  @Override
                  public void method1() {
                      System.out.println("匿名内部类实现了方法! 111-B");
                  }
      
                  @Override
                  public void method2() {
                      System.out.println("匿名内部类实现了方法! 222-B");
                  }
              }.method2();
          }
      
      }
      
      // 运行结果
      匿名内部类实现了方法! 111-A
      匿名内部类实现了方法! 222-A
      =================================
      匿名内部类实现了方法! 111-B
      匿名内部类实现了方法! 222-B
      
  6. 类作为成员变量类型

    • Hero类

      package cn.xiaoge.day11.demo06;
      
      // 游戏当中的英雄角色类
      public class Hero {
      
          private String name; // 英雄的名字
          private int age;     // 年龄
          private Weapon weapon; // 武器
      
          public Hero() {
          }
      
          public Hero(String name, int age, Weapon weapon) {
              this.name = name;
              this.age = age;
              this.weapon = weapon;
          }
      
          public void attack() {
              System.out.println("年龄为" + age + "的" + name + "正在用" + weapon.getCode() + "攻击敌方.");
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
          public Weapon getWeapon() {
              return weapon;
          }
      
          public void setWeapon(Weapon weapon) {
              this.weapon = weapon;
          }
      }
      
    • Weapon类

      package cn.xiaoge.day11.demo06;
      
      public class Weapon {
      
          private String code; // 武器的代号
      
          public Weapon() {
          }
      
          public Weapon(String code) {
              this.code = code;
          }
      
          public String getCode() {
              return code;
          }
      
          public void setCode(String code) {
              this.code = code;
          }
      }
      
    • 执行路口

      package cn.xiaoge.day11.demo06;
      
      public class DemoMain {
      
          public static void main(String[] args) {
              // 创建一个英雄角色
              Hero hero = new Hero();
              // 为英雄起一个名字, 并且设置年龄
              hero.setName("盖伦");
              hero.setAge(20);
      
              // 创建一个武器对象
              Weapon weapon = new Weapon("霜之哀伤");
              // 为英雄配备武器
              hero.setWeapon(weapon);
      
              // 年龄为20的盖伦正在用霜之哀伤攻击敌方.
              hero.attack();
          }
      
      }
      
      // 运行结果
      年龄为20的盖伦正在用霜之哀伤攻击敌方.
      
  7. 接口作为成员变量类

    • Skill接口

      package cn.xiaoge.day11.demo07;
      
      public interface Skill {
      
          public abstract void use(); // 释放技能的抽象方法
      
      }
      
    • Hero类

      package cn.xiaoge.day11.demo07;
      
      public class Hero {
          private String name; // 英雄的名称
          private Skill skill; // 英雄的技能
      
          public Hero() {
          }
      
          public Hero(String name, Skill skill) {
              this.name = name;
              this.skill = skill;
          }
      
          public void attack() {
              System.out.println("我叫" + name +", 开始施放技能: ");
              skill.use(); // 调用接口中的抽象方法
              System.out.println("施放技能完成! ");
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Skill getSkill() {
              return skill;
          }
      
          public void setSkill(Skill skill) {
              this.skill = skill;
          }
      }
      
    • 执行路口

      package cn.xiaoge.day11.demo07;
      
      public class DemoGame {
      
          public static void main(String[] args) {
              Hero hero = new Hero();
              hero.setName("李白"); // 设置英雄的名称
      
              // 使用匿名内部类
              // Skill skill = new Skill() {
              //     @Override
              //     public void use() {
              //         System.out.println("凤凰飞天! ");
              //     }
              // };
              // 设置英雄的技能
              // hero.setSkill(skill);
      
              hero.setSkill(new Skill() {
                  @Override
                  public void use() {
                      System.out.println("凤凰起飞! ");
                  }
              });
              hero.attack();
      
          }
      
      }
      
      // 运行结果
      我叫李白, 开始施放技能: 
      凤凰起飞! 
      施放技能完成! 
      
  8. 接口作为方法的参数或返回值

    • DemoInterface类

      package cn.xiaoge.day11.demo07;
      
      import java.util.ArrayList;
      import java.util.List;
      
      public class DemoInterface {
      
          public static void main(String[] args) {
              List<String> list = new ArrayList();
              List<String> result = addName(list);
              for (int i = 0; i < result.size(); i++) {
                  System.out.println(result.get(i));
              }
          }
      
          public static List<String> addName(List<String> list) {
              list.add("古力娜扎");
              list.add("杨幂");
              list.add("高圆圆");
              list.add("金泫雅");
              return list;
          }
      
      }
      
      // 运行结果
      古力娜扎
      杨幂
      高圆圆
      金泫雅
      
posted on 2019-10-26 18:19  gmlgxx  阅读(42)  评论(0)    收藏  举报