【一天一个基础系列】- java之内部类篇 | 七日打卡

183 阅读4分钟

简介

  • 内部类:在某些情况下,会把一个类放在另外一个类的内部定义,这个定义在其他类内部的的类就为内部类(也可称为嵌套类),包含内部类的类称为外部类
    • 定义格式:
    	public class Father { //外部类
       public class Son { //内部类
    
       }
    }
    
    • 作用:

      • 1)内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中其他类访问该类
      • 2)内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节
      • 3)匿名内部类适用于创建那些仅需要一次使用的类。
    • 内部类外部类的区别

      • 语法上
        • 内部类比外部类可以多使用三个修饰符:private、protected、static ,外部类不可以
        • 非静态内部类不能拥有静态成员
    • 非静态内部类:没static修饰的成员内部类是非静态内部类

      • 定义格式:
         public class Father { //外部类
         public class NonStaticInnerClass { //非静态内部类
         	//TODO
         }
      }
      
    • 静态内部类:static修饰的成员内部类是静态内部类

      • 定义格式:
         public class Father { //外部类
         public static class StaticInnerClass { //静态内部类
         	//TODO
         }
      }
      
    • 局部内部类:定义在方法内部的内部类,该类仅在该方法里有效

      • 定义格式
        private void method(){
        	class innerBaseClass{ //定义局部内部类
        		//TODO
        	} 
        }
        
        

    注:实际使用中很少定义局部内部类,因为其作用域很小

    • 匿名内部类
      • java 8改进,适合创建只需要一次使用的类
      • 定义格式
        new 实现接口() | 父类构造器(实参列表){
        	//TODO
        }
        
      • 规则
        • 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象
        • 匿名内部类不能定义构造器,由于匿名内部类没有类名,所以无法定义构造器
    • 非静态内部类对象和外部类对象的关系
      • 非静态内部类对象必须寄生在外部类对象里,而外部类对象则不必一定有非静态内部类对象寄生其中。简单地说,如果存在一个非静态内部类对象,则一定存在一个被它寄生的外部类对象。但外部类对象存在时,外部类对象里不一定寄生了非静态内部类对象。因此外部类对象访问非静态内部类成员时,可能非静态普通内部类对象根本不存在!而非静态内部类对象访问外部类成员时,外部类对象一定存在
    • Lambda表达式与匿名内部类的联系和区别
      • 联系:Lambda表达式是匿名内部类的一种简化,因此它可以部分取代匿名内部类的作用
        • Lambda表达式与匿名内部类一样,都可以直接访问“effectively final”的局部变量,以及外部类的成员变量(包括实例变量和类变量)
        • Lambda表达式表达式创建的对象与匿名类生成的对象一样,都可以直接调用从接口中继承的默认方法
      • 区别:
        • 匿名内部类可以为任意接口创建实例—不管接口包含多少个抽象方法,只要匿名内部类实现所有的抽象方法即可;但Lambda表达式只能为函数式接口创建实例

        • 匿名内部类可以为抽象类甚至普通类创建实例;但Lambda表达式只能为函数式接口创建实例

        • 匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法;但Lambda表达式的代码块不允许调用接口中定义的默认方法

  • 总结:不管内部类还是外部类,其原则都与使用场景有关,所以不要太过于纠结该怎么定义对应的类,结果为导向即可。