四种内部类

基本介绍

一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class)嵌套其他类的类称为外部类(outer class)。是我们类的第五大成员【思考∶类的五大成员是哪些?内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系

 

image-20220402213722545

基本语法

public class InnerClass01 {//外部其他类
   public static void main(String[] args) {

  }
}

class Outer{//外部类
   private int n1 = 100;//属性

   public Outer(int n1) {//构造器
       this.n1 = n1;
  }

   public void m1(){//方法
       System.out.println("m1()");
  }
  {               //代码块
       System.out.println("代码块....");
  }

   class Inner{//内部类,在Outer类的内部

  }
}

 

内部类的分类

  • 定义在外部类局部位置上(比如方法内):

    1. 局部内部类(有类名)

    2. 匿名内部类(没有类名,重点!!!!!

  • 定义在外部类的成员位置上:

    1. 成员内部类(没有static修饰)

    2. 静态内部类(使用static修饰)

 

局部内部类

两种内部类都遵守

说明∶ 局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。

  1. 可以直接访问外部类的所有成员,包含私有的

  2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用

    修饰符的。但是可以使用final 修饰,因为局部变量也可以使用final

  3. 作用域∶仅仅在定义它的方法或代码块中。

  4. 局部内部类---访问-->外部类的成员 [访问方式∶ 直接访问]

  5. 外部类---访问-->局部内部类的成员

    访问方式∶创建对象,再访问(注意∶必须在作用域内)

  6. 外部其他类--不能访问--->局部内部类(因为 局部内部类地位是一个局部变量)

  7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问【演示】

    System.out,println("外部类的n2="+外部类名.this.n2);

    需要解释一下原因∶!!!!Outer02.this 本质就是外部类的对象, 即哪个对象调用了 m1, Outer02.this 就是哪个对象

    public class LocalInnerClass {
       public static void main(String[] args) {
           //演示一遍
           Outer02 outer02 = new Outer02();
           outer02.m1();
           System.out.println("outer02 的 hashcode=" + outer02);
      }
    }
    class Outer02 {
       //外部类
       private int n1 = 100;
       private void m2(){
           System.out.println("Outer02 m2()");
      }//私有方法
       
       public void m1() {//方法
           //1.局部内部类是定义在外部类的局部位置,通常在方法
           //3.不能添加访问修饰符,但是可以使用 final 修饰
           //4.作用域 : 仅仅在定义它的方法或代码块中
           final class Inner02 {
               //局部内部类(本质仍然是一个类)
               //2.可以直接访问外部类的所有成员,包含私有的
    private int n1 = 800;
               public void f1() {
                   //5. 局部内部类可以直接访问外部类的成员,比如下面 外部类 n1 和 m2()
                   //7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,
                   // 使用 外部类名.this.成员)去访问
                   // Outer02.this 本质就是外部类的对象, 即哪个对象调用了 m1, Outer02.this 就是哪个对象
                   System.out.println("n1=" + n1 + " 外部类的 n1=" + Outer02.this.n1);
                   System.out.println("Outer02.this hashcode=" + Outer02.this); m2();
              }
          }
           //6. 外部类在方法中,可以创建 Inner02 对象,然后调用方法即可
           Inner02 inner02 = new Inner02(); inner02.f1();
      }
    }

     

 

 

记住:

  1. 局部内部类定义在方法/代码块中

  2. 作用域在方法体或者代码块中

  3. 本质仍然是一个类

 

 

 

匿名内部类!!!很重要

  1. 本质还是类

  2. 内部类

  3. 该类没有名字(看不到名字)

说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

  1. 匿名内部类的基本语法

    new 类或接口(参数列表){
    类体
    }

需求

想用IA接口,并创建对象,并且只使用一次

传统方法:

  • 是写一个类,实现该接口,并且创建对象

  • 如下

  •  

  • public class AnonymousInnerClass {
       public static void main(String[] args) {
           Outer04 outer04 = new Outer04();//调用
           outer04.method();
      }
    }
    class Outer04{
       private int n1 = 10;
       public void method(){
           IA tiger = new Tiger();//多态调用Tiger
           tiger.cry();
      }
    }

    interface IA{
       void cry();
    }

    class Tiger implements IA{//Tiger实现IA接口
       @Override
       public void cry() {
           System.out.println("老虎叫唤...");
      }
    }
  • !!!!!可以使用匿名内部类

  • 简化开发

  • 基于接口!!!

  • /**
    * @author: XHP
    * @date: 2022/4/2
    * @version: 1.0
    **/
    public class AnonymousInnerClass {
       public static void main(String[] args) {
           Outer04 outer04 = new Outer04();
           outer04.method();
      }
    }
    class Outer04{
       private int n1 = 10;
       public void method(){
    //       IA tiger = new Tiger();
    //       tiger.cry();

           //tiger的编译类型? IA
           //tiger的运行类型? 就是匿名内部类 (外部类名$1)Outer04$1
           /*
           底层 会分配 类名Outer04$1
           class tiger implements IA{
               @Override
               public void cry() {
                   System.out.println("老虎叫唤...");
               }
           }
           底层会创建内部类Outer04$1,并且把地址赋值tiger
           匿名内部类智能使用一次,之后就不能使用了
           */
           IA tiger = new IA() {
               @Override
               public void cry() {
                   System.out.println("老虎叫唤...");
              }
          };
           tiger.cry();
      }
    }

    interface IA{
       void cry();
    }
  • 基于类!!!

  •  

  • /**
    * @author: XHP
    * @date: 2022/4/2
    * @version: 1.0
    **/
    public class AnonymousInnerClass {
       public static void main(String[] args) {
           Outer04 outer04 = new Outer04();
           outer04.method();
      }
    }
    class Outer04{
       private int n1 = 10;
       public void method(){
           /*
           编译类型Father
           运行类型Outer04$1
           底层会创建匿名内部类
           与接口相似
           class Outer04$1 extends Father{

               public Outer04$1(String name) {
                       super(name);
               }

               @Override
               public void test() {
                   System.out.println("给爷叫...");
               }
           }
            */
           Father father = new Father("xhp"){
               @Override
               public void test() {
                   System.out.println("给爷叫...");
              }
          };
           System.out.println(father.getClass());
           father.test();
      }
    }

    class Father{
       public Father(String name){
           super();
      }
       public void test(){
           System.out.println("啥玩意");
      }
    }

匿名内部类的使用

匿名内部类的语法比较奇特,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,堆面前代码分析可以看出这个特点,因此可以调用匿名内部类方法。

  • 有两种方式

    • 方式一

      • image-20220403130955709

    • 方式二

      • image-20220403131032511

 

 

/**
* @author: XHP
* @date: 2022/4/3
* @version: 1.0
**/
public class AnonymousInnerClassDetail {
   public static void main(String[] args) {
       Outer05 outer05 = new Outer05();
       outer05.f1();
  }
}
class Outer05{
   private int n1 = 99;
   public void f1(){
       //方式一
       Person p = new Person(){
           @Override
           public void hi() {
               System.out.println("匿名内部类方式一hi()");
          }
      };
       p.hi();//动态绑定,运行类型是Outer05$1
       //方式二
       new Person(){
           @Override
           public void hi() {
               System.out.println("匿名内部类方式二hi()");
          }
      }.hi();
  }
}

class Person{
   public void hi(){
       System.out.println("Person hi()");
  }
}

最佳实战(作为参数传入)

/**
* @author: XHP
* @date: 2022/4/3
* @version: 1.0
**/
public class InnerClassExercise {
   public static void main(String[] args) {
       //作为参数传递
       sayLoudly(new TL() {
           @Override
           public void say() {
               System.out.println("给爷狗叫...");
          }
      });
  }
   public static void sayLoudly(TL tl){
       tl.say();
  }
}


interface TL{
   void say();
}

成员内部类

!!!!!!遵守成员变量的使用,也遵守类的使用

说明:成员内部类是定义在外部类的成员位置上,并且没有static修饰

  1. 可以直接访问外部类的所有成员,包含私有

  2. 可以添加修饰符,因为他也是成员

  3. 作用域:和外部类一样,为整个类体

  4. 成员内部类---访问---->外部类(比如∶属性)【访问方式∶直接访问】(说明)

  5. 外部类---访问---->内部类(说明)访问方式∶ 创建对象,再访问。

  6. 外部其他类---访问---->成员内部类

    //外部其他类---访问---->成员内部类
           Outer08 outer08 = new Outer08();
           Outer08.Inner08 inner08 = outer08.new Inner08();

     

  1. 演示

    /**
    * @author: XHP
    * @date: 2022/4/3
    * @version: 1.0
    **/
    public class MemberInnerClass {
       public static void main(String[] args) {
           //外部其他类---访问---->成员内部类
           Outer08 outer08 = new Outer08();
           Outer08.Inner08 inner08 = outer08.new Inner08();
           inner08.say();
      }
    }

    class Outer08{
       private int n1 = 10;
       public String name = "张三";
       private void hi(){
           System.out.println("hi()的方法...");
           //外部类---访问---->内部类(说明)访问方式∶ 创建对象,再访问。
           Inner08 inner08 = new Inner08();
           System.out.println(inner08.sal);
      }

       //2.可以添加修饰符
       public class Inner08{
           private double sal = 99.8;
           public void say(){
               //可以直接访问外部类的所有成员,包含私有,直接访问
               System.out.println("n1 = " + n1 + " name = " +name + " n1 = "+ Outer08.this.n1);
          }
      }

    }

     

静态内部类

!!!!!遵守静态变量的使用规则,同时也类

使用:

  1. 可以直接访问外部类的所有静态成员,包含私有,但不能直接访问非静态成员

  2. 可以添加任意访问修饰符,他的地位是一个成员

  3. 作用域:同其他的成员,为一个整体

  4. 静态内部类---访问---->外部类(比如∶静态属性)【访问方式∶直接访问所有静态成员】

  5. 外部类--访问--->静态内部类 访问方式∶创建对象,再访问

  6. 外部其他类---访问---静态内部类

  7. 重名遵守就近原则

 

  1. 演示

    /**
    * @author: XHP
    * @date: 2022/4/3
    * @version: 1.0
    **/
    public class StaticInnerClass {
       public static void main(String[] args) {
           Outer10 outer10 = new Outer10();
           outer10.m1();
           //外部其他类---访问---静态内部类
           Outer10.Inner10 inner10 = new Outer10.Inner10();
           inner10.say();
      }
    }

    class Outer10{
       private int n1 = 10;
       private static String name = "张三";
       private static void cry(){}



       public static class Inner10{
           private String name = "李四";
           public void say(){
               //可以直接访问外部类的所有静态成员,包含私有,但不能直接访问非静态成员,直接访问
               //重名遵守就近原则
               System.out.println(name + Outer10.name);
               cry();
          }

      }

       public void m1(){
           //外部类--访问--->静态内部类 访问方式∶创建对象,再访问
           Inner10 inner10 = new Inner10();
           inner10.say();
      }
    }
  2.  

 

 

posted @ 2022-04-03 16:24  子非鱼!  阅读(90)  评论(0编辑  收藏  举报