Java中的内部类

  1. 什么是内部类       

    内部类是指在一个外部类的内部再定义一个类。
    内部类可以是静态static的,也可用public,default,protected和private修饰。(而外部顶级类即类名和文件名相同的只能使用public和default)。
    注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类。编译完成后出现Outer.class和Outer$Inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。
    java内部类分为: 成员内部类、静态嵌套类、局部内部类、匿名内部类 。

  2. 内部类的共性

    (1)、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
    (2)、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的 。
    (3)、内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。
  3. 成员内部类
    public class Outer {
        private int a = 10;
        private int b = 15;
        
        public void print() {
            System.out.println("Outer.a="+this.a);
        }
        
        public int add(int i,int j) {
            return i+j;
        }
        
        class Inner {        
            private int a = 20;
            private int c = b;
            
            public void print() {
                //内部类访问外部类中的同名成员变量
                System.out.println("Outer.a="+Outer.this.a);    
                System.out.println("Inner.a="+this.a);
                System.out.println("a="+a);
                //内部类中可以直接访问外部类的成员变量和方法(内部类对象持有指向外部类对象的引用。)
                System.out.println("c="+c);
                System.out.println("c+1="+add(c,1));
            }
        }
        
        public static void main(String[] args) {
            Outer outer = new Outer();
            outer.print();
            //内部类对象的创建依赖于外部类对象;
            outer.new Inner().print();   
        }
    }
    这个类编译后出现Outer.class和Outer$Inner.class两个class文件。编译后成为两个独立的类,
    因此,内部类中可以定义与外部类中同名的属性和方法。

    成员内部类,就是作为外部类的成员,与外部类的属性、方法并列。可以直接使用外部类的所有成员和方法,即使是private的。
    同时外部类要访问内部类的所有成员变量和方法,则需要通过内部类的对象来获取。
    要注意的是,成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的

  4. 局部内部类
    局部内部类,是指内部类定义在方法和作用域内。
    (1)、定义在方法内
        
    public class Teacher {
        
        private String name;
        private int age;    
        
        public void teach() {
            final String str = "I'm a teacher!";
            class EnglishTeacher {
                public void teachEnglish() {
                    System.out.println("My name is "+name);
                    System.out.println("I'm "+age);
                    System.out.println(str);
                    System.out.println("I teach English");
                    
                }
            }
            
            EnglishTeacher englishTeacher = new EnglishTeacher();
            englishTeacher.teachEnglish();
        }

        /**
         * 
    @param args
         
    */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Teacher teacher = new Teacher();
            teacher.name = "张三";
            teacher.age = 35;
            teacher.teach();
        }
    } 


    (2)、定义在作用域内
     

    public class Teacher1 {

        private String name;
        private int age;    
        
        public void teach(String course) {
            final String str = "I'm a teacher!";
            System.out.println(str);
            if("English".equals(course)) {
                class EnglishTeacher {
                    public void teachEnglish() {
                        System.out.println("My name is "+name);
                        System.out.println("I'm "+age);
                        System.out.println("I teach English");
                    }
                }
                
                EnglishTeacher englishTeacher = new EnglishTeacher();
                englishTeacher.teachEnglish();
            }        
        }
        /**
         * 
    @param args
         
    */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Teacher1 teacher = new Teacher1();
            teacher.name = "张三";
            teacher.age = 35;
            teacher.teach("English");
        }

    }
        

    (1)、局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
    (2)、局部内部类对象不能使用该内部类所在方法的非final局部变量。
    (3)、局部内部类的地位和方法内的局部变量的位置类似,因此不能修饰局部变量的修饰符也不能修饰局部内部类,
           譬如public、private、protected、static、transient等
    因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。
  5. 静态嵌套类


    public class StaticOuter {

        private int a = 10;
        private static int b = 15;
        
        static class StaticInner {
            public static void print() {
                System.out.println("b="+b);
            }
            
            void print1() {
                System.out.println("b="+b);
            }
        }
        /**
         * 
    @param args
         
    */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            StaticOuter.StaticInner.print();
            new StaticOuter.StaticInner().print1();
        }

    }

    嵌套类和普通的内部类还有一个区别:普通内部类不能有static数据和static属性,也不能包含嵌套类,但嵌套类可以。
    而嵌套类不能声明为private,一般声明为public,方便调用。

    在静态方法中定义的内部类也是StaticNested Class,这时候不能在类前面加static关键字,静态方法中的StaticNested Class与
    普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,
    但是,该局部变量前必须加final修饰符。

  6. 匿名内部类

  7. 匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:
    ·只用到类的一个实例 。
    ·类在定义后马上用到。
    ·类非常小(SUN推荐是在4行代码以下)
    ·给类命名并不会导致你的代码更容易被理解。
    在使用匿名内部类时,要记住以下几个原则:
    ·匿名内部类不能有构造方法。
    ·匿名内部类不能定义任何静态成员、静态方法。
    ·匿名内部类不能是public,protected,private,static。
    ·只能创建匿名内部类的一个实例。
    ·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
    ·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

    (1)、继承式的匿名内部类

    public class Singer {
        
        public void sing() {
            System.out.println("Sing a song");
        }

        /**
         * 
    @param args
         
    */
        public static void main(String[] args) {
            // TODO Auto-generated method stub

            Singer singer = new Singer() {

                @Override
                public void sing() {
                    // TODO Auto-generated method stub
                    System.out.println("Sing a popular song");
                }
                
            };
            singer.sing();
        }

    }

    输出结果:Sing a popular song

    (2)、接口式的匿名内部类


    public interface Programmer {
        
        public void code();

    }



    public class TestProgrammer {

        /**
         * 
    @param args
         
    */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Programmer javaProgrammer = new Programmer() {

                @Override
                public void code() {
                    // TODO Auto-generated method stub
                    System.out.println("Java programmer");
                }
            };

            javaProgrammer.code();
            
            Programmer phpProgrammer = new Programmer() {

                @Override
                public void code() {
                    // TODO Auto-generated method stub
                    System.out.println("Php programmer");
                }
            };

            phpProgrammer.code();
        }

    }

    (3)、参数式的匿名内部类


    public interface Programmer {
        
        public void code();

    }




    public class TestProgrammer1 {

        public void testCode(Programmer p) {
            p.code();
        }
        
        /**
         * 
    @param args
         
    */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            TestProgrammer1 testProgrammer1 = new TestProgrammer1();
            testProgrammer1.testCode(new Programmer() {
                
                @Override
                public void code() {
                    // TODO Auto-generated method stub
                    System.out.println("testing code");
                }
            });
        }

    }


  8. 为什么需要内部类

  9. 典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。
    使用内部类最吸引人的原因是:
    每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。

posted on 2014-08-01 17:34 小罗 阅读(120) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 
<2019年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿

随笔分类

随笔档案

文章分类

文章档案

相册

收藏夹

Web Framework

常上的技术网站

查找资料的java网站

搜索

最新评论

阅读排行榜

评论排行榜