ACAC 内部类和匿名内部类


/*
* 内部类:
*   1、内部类的同名方法:
*       内部类可以调用外部类的方法,如果内部类方法和外部类方法名相同
* ·     使用“OutClass.this.MethodName()”格式调用
*       OutClass : 外部类名  MethodName :方法名  this: 关键字
*       若无同名方法,内部类可以直接调用外部方法
*   注意:外部类无法直接调用内部类的private方法,也无法调用其他类的private方法
*   那内部类是否可以直接调用外部类的private方法呢?
*   注意:内部类调用外部类方法,与他的权限以及是否是static无关,只与是否有同名方法有关
*
*
*   2、内部类访问外部类局部变量时,变量必须声明为final(jdk1.8以前)
*       方法中的局部变量,方法结束后释放这个变量,final保证这个变量始终指向一个对象
*       内部类和外部类属于同一级别,内部类不会因为定义在方法中就会随着方法的执行完毕而被销毁
*       问题:如果外部类中方法不定义final,那么当外部类方法执行完毕时,这个局部变量就被GC释放了
*             内部类如果没有执行完,他所引用的外部变量已经找不到了
*       所以用final定义,java会将这个变量复制一份作为成员变量内置于内部类中,由于final修饰的值
*       无法改变,所以这个变量所指向的内存区域就不会变
*   注意:如果使用JDK1.8,方法中内部类的方法是可以直接访问外部类方法的局部变量,不需要声明为final类型
*
*
*   3、内部类的实例化:
*       内部类必须在外部类实例化之后,才能实例化,并与外部类建立关系
*       但是在static方法中,(常见的main方法)
*           不能直接new内部类,为什么?
*           以你为静态方法是在类实例化之前就可以使用的,通过类名调用,这时动态内部类
*           还没有实例化,不能调用一个不存在的东西
*       怎么办?
*           1、将内部类声明为static
*           2、采用X.new A()方法 如同:
*               NeiBuLei.InnerClass in = new NeiBuLei().new InnerClass()
*
*    4、什么时候使用内部类?
*        每个内部类都能独立地继承(实现)接口,无论外部类是否要实现这个接口,对内部类都没有影响
*
*    5、静态方法中实例化内部类例子(就是内部类放在静态方法中)
*
*
* */
public class NeiBuLei {
    private void outerMethod(){
        System.out.println("外部类的私有方法");

        //外部类的非static方法中可有实例化内部类对象
        InnerClass innerClass = new InnerClass();
    }
    public static void main(String[] args) {

        NeiBuLei.InnerClass in = new NeiBuLei().new InnerClass();
        in.innerMethod();

        //拆开写,也行
        NeiBuLei n = new NeiBuLei();
        NeiBuLei.InnerClass a = n.new InnerClass();
        a.innerMethod();

        //静态方法中实例化内部里
        class Boy implements People{
            @Override
            public void speak() {
                System.out.println("内部类实现接口");
            }
            public void say(){
                System.out.println("内部类自定义方法");
            }
        }

        //内部类实现接口
        People people01 = new Boy();
        people01.speak();

        //匿名内部类实现接口,下章讲
        People people = new People() {
            @Override
            public void speak() {
                System.out.println("匿名内部类实现接口");
            }
        };
        people.speak();

    }
    class InnerClass{
        public void innerMethod(){
            NeiBuLei.this.outerMethod();
            //当内部类和外部类方法同名时,用this调用外部类的方法啊,这个就是调用的外部类的方法
            outerMethod();
            //这个就是调用的内部类的方法
        }
        private void outerMethod(){
            System.out.println("内部类的同名私有方法");
        }
    }
    /*
    * 运行结果:
        外部类的私有方法
        内部类的同名私有方法
        外部类的私有方法
        内部类的同名私有方法
    */
}
interface People{
    public void speak();
}
class outerClass01{
    int i = 12;

    private void outerMethod(){
        int a = 1;
        class Innerclass_1{
            public void innerMethod(){
               //访问成员变量
                System.out.println(i);
                //JDK1.8以前,方法中内部类中的方法,不能直接访问外部类的方法里的局部变量,要声明为final
                System.out.println(a);

               /* a++;
                注意:a这个变量虽然不写final,但默认是final的,只能访问,不能修改
                否则报错:
                Variable 'a' is accessed from within inner class,
                needs to be final or effectively final
                翻译: 变量“a”是从内部类中访问的,
                      必须是最终的或有效的最终的
                */
            }
        }
    }
}


/*
* 匿名内部类:
*       没有名字,作用:简化代码编写,只能使用一次
*    前提:必须继承一个父类或者实现一个接口
*         但只能继承一个或实现一个接口
*
* 两条规则:
*      1、匿名内部类不能是抽象类,因为系统创建匿名内部类的时候,会立即创建内部类的对象
*       因此不能定义为抽象类
*      2、匿名内部类不能定义构造器(构造方法),因为匿名内部类没有类名,所以无法定义构造器
*       但可以定义实例初始化块
*
* 使用:
*      可以在抽象类上使用,也可以在接口上使用
* */
abstract class Father{
    
    
    public abstract void sum();
}

class Son extends Father{
    
    
    @Override
    public void sum() {
    
    
        System.out.println("不使用匿名内部类,实现接口");
    }
}

public class NiMingNeiBuLei {
    
    

    public static void main(String[] args) {
    
    

        Father father = new Father() {
    
    
            @Override
            public void sum() {
    
    
                System.out.println("匿名内部类实现接口");
            }
        };//注意这个分号
        //使用匿名内部类,直接调用
        father.sum();

        //不使用匿名内部类,需要定义一个类继承抽象类,并实现方法
        //子类实例化父类,向上转型
        Father ff = new Son();
        ff.sum();

        //在接口上使用
        class Bb implements Person{
    
    

            @Override
            public void s() {
    
    
                System.out.println("实现接口");
            }


        }

        new Person(){
    
    
            @Override
            public void s() {
    
    
                System.out.println("----------");
            }
            //匿名内部类中隐含一个匿名对象,可以调用say方法
            public void say(){
    
    
                System.out.println("匿名对象调用");
            }
        }.say();

        //a.s();
        //a.say();
        //这样写是错的,因为a是person对象,不是匿名内部类的对象
        //匿名内部类没有名字,怎么调用他的方法呢?
        //1、向接口中声明这个方法,再在匿名内部类中覆盖这个方法
        //2、采用 new Person(){}.Method(); 进行调用,注意不能写Person p = new Person(){}

    }
}
interface Person{
    
    
    public void  s();
}

猜你喜欢

转载自blog.csdn.net/qq_44707513/article/details/114376345
今日推荐