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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 汪龙 注册黑马   /  2014-4-10 20:59  /  776 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

什么是内部类?Static Nested Class Inner Class的不同。

4 个回复

倒序浏览
内部类就是在一个类的内部定义的类,内部类中不能定义静态成员(静态成员不是对象的特性,只是为了找一个容身之处,所以需要放到一个类中而已,这么一点小事,你还要把它放到类内部的一个类中,过分了啊!提供内部类,不是为让你干这种事情,无聊,不让你干。我想可能是既然静态成员类似c语言的全局变量,而内部类通常是用于创建内部对象用的,所以,把“全局变量”放在内部类中就是毫无意义的事情,既然是毫无意义的事情,就应该被禁止),内部类可以直接访问外部类中的成员变量,内部类可以定义在外部类的方法外面,也可以定义在外部类的方法体中,如下所示:
  1. public class Outer
  2. {
  3.            int out_x  = 0;
  4.            public void method()
  5.                    {
  6.                     Inner1 inner1 = new Inner1();
  7.                     public class Inner2   //在方法体内部定义的内部类
  8.                     {
  9.                              public method()
  10.                              {
  11.                                        out_x = 3;
  12.                              }
  13.                     }
  14.                     Inner2 inner2 = new Inner2();
  15.            }

  16.            public class Inner1   //在方法体外面定义的内部类
  17.            {
  18.            }
  19.          
  20. }
复制代码


在方法体外面定义的内部类的访问类型可以是public,protecte,默认的,private等4种类型,这就好像类中定义的成员变量有4种访问类型一样,它们决定这个内部类的定义对其他类是否可见;对于这种情况,我们也可以在外面创建内部类的实例对象,创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象,代码如下:
Outer outer = new Outer();
Outer.Inner1 inner1 = outer.new Innner1();
在方法内部定义的内部类前面不能有访问类型修饰符,就好像方法中定义的局部变量一样,但这种内部类的前面可以使用final或abstract修饰符。这种内部类对其他类是不可见的其他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问。这种内部类必须是先定义,后使用,即内部类的定义代码必须出现在使用该类之前,这与方法中的局部变量必须先定义后使用的道理也是一样的。这种内部类可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符。
对于这些细节,只要在eclipse写代码试试,根据开发工具提示的各类错误信息就可以马上了解到。
在方法体内部还可以采用如下语法来创建一种匿名内部类,即定义某一接口或类的子类的同时,还创建了该子类的实例对象,无需为该子类定义名称:
  1. public class Outer
  2. {
  3.            public void start()
  4.            {
  5.                     new Thread(
  6. new Runable(){
  7.                                        public void run(){};
  8. }
  9. ).start();
  10.            }
  11. }
复制代码

最后,在方法外部定义的内部类前面可以加上static关键字,从而成为Static Nested Class,它不再具有内部类的特性,所有,从狭义上讲,它不是内部类。Static Nested Class与普通类在运行时的行为和功能上没有什么区别,只是在编程引用时的语法上有一些差别,它可以定义成public、protected、默认的、private等多种类型,而普通类只能定义成public和默认的这两种类型。在外面引用Static Nested Class类的名称为“外部类名.内部类名”。在外面不需要创建外部类的实例对象,就可以直接创建Static Nested Class,例如,假设Inner是定义在Outer类中的Static Nested Class,那么可以使用如下语句创建Inner类:
Outer.Inner inner = new Outer.Inner();
由于static Nested Class不依赖于外部类的实例对象,所以,static Nested Class能访问外部类的非static成员变量。当在外部类中访问Static Nested Class时,可以直接使用Static Nested Class的名字,而不需要加上外部类的名字了,在Static Nested Class中也可以直接引用外部类的static的成员变量,不需要加上外部类的名字。
在静态方法中定义的内部类也是Static Nested Class,这时候不能在类前面加static关键字,静态方法中的Static Nested Class与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。


评分

参与人数 1技术分 +1 收起 理由
itpower + 1

查看全部评分

回复 使用道具 举报
本帖最后由 沫然 于 2014-4-10 22:53 编辑

Nested Class (一般是C++的说法),InnerClass (一般是JAVA的说法)

Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。



Nested class分为静态Static nestedclass 的和非静态的 inner class,


静态的Static nested class是不可以直接调用它的外部类enclosing class的,但是可以通过外部类的引用来调用,就像你在一个类中写了main方法一样。

非静态类inner class 可以自由的引用外部类的属性和方法,但是它与一个实例绑定在了一起,不可以定义静态的属性、方法

Inner Class(内部类)定义在类中的类。


Nested Class(嵌套类)是静态(static)内部类。
1. 要创建嵌套类的对象,并不需要其外围类的对象。
2. 不能从嵌套类的对象中访问非静态的外围类对象。


Anonymous Inner Class (匿名内部类)匿名的内部类是没有名字的内部类。


匿名的内部类不能extends(继承)其它类,但一个内部类可以作为一个接口,由另一个内部类实现。


嵌套类可以作为接口的内部类。正常情况下,你不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分,因为它是static 的。只是将嵌套类置于接口的命名空间内,这并不违反接口的规则。

静态方法是不能继承的,因为它是静态的,所谓静态当然是时间和空间的静止喽.
然后finaljava里面定义的,不能被重载的函数。

java里面的函数如果没有特别标识,只要在子类中定义了一个同名的函数,那么父类的函数就被重载掉了。如果new一个子类的对象给父类再调用这个函数,就是调用子类的了。只有new的是父类的调的才是父类的。

java里面没有virtual的说法,因为不是finalstatic就是virtual的。

abstract是虚函数,自然不可能是final的,同时如上所说,static是不能被重载只能被覆盖的,所以也不可以是abstract


