Java--内部类

一、内部类的分类

  成员内部类  静态内部类 局部内部类  匿名内部类

  • 概念:在一个类的内部再定义一个完整的类。
  • 特点:
    • 编译之后可生成独立的字节码文件。
    • 内部类可直接访问外部类的私有成员,而不破坏封装
    • 可为外部类提供必要的内部组件
package com.monv.neibulei;

public class Body {
    private String name;
    
    class Head{
         public void show(){
             System.out.println(name); //可以直接访问外部类的私有成员
         }
    }
}    

二、成员内部类

  • 在类的内部定义,与实例变量、实例方法同级别的类。
  • 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象。
  • 当外部类、内部类存在重名属性时,会优先访问内部类属性。(访问外部类属性时需要加 外部类名.this.属性)
  • 成员内部类不能定义静态成员。但是可以定义静态常量。
package com.monv.neibulei;
//外部类
public class Outer {
    //实例变量
    private String name = "小明";
    private int age = 20;
    //内部类
    class Inner{
        //不能包含静态成员 但是可以包含静态常量
//        private static String S1="aaa";//这句是不可以的
//        private final static String S1="aaa";//这句是可以的(静态常量)
        
        private String name = "小红";
        private String address = "北京";
        private String phone = "15930221236";
        //方法
        public void show(){
            //打印外部类属性 内部类属性和外部类属性重名的时候 访问外部类属性需要加Outer.this.
            System.out.println(Outer.this.name);
            System.out.println(Outer.this.age);
            //打印内部类属性
            System.out.println(this.address);
            System.out.println(this.phone);
        }
    }
}
---------------------测试-------------------------------
package com.monv.neibulei;

import com.monv.neibulei.Outer.Inner;

public class TestOuter {
    public static void main(String[] args) {
//        //1、创建外部类对象
//        Outer outer = new Outer();
//        //2、创建内部类对象
//        Inner inner = outer.new Inner();
        
        //一步到位的写法
        Inner inner = new Outer().new Inner();
        inner.show();
    }
}

三、静态内部类(相当于外部类,普通的外部类包含什么,静态内部类就包含什么)

  • 不依赖外部类对象,可以直接创建或通过类名访问,可声明静态成员。
  • 只能直接访问外部类的静态成员(实例成员,需要实例化外部类对象)
package com.monv.neibulei_2;
//外部类 注意:普通的类不能用static修饰,只有内部类才可以用static修饰
public class Outer {
    private String name = "小明";
    private int age = 20;
    
    //静态内部类(在成员内部类的基础上增加 static关键字修饰) 级别和外部类相同
    static class Inner{
        private String address="河北";
        private String phone = "123";
        //静态成员
        private static int count = 1000;
        //方法
        public void show(){
            //调用外部类属性 
            //1.先创建外部类对象
            Outer outer = new Outer();
            //2.调用外部类对象属性
            System.out.println(outer.name);
            System.out.println(outer.age);
            //调用静态内部类的属性和方法
            System.out.println(address);
            System.err.println(phone);
            //调用静态内部类的静态属性(静态属性访问:类名.静态属性)
            System.out.println(Inner.count);
            
        }
    }
}
----------------------------测试---------------------------------
package com.monv.neibulei_2;

public class TestOuter {
    public static void main(String[] args) {
        //直接创建静态内部类对象 注意 这里new的时候Outer后没有()
        Outer.Inner inner = new Outer.Inner();
        //调用方法
        inner.show();
    }
}
----------------------------------------------------------------

四、局部内部类

  • 定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
  • 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须用final修饰
  • 限制类的使用范围(只能在当前的方法中使用)
package com.monv.neibulei_3;

import java.util.concurrent.CountDownLatch;

//外部类
public class Outer {
    
    private String name = "小明";
    private int age = 20;
    
    public void show(){
        //定义局部变量  用final修饰表示常量 说明值不可以被修改
        final String address ="河北";
        
        //局部内部类 注意:不能带任何访问修饰符
        class Inner{
            //局部内部类的属性
            private String phone = "1236523";
            //不能包括静态变量 可以包括静态常量
//            private static int count = 2000;//这个是不可以的
//            private final static int count = 2000; //这个是可以的(静态常量)
            //局部内部类的方法
            public void show2(){
                //访问外部类的属性(直接访问)
                System.out.println(Outer.this.name);
                System.out.println(Outer.this.age);
                //访问内部类的属性
                System.out.println(this.phone);
                //访问局部变量:jdk1.7 要求变量是常量 final;jdk1.8自动添加final
                System.out.println(address);
            }
        }
        //创建内部类对象 
        Inner inner = new Inner();
        inner.show2();
    }
}
--------------------------------------------------
package com.monv.neibulei_3;

public class TestOuter {
    public static void main(String[] args) {
        //这里只能创建外部类对象 用外部类对象调用show方法
        //show方法中有局部内部类 如果想要调用局部内部类的show2方法 则需要在show方法中定义 局部内部类对象 然后再调用show2方法
        Outer outer = new Outer();
        outer.show();
    }
}
---------------------------------------------------

 五、匿名内部类

  • 没有类名的局部内部类(一切特征都与局部内部类相同)
  • 必须继承一个父类或者实现一个接口
  • 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象
  • 优点:减少代码量
  • 缺点:可读性较差

  例如:之前写的Usb的接口,需要定义一个实现类 Mouse类来实现这个接口,然后再定义一个Usb的变量,实例化成Mouse对象之后再调用方法。现在可以用匿名类来进行优化。

---------------------接口-----------------------------
package com.monv.neibulei;
//接口
public interface Usb {
  void  service();
}
---------------------鼠标的实现类---------------------
package com.monv.neibulei;

public class Mouse implements Usb {

    @Override
    public void service() {
        System.out.println("鼠标连接成功,开始工作。。");
    }

}
------------------------测试-----------------------------
package com.monv.neibulei;

public class TestUsb {
    public static void main(String[] args) {
        //方法1.创建接口类型的变量
        Usb usb = new Mouse();
        usb.service();
        //方法2.定义局部内部类
//        class Upan implements Usb{
//
//            @Override
//            public void service() {
//                System.out.println("U盘连接成功,开始工作");
//            }
//            
//        }
//        //使用局部内部类创建对象
//        Usb usb2 = new Upan();
//        usb2.service();
        
        //方法3.使用匿名类优化(相当于创建了一个局部内部类)
        Usb usb2 = new Usb() {
            
            @Override
            public void service() {
                System.out.println("U盘连接成功,开始工作。。");
            }
        };
        usb2.service();        
    }
}
-----------------------------------------------------------------------

 

posted @ 2020-09-07 22:29  改Bug的小魔女  阅读(203)  评论(0编辑  收藏  举报