zoukankan      html  css  js  c++  java
  • Java 匿名内部类 & 内部类

     

    一、JAVA中内部类和匿名内部类的区别

            内部类:内部类可以是static的或者非static的,static内部类只能包含静态方法和静态类变量,只能访问外部类的静态元素,内部类可以实例化,多次使用。

            匿名内部类:它只能使用一次,不区分static和非static。如果用到外部类的变量的话,必须是类变量或者实例变量,就是必须是类定义的变量,或者final的局部变量。匿名内部类如果是继承某个类的话是可以重写那个类的方法的,这个和普通内部类一样。

            总结:可以用匿名内部类的地方都可以用内部类替换,但是用匿名内部类编码非常简洁,也容易读懂,除非你需要多次使用那个内部类,不然建议还是使用匿名内部类。

    二、内部类的使用时机

          1、实现事件监听器的时候(比方说actionListener 。。。采用内部类很容易实现);

          2、编写事件驱动时(内部类的对象可以访问外部类的成员方法和变量,注意包括私有成员);

          3、在能实现功能的情况下,为了节省编译后产生的字节码(内部类可以减少字节码文件,即java文件编译后的.class文件);

    三、匿名内部类的使用时机

           匿名内部类是内部类的一种特殊情况。它只有一个实例,而且没有引用。所以,一般在能用内部类实现,但是实例只用一次的情况下使用它(可以减少资源开销);

    ===========================================================================

     

    匿名内部类也就是没有名字的内部类

    正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

    但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

    1.匿名内部类的基本实现

    abstract class Person {
        public abstract void eat();
    }
     
    public class Demo {
        public static void main(String[] args) {
            Person p = new Person() {
                public void eat() {
                    System.out.println("eat something");
                }
            };
            p.eat();
        }
    }

    运行结果:eat something

    可以看到,我们直接将抽象类Person中的方法在大括号中实现了

    这样便可以省略一个类的书写

    并且,匿名内部类还能用于接口上

     

    2.在接口上使用匿名内部类

    interface Person {
        public void eat();
    }
     
    public class Demo {
        public static void main(String[] args) {
            Person p = new Person() {
                public void eat() {
                    System.out.println("eat something");
                }
            };
            p.eat();
        }
    }

    运行结果:eat something

    由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现

    最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

     

    3.Thread类的匿名内部类实现

    public class Demo {
        public static void main(String[] args) {
            Thread t = new Thread() {
                public void run() {
                    for (int i = 1; i <= 5; i++) {
                        System.out.print(i + " ");
                    }
                }
            };
            t.start();
        }
    }

    运行结果:1 2 3 4 5

     

     

    4.Runnable接口的匿名内部类实现

    public class Demo {
        public static void main(String[] args) {
            Runnable r = new Runnable() {
                public void run() {
                    for (int i = 1; i <= 5; i++) {
                        System.out.print(i + " ");
                    }
                }
            };
            Thread t = new Thread(r);
            t.start();
        }
    }

    运行结果:1 2 3 4 5

     

     

     

     

     

    以下是内部类

    实例1:内部类的基本结构

     

    //外部类
    class Out {
        private int age = 12;
         
        //内部类
        class In {
            public void print() {
                System.out.println(age);
            }
        }
    }
     
    public class Demo {
        public static void main(String[] args) {
            Out.In in = new Out().new In();
            in.print();
            //或者采用下种方式访问
            /*
            Out out = new Out();
            Out.In in = out.new In();
            in.print();
            */
        }
    }

     运行结果:12

    从上面的例子不难看出,内部类其实严重破坏了良好的代码结构,但为什么还要使用内部类呢?

    因为内部类可以随意使用外部类的成员变量(包括私有)而不用生成外部类的对象,这也是内部类的唯一优点

    如同心脏可以直接访问身体的血液,而不是通过医生来抽血

    实例2:静态内部类

    class Out {
        private static int age = 12;
         
        static class In {
            public void print() {
                System.out.println(age);
            }
        }
    }
     
    public class Demo {
        public static void main(String[] args) {
            Out.In in = new Out.In();
            in.print();
        }
    }

    运行结果:12

    可以看到,如果用static 将内部内静态化,那么内部类就只能访问外部类的静态成员变量,具有局限性

    其次,因为内部类被静态化,因此Out.In可以当做一个整体看,可以直接new 出内部类的对象(通过类名访问static,生不生成外部类对象都没关系)

    实例3:方法内部类

    class Out {
        private int age = 12;
     
        public void Print(final int x) {
            class In {
                public void inPrint() {
                    System.out.println(x);
                    System.out.println(age);
                }
            }
            new In().inPrint();
        }
    }
     
    public class Demo {
        public static void main(String[] args) {
            Out out = new Out();
            out.Print(3);
        }
    }

    运行结果:

    3
    12

    在上面的代码中,我们将内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法

    如果此时我们需要往外部类的方法中传入参数,那么外部类的方法形参必须使用final定义

    至于final在这里并没有特殊含义,只是一种表示形式而已

     

     

  • 相关阅读:
    How to use my view helpers in my ActionMailer views?
    大败笔,状态机
    把程序进行上线部署调试了,
    支付接口心得
    rails3 正则路由
    linux下配置Mysql远程访问,不受ip限制
    ActionController::InvalidAuthenticityToken解决办法
    支付宝接口错误
    DHTML 中的绝对定位
    部署备份
  • 原文地址:https://www.cnblogs.com/novalist/p/6605384.html
Copyright © 2011-2022 走看看