在使用匿名内部类时,要记住以下几个原则:
  ·匿名内部类不能有构造方法。   
  ·匿名内部类不能定义任何静态成员、方法和类。   
  ·匿名内部类不能是public,protected,private,static   
  ·只能创建匿名内部类的一个实例。
      ·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。   
  ·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。  


匿名类和内部类中的中的this :

有时候,我们会用到一些内部类和匿名类。当在匿名类中用this时,这个this则指的是匿名类或内部类本身。这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。

  1. /**  
  2. *  
  3. * 普通内部类持有对外部类的一个引用, 静态内部类却没有  
  4. *  
  5. * @author howard  
  6. */  
  7. public class OutterClass {   
  8.   
  9.     /*  
  10.      * this is static nested class  
  11.      */  
  12.     private static class StaticNestedClass {   
  13.         private void yell() {   
  14.             System.out.println(this.toString());   
  15.             // OutterClass.this.yell();//静态内部类实例没有外部类实例的引用   
  16.         }   
  17.     }   
  18.   
  19.     /*  
  20.      * this is inner class  
  21.      */  
  22.     private class InnerClass {   
  23.         private void yell() {   
  24.             System.out.println(this.toString());   
  25.             OutterClass.this.yell();//内部类实例显式使用外部类实例的方式   
  26.         }   
  27.     }   
  28.   
  29.     private void yell() {   
  30.         System.out.println( this.toString());   
  31.     }   
  32.   
  33.     private void run() {   
  34.         /*  
  35.          * this is local class  
  36.          */  
  37.         class LocalClass {   
  38.             public void yell(){   
  39.                 System.out.println(this.toString());   
  40.             }   
  41.         }   
  42.         /*  
  43.          * this is anonymous class  
  44.          */  
  45.         new Object() {   
  46.             public void yell(){   
  47.                 System.out.println(this.toString());   
  48.             }   
  49.         }.yell();   
  50.         LocalClass lc=new LocalClass();   
  51.         InnerClass ic = new InnerClass();   
  52.         StaticNestedClass sc=new StaticNestedClass();   
  53.         lc.yell();   
  54.         ic.yell();   
  55.         sc.yell();   
  56.     }   
  57.   
  58.     public static void main(String[] args) {   
  59.         OutterClass oc = new OutterClass();   
  60.         oc.run();   
  61.     }   
  62. }  
复制代码


仔细分析如上代码,可以得出一个结论,所有的内部类,Local内部类,匿名内部类都可以直接访问外面的封装类的实例变量和方法。而静态嵌套类则不能。

调试代码可以发现,内部类,Local内部类,匿名内部类的实例都持有一个外部封装类实例的隐式引用; java对象序列化要求对象里所有的对象成员都实现序列化接口。

所以,如果只有内部类实现序列化,而外部封装类没有实现序列化接口,就会在对内部类进行序列化的时候报出异常。


评分

参与人数 1技术分 +1 收起 理由
itpower + 1

查看全部评分

回复 使用道具 举报
内部类 就是类中类,

class Outer
{
            class Inner
        {
        }

}  其他的我都省了只是为了方便你理解看懂。
回复 使用道具 举报
内部类的访问规则:
1,内部类可以直接访问外部类中的成员,包括私有
        之所以可以直接访问内部类中的成员,是因为内部类持有了一个外部类的引用 。格式:外部类名.this
2,外部类要访问内部类,必须建立内部对象

访问格式:
1,当内部类定义在外部类的成员位置上,也非私有,可以在外部其他类中直接建立内部类对象
格式:
        外部类名.内部类名 变量名 = 外部对象.内部对象
        Outer.Inner in = new Outer().new Inner();
2,当内部类在成员位置上,就可以被成员修饰符所修饰
        比如private:将内部类在外部类中进行封装
        static:内部类就具备了静态的特性
        当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问权限
       
        在外部其他类中,如何直接访问静态内部类的非静态成员呢
        new Outer.Inner().functin();
        在外部其他类中,如何直接访问静态内部类的静态成员呢
        Outer.Inner.function();
       
        注意当内部类定义了静态成员,该内部类必须是静态的
        当外部类中的静态方法访问内部类时,内部类也必须是static的

当描述事物时,事物的内部还有事物,该事物用内部类描述
因为内部事物在使用外部事物的内容。
  1. class Outer
  2. {
  3.         private static int x;
  4.         static class Inner
  5.         {
  6.                 static void fuction()
  7.                 {       
  8.                         int x = 4;
  9.                         System.out.println("inner"+ x);
  10.                 }
  11.         }
  12.         static class Inner2
  13.         {
  14.                  void show()
  15.                 {
  16.                         System.out.println("show run");
  17.                 }
  18.         }
  19.         public static void method()
  20.         {
  21.                 //Inner in = new Inner();
  22.                 //in.fuction();
  23.                 new Inner2().show();
  24.         }
  25. }

  26. class InnerClassDemo
  27. {
  28.         public static void main(String[] args)
  29.         {
  30.                 Outer out = new Outer();
  31.                 out.method();
  32.                 new Outer.Inner().fuction();
  33.                 //直接访问内部类的成员
  34.                 //Outer.Inner in =  new Outer().new Inner();
  35.                 //in.fuction();
  36.         }
  37. }
复制代码

内部类定义在局部时
1,不可以被成员修饰符修饰
2,可以直接访问外部类中的成员,因为还持有外部类的引用,但是不可以访问它所在的局部的变量
        只能访问被final修饰的局部变量
匿名内部类:
1,匿名内部类其实就是内部类的简写格式
2,定义匿名内部类的前提:
        内部类必须是继承一个类或实现接口
3,匿名内部类的格式:new 父类或者接口() {定义子类的内容}
4,其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象
5,匿名内部类中定义的方法最好不超过三个
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马