A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 周刚 中级黑马   /  2012-6-30 14:06  /  1879 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

毕老师在讲到Iterator的时候讲到了内部类,我想集合大家的智慧再将内部类弄得更清楚一些。
什么时候用内部类,使用内部类有什么作用和好处,还有使用内部类要注意些什么?

8 个回复

倒序浏览
你听课是跳着听的?老师在前面貌似花了两个视频讲解这个东西
回复 使用道具 举报
这个问题我也是刚刚总结了一下,分享给大家吧!

内部类:
(注:所有使用内部类的地方其实都可以不用内部类,使用内部类可以使程序更加的简洁,便于命名规范和划分层次结构)。
内部类是指在一个外部类的内部再定义一个类。
内部类作为外部类的一个成员,并且依附于外部类而存在的。
内部类可为静态,可用protected和private修饰。(而外部类不可以:外部类只能使用public和default)。
内部类的分类:
成员内部类、局部内部类、静态内部类、匿名内部类。
成员内部类:作为外部类的一个成员存在,与外部类的属性、方法并列。
内部类和外部类的实例变量可以共存。
在内部类中访问实例变量:this.属性
在内部类访问外部类的实例变量:外部类名.this.属性。
成员内部类的优点:
⑴内部类作为外部类的成员,可以访问外部类的私有成员或属性。(即使将外部类声明为PRIVATE,但是对于处于其内部的内部类还是可见的。)
⑵用内部类定义在外部类中不可访问的属性。这样就在外部类中实现了比外部类的private还要小的访问权限。
注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。
对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。

成员内部类不可以有静态属性。
如果在外部类的外部访问内部类,使用out.inner.
建立内部类对象时应注意:
在外部类的内部可以直接使用inner s=new inner();(因为外部类知道inner是哪个类,所以可以生成对象。)
而在外部类的外部,要生成(new)一个内部类对象,需要首先建立一个外部类对象(外部类可用),然后在生成一个内部类对象。
Outer.Inner in=Outer.new.Inner()。
错误的定义方式:
Outer.Inner in=new Outer.Inner()。
注意:当Outer是一个private类时,外部类对于其外部访问是私有的,所以就无法建立外部类对象,进而也无法建立内部类对象。
局部内部类:在方法中定义的内部类称为局部内部类。
与局部变量类似,在局部内部类前不加修饰符public和private,其范围为定义它的代码块。
注意:局部内部类不仅可以访问外部类实例变量,还可以访问外部类的局部变量(但此时要求外部类的局部变量必须为final)
在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)。
要想使用局部内部类时需要生成对象,对象调用方法,在方法中才能调用其局部内部类。
静态内部类:(注意:前三种内部类与变量类似,所以可以对照参考变量)
静态内部类定义在类中,任何方法外,用static定义。
静态内部类只能访问外部类的静态成员。
生成(new)一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成:
Outer.Inner in=new Outer.Inner();
而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类。
静态内部类不可用private来进行定义。
例子:
对于两个类,拥有相同的方法:
People
{
  run();
}
Machine{
   run();
}
此时有一个robot类:
class Robot extends People implement Machine.
此时run()不可直接实现。
注意:当类与接口(或者是接口与接口)发生方法命名冲突的时候,此时必须使用内部类来实现。
用接口不能完全地实现多继承,用接口配合内部类才能实现真正的多继承。
匿名内部类:
匿名内部类是一种特殊的局部内部类,它是通过匿名类实现接口。
IA被定义为接口。
IA I=new IA(){};
注:一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类,没有类名,根据多态,我们使用其父类名。
因其为局部内部类,那么局部内部类的所有限制都对其生效。
匿名内部类是唯一一种无构造方法类。
匿名内部类在编译的时候由系统自动起名Out$1.class。
如果一个对象编译时的类型是接口,那么其运行的类型为实现这个接口的类。
因匿名内部类无构造方法,所以其使用范围非常的有限。

点评

