Java|内部类

  • 内部类 :在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

一、成员内部类

  • 成员内部类时最普通的内部类,定义在另一个类的内部
  • 示例代码1:
//成员内部类的定义
public class Outer{
      private String name = "全辣柯基";

      public class Inner{
          
          private static final String Welcome = "HelloWorld";
          private String say = "芜湖";

          public void sayHello(){
                System.out.println(say);
          }     
      } 
}
//成员内部类的调用
public class Test{

        public void main(String[] args){
      
                //创建外部类对象
                Outer outer = new Outer();
                //创建内部类对象
                Inner inner = outer.new.Inner();
                inner.say();
}
}
  • 示例代码2:同名属性和方法的调用
//成员内部类的定义
public class Outer{
      private String name = "全辣柯基";
      private int age = 10;

      public class Inner{
         private String name = "全辣鲤鱼";
         private int age = 20;

         void say(){
              System.out.println(name);  //会输出 全辣鲤鱼,若同名默认优先内部类。
              System.out.println(age);    //会输出20
    
              System.out.println(Outer.this.name);  //输出全辣柯基
              System.out.println(Outer.this .age);    //输出10

              System.out.println(this.name);  //输出全辣鲤鱼
              System.out.println(this.age);    //输出20    
          }
     } 
}
//调用 ->  展示创建内部类对象的语法
public class Test{

        public void main(String[] args){
              //创建内部类的另一种语法
              Inner inner = new Outer().new Inner();
              inner.say;   
}
}
  • 注意事项:
  • 创建内部类对象的语法有两种
  1. 先创建外部类对象,再创建内部类对象
    Outer outer = new Outer()
    Inner inner = outer.new Outer();

  2. 合并创建
    Inner inner = new Outer().new Inner();

  • 内部类中不能定义静态成员变量和静态方法,但可以定义static finnal,即静态常量

二、静态内部类

  • 静态内部类与成员内部类的定义只在于类名前加了static修饰词

  • 区别在于初始化静态内部类和调用静态内部类的属性和方法

  • 示例代码:

public static class Outer{
        private String name = "全辣柯基";
        private int age = 18;

        public static class Inner{
                private String name  = "全辣鲤鱼";
                private int age = 22;

                public static String welcome = "Hello";  //  静态内部类中可以定义静态变量和静态方法

                public void show{
                    //1.调用外部类的属性
                    //先创建外部类的对象
                    Outer outer = new Outer();

                    //再调用外部类属性
                    System.out.println(outer.name);
                    System.out.println(outer.age);

                    //2.调用静态内部类的属性和方法
                    System.out.println(name);
                    System.out.println(age);

                     //3.调用静态内部类的静态属性 
                     //静态成员通过类名访问
                     System.out.println(Inner.welcome);
              }
        }
}

-> 测试代码

public void main(String[] args){
              //*****由于静态类和外部类时平级的,所以不需要先创建外部类
              //*****直接创建静态内部类对象
               Outer.Inner inner = new Outer.Inner();  //注意,new后面的Outer后无括号,真正new的时Inner,Outer只表示一种包含关系
               inner .show();
}
  • 注意事项:
  • 只有静态内部类可以用static修饰,正常的类不可以用static修饰
  • 静态内部类和外部类是平级的,所以可以直接创建静态内部类的对象,而不要先创建外部类对象。
  • 静态变量可以通过类名.来调用
  • 静态内部类中可以定义静态变量

三、局部内部类

  • 局部内部类定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
  • 示例代码1:局部内部类的定义和访问
public class Outer{
        private String name = "全辣柯基";
        private age = 18;

      public void show(){
          private String address = "重庆";

          //在外部类的方法里定义局部内部类
          //局部内部类的定义不加修饰词
          class Inner{
                private String phone = "57575757";
                private String email = "haoshuai@qq.com";

                public void show2(){
                    //访问外部类的属性
                    System.out.println(Outer.this.name);
                    System.out.println(Outer.this.age);

                    //访问内部类的属性
                    System.out.println(this.phone);
                    System.out.println(this.email);    
              }
        }         
    }
}
  • 示例代码2:当定义局部内部类的方法是静态方法时
public class Outer{
        private String name = "全辣柯基";
        private age = 18;

