zoukankan      html  css  js  c++  java
  • java的内部类及匿名内部类

    在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类

    • 内部类和外层封装它的类之间存在逻辑上的所属关系
    • Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。 Inner class的名字不能与包含它的类名相同;
    • Inner class可以使用包含它的类的静态和实例成员变量,也可以使用它所在方法的局部变量
    • 内部类跟方法和成员变量一样,都是类的一个成员。所以像final,abstract,private,static,protected可以用来修饰内部类(比如外部类不能声明为private)。内部类享有和内部成员同样的待遇

    为什么使用内部类?

          如果这个类没有定义在外部的必要,即使此类仅供外部类的方法来调用,而不会被其他外部类调用。

    package com.atguigu.java;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * 内部类: 
     * 1. 在类的内部定义的类成为内部类
     * 2. 内部类相当于类的一个成员, 可以修饰类的成员的 private, static, final, abstract 都可以修饰内部类
     * 3. 声明、使用内部类的实例. 
     * 3.1 非静态内部类的创建, 先创建外部类的实例, 再通过 外部类名.new 创建内部类的实例.
     * OuterClass oc = new OuterClass();
     * OuterClass.InnerClass in = oc.new InnerClass();
     * 
     * 3.2 静态内部类的创建: 不再需要外部类的实例. 
     * OuterClass.StaticInnerClass sic = new OuterClass.StaticInnerClass();
     * 
     * 4. 内部类引用外部类的成员: 
     * 
     * 5. ** 匿名内部类对象: 使用某一个接口通常是 先创建接口的实现类, 再创建其实现类的对象.
     * 还可以, 直接创建其实现类对象. 
     * 
     * InvocationHandler invocationHandler = new InvocationHandler() {
     *            @Override
     *             public Object invoke(Object proxy, Method method, Object[] args)
     *                    throws Throwable {
     *                return null;
     *            }
     *        };
     * 
     *
     */
    public class OuterClass {
        
        int age;
        
        static class StaticInnerClass{
            void test(){ 
                //System.out.println(age);
            }
        }
        
        static String name = "-1";
        
        //内部类
        class InnerClass{
            String name = "0";
            
            public void test(){
                String name = "1";
                
                System.out.println(name); //1
                System.out.println(this.name); //0
                System.out.println(OuterClass.this.name); //-1
            }
        }
        
    }
    package com.atguigu.java;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class TestInnerClass {
        
        public static void main(String[] args) {
            
            OuterClass.StaticInnerClass sic = new OuterClass.StaticInnerClass();
            
            OuterClass oc = new OuterClass();
            OuterClass.InnerClass in = oc.new InnerClass();
            in.test();
            
            Proxy.newProxyInstance(null, null, new InvocationHandler() {
                
                @Override
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    // TODO Auto-generated method stub
                    return null;
                }
            });
            
            InvocationHandler invocationHandler = new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    return null;
                }
            };
            
        }
        
    }

     匿名内部类 

           使用匿名内部类课使代码更加简洁、紧凑,模块化程度更高。内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到。

            就是匿名内部类的两种实现方式:

            第一种,继承一个类,重写其方法;

            第二种,实现一个接口(可以是多个),实现其方法。下面通过代码来说明:

    不使用内部类

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

    运行结果:eat something

    可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用

    但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

    这个时候就引入了匿名内部类

    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中的方法在大括号中实现了

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

     

    • 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
    • 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口。匿名内部类就是重写父类或接口的方法。
    • 匿名内部类是没有名字的,所以我们没办法获得其类型,而只能把它当作超类或接口类型来使用

     参考:内部类 http://www.cnblogs.com/tech-bird/p/3650069.html

               匿名内部类 http://www.cnblogs.com/tech-bird/p/3651551.html

  • 相关阅读:
    android openGl视频
    《jQuery权威指南》学习笔记之第2章 jQuery选择器
    RobHess的SIFT源码分析:综述
    building android/ubuntu-touch on 32bit machine
    Android开发(24)---安卓中实现多线程下载(带进度条和百分比)
    创建Sdcard
    POJ 1033 Defragment
    [C++STDlib基础]关于C标准输入输出的操作——C++标准库头文件<cstdio>
    机器学习实战决策树之眼镜男买眼镜
    protubuffer for windows配置指南!
  • 原文地址:https://www.cnblogs.com/tech-bird/p/3514753.html
Copyright © 2011-2022 走看看