警告一次,麻烦不要用这种回答,最好是你自己的理解,简单,直接  发表于 2012-6-30 17:10
回复 使用道具 举报
内部类
        (1)概述 在类的内部定义类。
                A:只不过是类的位置发生了变化而已。
        (2)特点
                A:内部类可以直接访问外部类的成员,包括private修饰的。
                B:外部类要想访问内部类,必须创建对象。
        (3)在类中的所在位置
                A:成员位置
                        class Outer
                        {
                                private int num = 10;

                                class Inner()
                                {
                                        void show()
                                        {
                                                System.out.println("show");
                                        }
                                }

                                void method()
                                {
                                        Inner i = new Inner();
                                        i.show();
                                }
                        }

                        外部:
                        Outer.Inner oi = new Outer().new Inner();
                        oi.show();

                        **它可以被private修饰
                                class Body
                                {
                                        private class Heart
                                        {
                                       
                                        }

                                        public Heart getHeart()
                                        {
                                                //code
                                                return new Heart();
                                        }
                                }
                        **它可以被static修饰,它只能访问外部类中的静态成员

                B:局部位置
                        class Outer
                        {
                                void method()
                                {
                                        final int X = 10;
                                        class Inner
                                        {
                                                void show()
                                                {
                                                        System.out.println(X);
                                                }
                                        }

                                        Inner i = new Inner();
                                        i.show();
                                }
                        }

                        **它可以访问外部类的成员,也可以访问局部变量,但是访问局部的变量必须
                          被final修饰,其实也就是常量。
                        **它不可以被private或者static修饰。
        (4)匿名内部类
                A:没有名字的局部的内部类。
                B:前提
                        **内部类可以继承或实现一个外部类或者接口。
                C:格式
                        **new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
                D:简单理解:
                        **就是建立一个带内容的外部类或者接口的子类匿名对象。

                举例:
                        interface Inter
                        {
                                public abstract void show();
                        }

                        class Outer
                        {
                                void method()
                                {
                                        第一种:
                                        new Inter()
                                        {
                                                public void show()
                                                {
                                                        System.out.println("show");
                                                }
                                        }.show();


                                        第二种:
                                        Inter i = new Inter()
                                        {
                                                public void show()
                                                {
                                                        System.out.println("show");
                                                }
                                        };
                                        i.show();
                                }
                        }

这是我学习时候的总结,楼主看看吧

评分

参与人数 1技术分 +1 收起 理由
刘蕴学 + 1

查看全部评分

回复 使用道具 举报
以下是我的学习总结,希望可以帮到你。
内部类定义原则:当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物的内容。
访问特点:
1、内部类可以直接访问外部类中的成员,包括私有成员。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this.
2、而外部类要访问内部类中的成员必须要建立内部类的对象。

例:
class Outer
{
        private int x=5,y=3;
       
        int sum=x+y;
               
       
        class Inner
        {
                int x = 7;
                void funcation()
                {
                        int x =6;
                        System.out.println(Outer.this.x);
                        System.out.println(y);
                        System.out.println("Outer sum="+sum);
                }
               
        }
        void method()
        {
                Inner in = new Inner();
                in.funcation();
        }
}
class Demotext
{
        public static void main(String[] args)
        {
                Outer out = new Outer();
                out.method();
        }
}
分析:System.out.println(x);有局部变量x时,打印的是内部类里的局部变量x,如果要打印成员变量x=7,则写成System.out.println(this.x);如果要打印外部类的x=5,则写成System.out.println(Outer.this.x);

访问格式:
1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,直接建立内部类对象。格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象
例如以上代码最后两句可写为:Outer.Inner c = new Outer( ).new Inner( );
                                    c.funcation();
2、当内部类在成员位置上,就可以被成员修饰符所修饰。比如,private:将内部类在外部类中进行封装。static:内部类就具备static的特性。当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。

在外部其他类中,如何直接访问静态内部类的非静态成员呢?
class Without
{
        static private int x = 10;
        static class Inside //静态内部类
        {
                void funcation()
                {
                        System.out.println(x);

                }
                static  String a = "hello";

        }
}
class DemoText
{
        public static void main(String[] args)
        {
                System.out.println((Without.Inside.a));
                new Without.Inside().funcation();
        }
}
分析:变量x是静态的,跟着类的加载而直接存在在内存中,可以直接显示,即不用建立外部类对象。而funcation这个方法是非静态的,要调用此方法,就需要新建个内部类对象,再用内部类对象来调用此方法:new Without.Inside().funcation();
在外部其他类中,如何直接访问静态内部类的静态成员呢?
如果funcation这个方法是静态的,访问格式为:Without.Inside().funcation();
注意:当内部类中定义了静态成员,该内部类也必须是static的。当外部类中的静态方法访问内部类时,内部类也必须是static的。
内部类定义在局部时:1、不可以被成员修饰符修饰。2、可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。
例:
class Outside
{
        private int x = 6;
        void show(final int a)
        {
                final int y =12;
                class Inside
                {
                        void funcation()
                        {
                                System.out.println("x="+x);
                                System.out.println("y="+y);
                                System.out.println("a="+a);
                        }
                }
                new Inside().funcation();
        }
       
}
class DemoText
{
        public static void main(String[] args)
        {
                 Outside out = new Outside();
                 out.show(2);
                 out.show(3);

        }
}
分析:out.show(2);把2传给a,又把out.show(3);3传给a后,最后的结果是a=3。因为a=2时虽然被锁住了,但是它一进栈内存,程序运行完后就会被释放,接着运行out.show(3);
时,又是一个新的a=3进了栈内存。