      public static void show(){
          private String address = "重庆";

          //在外部类的方法里定义局部内部类
          //局部内部类的定义不加修饰词
          class Inner{
                private String phone = "57575757";
                private String email = "haoshuai@qq.com";

                public void show2(){
                    //当show()方法为普通方法时,局部内部类的方法可以直接调用外部类的不重名属性。
                    //System.out.print(name);

                    //***当show()方法为静态方法时,不可以直接调用,因为静态方法不能直接访问非静态的属性,可以采取以下调用。
                    System.out.println(Outer.this.name);
                    System.out.println(Outer.this.age);
              }
        }         
    }
}
  • 小结:
  1. 当存放局部内部类的方法是静态方法时,局部内部类的方法不能直接访问外部类的属性
  2. 为了清晰和不易出错建议所有的调用都加上如Outer.this,this等前缀。
  • 示例代码3:如何 调用局部内部类的方法
//先定义一个局部内部类
public class Outer{
      private age =18;

      public void show(){
          private String address = "重庆";//****如何访问address属性?

          class Inner{
                private String phone = "57575757";
                private String email = "haoshuai@qq.com";

                public void show2(){
                 
                public void show2(){
                    System.out.println(Outer.this.name);
                    System.out.println(Outer.this.age);
              }
        }         
    }

倘若想在主函数里创建Outer对象,通过调用 存放局部内部类的方法show 来达到调用show2的目的,是不行的

public void main(String[] args){
        Outer outer = new Outer();
        outer.show;
}

不会有任何输出,因为在执行Outer.show方法时里面 只初始化了一个变量phone,接着就是定义了一个局部内部类,但这个类没有得到使用。

所以如果想要使用show2方法的话,需要在方法里创建局部内部类对象,如

public class Outer{
      private age =18;

      public void show(){
          private String address = "重庆";//定义局部变量

          class Inner{
                private String phone = "57575757";
                private String email = "haoshuai@qq.com";

                public void show2(){
                    System.out.println(Outer.this.name);
                    System.out.println(Outer.this.age);
              }
        }         
                //******创建局部内部类对象
                Inner inner = new Inner();
                inner.show2();
    }
}

-> 这个时候再在主函数里调用就可以打印出show2方法了。

public void main(String[] args){
        Outer outer = new Outer();
        outer.show;
}
  • 示例代码4:如何访问局部变量?即 存放局部内部类的方法 里定义的变量
public class Outer{
      private age =18;

      public void show(){
          finnal private String address = "重庆";//定义局部变量

          class Inner{
            
                public void show2(){
                      //访问局部变量
                      //注意:jdk1.7及以上要求 访问的变量必须是常量finnal,jdk1.8以后,自动将变量添加为finnal,不再用手动定义
                      System.out.println(address);  
              }
        }                       
    }
}  
  • 注:为什么访问的局部变量必须是常量?
  1. 常量的特点是不可修改
  2. 方法中的变量在执行完后会消失
  3. 但new出来的inner对象和类不会消失
  4. 所以类和对象不可能调用一个已经消失的量,所以需要把局部变量定义为常量。
  5. 局部内部类中同样不能定义静态成员变量

四、匿名内部类

  • 没有类名的局部内部类(一切特性与局部内部类相同)

  • 必须继承一个父类或一个接口

  • 匿名内部类实际上是把定义类,实现类,创建对象的语法合并,并且只能创建一个该类的对象

  • 匿名内部类的优点是减少代码量,并且可以在定义一个类的同时对其进行实例化

  • 匿名内部类的缺点是可读性较差

  • 示例代码

//1.定义一个USB接口
public interface USB{
        void service();
}
//2.定义一个Mouse类来实现接口
public class Mouse{
        @Override
        public void service() {
            System.out.println("已连接电脑,鼠标开始工作...");
    }
}
//3.测试1
public class USBTest {

    public static void main(String[] args) {
        //创建接口类型的变量
        //多态
        USB usb = new Mouse();
        usb.service();//能够打印鼠标开始工作

        class FengShan implements USB{
            @Override
            public void service() {
                System.out.println("连接电脑成功,风扇开始工作...");
            }
        }

        //使用局部内部类创建对象
        USB usb1 = new FengShan();
        usb1.service();  //同样能打印得出
    }
}

我们发现,这个风扇的局部内部类只使用一次后续就不再使用了;于是用匿名内部类对这种写法进行优化

//测试2
public class USBTest {

    public static void main(String[] args) {
        //使用匿名内部类进行优化(相当于创建了一个局部内部类)
        USB usb = new USB(){
            @Override
            public void service() {
                System.out.println("连接电脑成功,风扇开始工作了...");
            }
        };
        usb.service();
}

这样使用一次后匿名内部类就不再使用。

  • new后面可以是抽象类,父类,接口等。
posted @ 2021-09-15 18:54  全辣柯基  阅读(57)  评论(0编辑  收藏  举报