内部类的分类

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

  • 局部内部类(有类名)
  • 匿名内部类(没有类名)

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

  • 成员内部类(没用static修饰)
  • 静态内部类(使用static修饰)

局部内部类

  1. 可以直接访问外部类的所有的成员,包括私有的
  2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final,加了final就不能被其他的内部类所继承
  3. 作用域:仅仅在定义它的方法或代码块中
  4. 局部内部类访问外部内部类的成员 可以直接访问
  5. 外部类访问局部内部类的成员需要先创建对象再访问
  • 局部内部类定义在方法中/代码块
  • 作用域在方法体或代码块中
  • 本质仍然是一个类
  • 外部其他类不能访问局部内部类(因为局部内部类地位是一个局部变量)
  • 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
class Outer { //外部类
    class inner{//内部类
        
    }
}
class Other{ //外部其他类
    
}
public class LocalInnerClass {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method_1();
    }
}
class  Outer {
    private  int number =100;
    private  void  method() {
        System.out.println("实现了方法method");
    }
    public  void  method_1(){ //局部内部类访问外部成员
        final  class Inner{
            private  int number=200;  //修改外部类的属性
            public  void  method_2(){
                //外部类和局部内部类的成员重名时,遵循就近原则
                System.out.println("局部内部类访问外部私有属性"+number);
                //访问外部类的成员时,采用 外部类名.this.成员
                //这里的this更说明了一点,实例化了外部了的对象调用了外部类的成员
                System.out.println(Outer.this.number);
                method();
            }
        }
        Inner inner = new Inner();
        inner.method_2();
    }
    }

匿名内部类

  1. 本质是类
  2. 内部类
  3. 该类没有名字
  4. 是一个对象
  • 匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
  • 匿名内部类可以基于接口,基于普通类,但是不能基于抽象类
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();
    }
}
class  Outer{
    private  int number =100;
    public void  method(){
        //这里类似实现了接口+向上转型
        Ia tiger = new Ia(){
            @Override
            public void cry() {
                System.out.println("老虎在叫唤。。。");
            }
        };
        System.out.println("老虎的运行类型是"+tiger.getClass());
        //动态绑定
        tiger.cry();
        /*
        * 也可以用匿名内部类直接调用。
        *匿名内部类本身就是对象,此处调用cry方法也是动态绑定
        new Ia(){
            @Override
            public void cry() {
                System.out.println("老虎在叫唤。。。");
            }
        }.cry();
        **/
    }
    interface  Ia{
        public  void  cry();
    }
}

运行结果

底层会创建匿名内部类

class Ia$1 implements Ia{
            @Override
            public void cry() {
                System.out.println("匿名内部类重写了cry方法。。。");
            }
        }

匿名内部类作实参

public class AnonymousInnerClass {
    public static void main(String[] args) {
        //内部类作实参
        method(new Ia(){
            @Override
            public void cry() {
                System.out.println("haha");
            }
        });
}
    private static void method(Ia ia) {
        //动态绑定,回到匿名内部类,
        ia.cry();
    }
    
    interface  Ia{
        public  void  cry();
    }

}

成员内部类

  1. 成员内部类是定义在外部类的成员位置,并且没有static修饰
  2. 可以直接访问外部类的所有成员,包含私有的
  3. 可以添加任意访问修饰符(public,protected,默认,private),因为它就是一个成员
  4. 作用域和外部类的其他成员一样,为整个类体
  5. 成员内部类访问外类成员直接访问
  6. 外部类访问成员内部类的访问方式是创建对象再访问
  7. 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外类类名.this.成员)去访问
public class MemberInner {
    public static void main(String[] args) {
        Outer outer = new Outer(); 
        
        //通过getInter方法获得到的成员内部类的对象传给 Inter类
        // Outer.Inter inter= outer.getInter();
        
        //这里把new Inter()当做outer对象的成员
        Outer.Inter inter = outer.new Inter();
        inter.say();
    }
}
class  Outer{
    private int number =10;
    private void  hello(){
        System.out.println("输出了父类hello方法");
    }
    public class  Inter{
        private  int number=100;
        public  void  say(){
            //当成员内部类和外部类的成员重名时,采用就近原则
            System.out.println("number="+number);
            //成员内部类访问外部类可以直接访问
            hello();
        }
    }
    //在外部类中编写一个方法,返回一个成员类的对象
    public Inter  getInter(){
        return  new Inter();
    }
}

静态内部类

  1. 静态内部列是定义在外部类的成员位置,并且有static修饰
  2. 可以直接访问外部类的所有的静态成员,包含私有的,但不能直接访问非静态成员
  3. 可以添加任意访问修饰符(public,protected,默认,private),因为它的低位就是一个成员
  4. 作用域同其他的成员一样,是整个类体
  5. 外部类访问静态属性需要创建对象
  6. 如果外部类和静态内部类的成原重名时,默认遵循就近原则,若访问外部类的成员,则可以使用(外部类名.成员)
public class MemberInner {
    public static void main(String[] args) {
    
        //这里把new Inter()当做outer对象的成员
      //  Outer.Inter inter = new Outer.Inter();
        
        //通过getInter方法获得到的成员内部类的对象传给 Inter类
        Outer.Inter inter = Outer.getInter();
        
        inter.say();
    }
}
    class Outer{
    private int number =10;
    private static void  hello(){
        System.out.println("输出了父类hello方法");
    }
    public static class  Inter{
        private  int number=100;
        public  void  say(){
            //当成员内部类和外部类的成员重名时,采用就近原则
            System.out.println("number="+number);
            //成员内部类访问外部类的成员可以直接访问(得是静态的)
            hello();
        }
    }
    //在外部类中编写一个方法,返回一个成员类的对象
    public static Inter  getInter(){
        return  new Inter();
    }
}

总结:静态内部类和成员内部类最本质的区别就是它是静态的,可以直接类名调用

最后修改:2022 年 04 月 06 日 02 : 45 PM