评分

参与人数 1技术分 +1 收起 理由
刘蕴学 + 1

查看全部评分

回复 使用道具 举报
我在这里跟你简单的总结下:
内部类是指在一个类的内部再定义一个类。内部可以用private和protected修饰,而普通的类只能用public或默认的访问权限修饰。
内部类包括:成员内部类、局部内部类、静态内部类、匿名内部类。
1、成员内部类 :
形如:
class Outer {  /外部类
       class Inner{}  //内部类
  }


2、局部内部类
局部内部类的作用范围和局部变量是一样的,形如:
class Outer {
    public void doSomething() {
        class Inner { }
    }
}

3、静态内部类
使用static关键字声明的内部类,形如:
class Outer {
        static class Inner{}
  }


4、匿名内部类
匿名内部类是在抽象类和接口的基础上发展起来的,形如:
new InnerFather{
       //匿名内部类
  }
其中,
InnerFather
是匿名内部类继承的类名,或是要实现的接口的接口名。

总结内部类的优点:
1)可以很好的实现隐藏
2)可以随意访问外部类的元素
3)可以实现多重继承


这些刚开始你可能不理解,不过没关系,当你运用起来的时候,你自然就体会到了。


评分

参与人数 1技术分 +1 收起 理由
刘蕴学 + 1

查看全部评分

回复 使用道具 举报
金龙 中级黑马 2012-6-30 21:48:44
7#
首先,内部类与外部类的调用特点要记住:   1:内部类可以直接调用外部类的成员,包括私有。而外部类想要调用内部类的成员则需要建立内部类对象来调用。
                                         2:内部类之所以可以调用外部类的成员,是因为它持有了外部类的引用。
还有需要注意内部类定义的位置,可以定义在成员位置上,也可以定义在局部,,具体的我觉得你应该回头看一看内部类的视频。
回复 使用道具 举报
内部类说通说点就是在一个类的下边再定义一个类,这样的类中的类叫做内部类
内部类的好处有以下几点:
1.能够很好的将自身隐藏 因为一般情况下不是内部类是不允许使用 private 和protected这两个修饰符的,但是内部类是可以使用的,这样通过这样的修饰符便可以将内部类做一个很好的隐藏
2.内部类他可以使用他自己外边类中的所有元素
3.一般的类在java中只允许单继承,而内部类可以多继承
下边这段代码是典型的内部类继承的一个例子,又有内部类 并且还有其他类继承内部类的一个方法
class WithInner
{
    class Inner//这个是Withinner类的内部类,Inner拥有withinner类中所有元素的访问权限
    {
        public void sayHello()
        {
            System.out.println("Hello.");
        }
    }
}

public class Test extends WithInner.Inner//这个是继承WithInner中的Inner类。Inner是WithInner的内部类
{
    Test(WithInner wi)
    {
        wi.super();
    }
    public static void main(String[] args)
    {
        WithInner wi=new WithInner();
        Test test=new Test(wi);
        test.sayHello();
    }
}

评分

参与人数 1技术分 +1 收起 理由
刘蕴学 + 1

查看全部评分

回复 使用道具 举报
我也来谈谈自己关于内部类的理解吧:顾名思义,通俗点就是一个类在另一个类的内部,这就叫做内部类,大家也都说了,内部类能够访问外部类的所有成员,为什么呢,就是因为在创建内部类的时候,会有一个外部类的引用被内部类捕获,所以这根外部类访问自己的变量是一个效果。而且获得当前外部类的引用通过.this 注意了 千万不要new一个外部类来将引用给内部类,这时候就是一个新的引用了
而且内部类实现一个接口的方法的时候可以声明成私有的类,这样除了他的外部类可以访问 其他都不能访问,这样就很容易做到 将接口方法的实现代码隐藏起来,

内部类也可以写在一个方法里面,但是这时候不能用类型修饰符,

接下来就是匿名内部类了,我们一般的应用就是去实现一个接口当中的方法 这是我们常用的,匿名内部类要防伪外部类的变量或者形参时这些变量必须声明为final类型的 具体为什么我以前也问过 也论坛里面有很多的在这就不详细写了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马