问题:内部类、静态内部类区别、使用场景?
1.静态内部类可以有静态成员(方法,属性),而非静态内部类则不能有静态成员(方法,属性)。
2.静态内部类只能够访问外部类的静态成员,而非静态内部类则可以访问外部类的所有成员(方法,属性)。
3.实例化方式不同:
(1)实例化成员内部类“”
通过外部类对象创建
OutClassTest oc1 = new OutClassTest();
OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();
(2)实例化静态内部类:
OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();

3.访问内部类成员属性不同:
(1)外部类访问内部类属性和方法:
外部类可以通过内部类引用间接访问内部类元素 类似:new IN().inMessage()
(2)外部类访问静态内部类:
调用内部静态类的方法或静态变量,通过类名直接调用
OutClassTest.InnerStaticClass.static_value
OutClassTest.InnerStaticClass.getMessage()
6.为何要用内部类?

内部类可以访问外部类的所有成员,包括私有属性。
方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
每个内部类都能独立地继承一个接口,而无论外部类是否已经继承了某个接口。因此,内部类使多重继承的解决方案变得更加完整。
一、什么是内部类?(一般)
在一个类Out的内部定义一个类in,这个类就是内部类,相应的Out就成为外部类。

二、内部类与外部类的联系
1、内部类是一个编译时概念,编译后外部类及其内部类会生成两个独立的class文件: OuterClass.class和OuterClass$InnerClass.class
2、内部类可以直接访问外部类的元素,但是外部类不可以直接访问内部类的元素

3、外部类可以通过内部类引用间接访问内部类元素

4、对于静态内部类来说,静态内部类是不依赖于外部类的,也就说可以在不创建外部类对象的情况下创建内部类的对象。另外,静态内部类是不持有指向外部类对象的引用的

三、内部类的分类
成员内部类、局部内部类、匿名内部类、静态内部类。

1、成员内部类
成员内部类就是普通的内部类,内部类可以声明public、protected、private等访问限制,可以声明 为abstract的供其他内部类或外部类继承与扩展,或者声明为static、final的,也可以实现特定的接口。
如果成员内部类用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;
如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。

外部类按常规的类访问方式使用内部类,唯一的差别是外部类可以访问内部类的所有方法与属性,包括私有方法与属性。

内部类中的this与其他类一样是指的本身。创建内部类对象时,它会与创造它的外围对象有了某种联系,于是能访问外围类的所有成员,不需任何特殊条件,可理 解为内部类链接到外部类。 用外部类创建内部类对象时,此内部类对象会秘密的捕获一个指向外部类的引用,于是,可以通过这个引用来访问外围类的成员。

2、局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

3、匿名内部类
匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,初次之外,还有一些地方需要注意:
匿名内部类是没有访问修饰符的。
匿名内部类必须继承一个抽象类或者实现一个接口
匿名内部类中不能存在任何静态成员或方法
匿名内部类是没有构造方法的,因为它没有类名。

一般使用匿名内部类的场景是,要继承或实现的接口只有一个抽象方法:

public class Test {
     public static void main(String[] args) {
         //4.匿名内部类
         //主要是针对那些不能直接创建对象的抽象类和接口而来的
         Student stu=new Student();
         System.out.println(stu.getClass());//class com.aowin.noname.Student
         //4.1.通过实体类创建匿名内部类对象
         //相当于创建该类的一个子类对象
         Person p=new Person(){
             public void eat(){
                 System.out.println("吃八元套餐");
             }
         };
         p.eat();
         System.out.println(p.getClass());//class com.aowin.noname.Test$1//系统自动为子类命名Test$1
         
         Dog dog=new Dog();
         dog.bark();
         //4.2.通过抽象类创建匿名内部类对象
         //相当于定义了该抽象类的一个子类对象,并重写了抽象类中所有的抽象方法
         Animal an=new Animal(){
             public void bark(){
                 System.out.println("汪汪汪...");
             }
         };
         an.bark();
         //返回的是包名加类名
         System.out.println(an.getClass());//class com.aowin.noname.Test$2
         
         //4.3.通过接口创建匿名内部类对象
         //相当于定义了该接口的一个实现类对象,并重写了接口中所有的抽象方法
         Sportable s=new Sportable(){
             public void sport(){
                 System.out.println("打篮球");
             }
         };
         s.sport();
         System.out.println(s.getClass());//class com.aowin.noname.Test$3
         
     }
 }
 //实体类
 class Person{
     public void eat(){
         System.out.println("吃饭");
     }
 }
 class Student extends Person{
     public void eat(){
         System.out.println("吃八元套餐");
     }
 }
 //抽象类
 abstract class Animal{
     public abstract void bark();
 }
 class Dog extends Animal{
     public void bark() {
         System.out.println("汪汪...");
     }
 }
 //接口
 interface Sportable{
     public abstract void sport();
 }


4、静态内部类
关键字static可以修饰成员变量、方法、代码块,其实它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类。
静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内。
但是静态内部类却没有。没有这个引用就意味着:
静态内部类的创建是不需要依赖于外围类,可以直接创建
静态内部类不可以使用任何外围类的非static成员变量和方法,而内部类则都可以

private static String outerName;
     public  int age;
  
     static class InnerClass1{
         /* 在静态内部类中可以存在静态成员 */
         public static String _innerName = "static variable";
         public void display(){
             /*
              * 静态内部类只能访问外部类的静态成员变量和方法
              * 不能访问外部类的非静态成员变量和方法
              */
             System.out.println("OutClass name :" + outerName);
         }
     }
     class InnerClass2{
         /* 非静态内部类中不能存在静态成员 */
         public String _innerName = "no static variable";
         /* 非静态内部类中可以调用外部类的任何成员,不管是静态的还是非静态的 */
         public void display(){
             System.out.println("OuterClass name:" + outerName);
             System.out.println("OuterClass age:" + age);
         }
     }
     public void display(){
         /* 外部类能直接访问静态内部类静态元素 */
         System.out.println(InnerClass1._innerName);
         /* 静态内部类可以直接创建实例不需要依赖于外部类 */
         new InnerClass1().display();
         /* 非静态内部的创建需要依赖于外部类 */
         OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
         /* 非静态内部类的成员需要使用非静态内部类的实例访问 */
         System.out.println(inner2._innerName);
         inner2.display();
     }
  
     public static void main(String[] args) {
         OuterClass outer = new OuterClass();
         outer.display();
     }
 }


四、内部类和外部类的相互访问
1、内部类访问外部类成员

当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:

外部类.this.成员变量 
外部类.this.成员方法
但是静态内部类,只能访问外部类的静态成员
2、外部类访问内部类成员
外部类可以通过内部类引用间接访问内部类元素

外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:

外部类访问内部类:

new In().inMessage();  //必须先创建内部类的对象,再访问
  
     class In{     //内部类
         public void inMessage() {
             System.out.println("外部类访问");  //外部类的private成员
         }
     }


3、静态内部类与外部类的访问(相当于嵌套类)

(1)静态内部类访问外部类: 只能访问外部类的静态成员,不能访问非静态成员!
(2)外部类访问静态内部类成员:可以直接访问,内部类名.属性(方法)