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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 曾林魁 于 2013-5-30 12:22 编辑

这几天在学面向对象基础,里面的内部类访问规则不太懂,谁能解释一下吗?例如  Outer.Inner in = new Outer().newInner();
还有就是内部类与匿名内部类有什么区别?
我是菜鸟,谁帮我解释一下吧?我先谢谢了 !!

评分

参与人数 1技术分 +1 收起 理由
袁梦希 + 1 很给力!

查看全部评分

10 个回复

倒序浏览
内部类中有一种定义在方法中的类叫局部内部类,匿名内部类是没有命名的一种局部内部类。
规则大体如下(是我在做一道基础测试题时总结的,可能不全面):
  1. * 外部类实例与内部类的实例的之间为一对多关系。一个内部类实例只会引用一个外部类实例。
  2. * 而一个外部类实例对应零个或者多个内部类的实例。在外部类中不能直接访问内部类成员,
  3. * 必须通过内部类的实例访问。
  4. *
  5. * 实例内部类的实例自动持有外部类的实例的引用。
  6. * 在内部类中,可以直接访问外部类的所有成员。包括成员变量和成员方法。
  7. *
  8. * 一般的内部类(非static类)的内部没有静态属性。在实例内部类中不能定义静态成员,只能定义实例成员。
  9. *
  10. * 在多层嵌套中,内部类可以访问所有外部类的成员。内层内部类可以访问外层内部类。
  11. *
  12. * 局部内部类是在一个方法中定义的内部类,他的可见范围是当前的方法,局部内部类不能访问修饰符及修饰。
  13. *
  14. * 局部内部类和实例内部类一样,可以访问外部类的所有成员。
  15. * 局部内部类还可以访问所在方法中的final类型的参数和变量。
  16. * 在局部内部类和实例内部类一样,不能包含静态成员。
复制代码

评分

参与人数 2技术分 +1 黑马币 +3 收起 理由
袁梦希 + 1 很给力!
曾林魁 + 3

查看全部评分

回复 使用道具 举报
内部类:
     1、访问特点:内部类可以直接访问外部类中的成员,包括私有。
     2、外部类访问内部类时必须建立内部类的对象。
匿名内部类:
     1、其实是内部类的简写格式,匿名内部类必须继承一个类或者实现接口。

区别:
    内部类的访问格式是:Outer.Inner in=new Outer().new Inner();
    匿名内部类的访问格式:new 父类或者接口(){定义子类内容}.方法();
    匿名内部类对象一次只能调用一个方法。
   匿名内部类时一个带内容的匿名子类对象。   

评分

参与人数 2技术分 +1 黑马币 +2 收起 理由
袁梦希 + 1 很给力!
曾林魁 + 2

查看全部评分

回复 使用道具 举报
最好看看(传智播客毕向东Java基础视频教程-day09),毕竟知识不是三言两语告诉你你就能理解的,这是毕老师所有的java基础课程的下载地址:http://edu.csdn.net/news/2012821/83780387427c.shtml  。如果你已经下载了,就好好看看,想必就会了。

评分

参与人数 2技术分 +1 黑马币 +1 收起 理由
袁梦希 + 1 很给力!
曾林魁 + 1

查看全部评分

回复 使用道具 举报
匿名就是没名字呗。这个貌似用处不大,就是在写GUI程序的事件那部分有点用处。
回复 使用道具 举报
以下内容均系手打,并非从网上Ctrl+C、Ctrl+V来的(我也刚学到这里)

从字面上理解,内部类就是定义在Outer类里面的类(Inner),是Outer类的一部分,所以Outer的成员变量和成员函数都可以被Inner直接调用,即便被private修饰也可以。但是如果想要调用被static修饰的成员,那么Inner本身也必须加上static。

Inner可以定义在Outer的成员位置上,这时根据类中成员的特点,Inner类可以被static等成员修饰符修饰;
Inner也能定义在Outer中方法的内部,这时Inner定义在局部,如果想要访问所在局部的局部变量,该变量必须被final修饰。

无论Inner定义在哪个位置,它都拥有对外部类的引用,即:Outer.this.  
但是如果外部类想要访问内部类中的内容,就必须创建一个内部类的实例对象,因为类中的内容只有创建了对象才能被调用。(static情况除外)

Outer.Inner in = new Outer().newInner(); 这句我们类比一下Person p = new Person();  并把它分解一下:
左边:Outer.Inner 是声明引用类型。类比一下Person p,Person声明了这是一个Person类类型的类引用,同理 Outer.Inner声明了这是一个Inner类类型的引用,但是有可能还同时存在另一个Outer02里面也定义了一个类名叫做Inner的内部类,所以加上Outer.用于区分。  "in"就是相当于p,就是给这个引用起了个名字。
右边:如果是new Person()就是创建一个实例化对象。但是,这里由于Inner是在Outer里面的,Outer是一个类,类中的成员是通过对象来调用(访问)的,所以如果想要访问到Inner类就需要创建Outer的实例化对象,即:new Outer() 。那么"new Outer()."就相当于对象调用的方式。访问到Inner类后,使用后面的new Inner()就是创建了一个Inner的实例化对象。
概括起来可以这样表示: Outer.Inner in = new Outer().new Inner() <===> 外部类名.内部类名 引用变量名 =  外部类对象.内部类对象



匿名就是隐藏起来了名字,也就是没有名字。换句话说,这个内部类很特殊,他没有名字。
没有名字我们怎么创建、使用、访问这个内部类呢?于是有了匿名内部类的前提:匿名内部类必须是继承(或者实现)父类(或者接口)。
这时内部类的父亲说了:既然你没有名字,就用我的吧。于是出现了:Fu f = new Inner(); (这里的Inner是假想出来的,为了便于表示,实际上是没有名字的)这就形成了父类的引用指向了子类的对象,也就是多态的体现。可以看到,匿名内部类其实不是“类”,而是一个子类的对象。

由于匿名内部类继承(实现)了父类(接口),所以必须复写父类(接口)的功能 ,并使用对象调用的方法调用复写的功能。

以毕老师视频中内部类练习为例说明一下(注释中的一、二、三是我根据楼主提的问题标注的,其他的是毕老师的,看视频都有的)
  1. interface Inter//接口
  2. {
  3.         void method();//接口中功能,省略了public abstract修饰符
  4. }

  5. class Test
  6. {
  7.         //补足代码。通过匿名内部类。
  8.         /*
  9.         static class Inner implements Inter
  10.         {
  11.                 public void method()
  12.                 {
  13.                         System.out.println("method run");
  14.                 }
  15.         }
  16.         */
  17.        
  18.         static Inter function()//返回值类型是Inter类型的对象
  19.         {
  20.                 return new Inter()//一、从new Inter(){}开始就是匿名内部类。可以看到在创建匿名内部类对象的时候使用的是接口名,并在"{}"中复写了接口对外提供的功能。而这个new Inter(){}整体作为一个对象存在,成为function()方法的返回值,注意返回值类型是Inter类类型的
  21.                 {
  22.                         public void method()
  23.                         {
  24.                                 System.out.println("method run");
  25.                         }
  26.                 };
  27.         }

  28. }



  29. class  InnerClassTest
  30. {
  31.         public static void main(String[] args)
  32.         {

  33.                 //Test.function():Test类中有一个静态的方法function。
  34.                 //.method():function这个方法运算后的结果是一个对象。而且是一个Inter类型的对象。
  35.                 //因为只有是Inter类型的对象才可以调用method方法。


  36.                 Test.function().method();


  37. //                Inter in = Test.function();
  38. //                in.method();

  39.                
  40.                 show(new Inter()//二、这里的new Inter(){}整体也是一个匿名内部类,道理请类比“一”中的解释
  41.                 {
  42.                         public void method()
  43.                         {
  44.                                 System.out.println("method show run");               
  45.                         }
  46.                 });

  47.         }

  48.         public static void show(Inter in)
  49.         {
  50.                 in.method();
  51.         }
  52. }

  53. class InnerTest
  54. {

  55.         public static void main(String[] args)
  56.         {
  57.                 new Object()//三、Object是所有类的直接、间接父类,所以也可以被匿名内部类继承。这里定义了父类中没有的特有方法,注意方法调用的书写方式
  58.                 {
  59.                         public void function()
  60.                         {
  61.                                
  62.                         }

  63.                 }.function();
  64.         }
  65. }
复制代码
差不多就这些了。。。累死我了。。。吃饭去 =。=






评分

参与人数 2技术分 +2 黑马币 +6 收起 理由
袁梦希 + 2 很给力!
曾林魁 + 6

查看全部评分

回复 使用道具 举报
1,如何定义内部类
   把一个类放在另一个类的内部即可
  1.    public class Outer
  2. {
  3.         class Inner
  4.         {
  5.         }
  6. }
复制代码
2,内部类的划分:
            成员内部类: 非静态内部类
                         静态内部类
            匿名内部类
            局部内部类
成员内部类的意思是把这个类当做外部类的一个成员,等同于属性、方法、构造器的地位。
成员内部类是类成员,故可以同方法一样可以用public、protected、private修饰。
匿名内部类、局部内部类则不是类成员。

3,访问规则
非静态内部类可以访问外部类private成员。原因:在非静态内部类对象里,保存了一个它寄存的外部对象的引用。举例说明:
  1. public class Outer{
  2.         private int x = 10;//外部类属性 x
  3.         private int y = 100;//外部类属性 y
  4.         public Outer(){
  5.                 System.out.println("Outer"+"-->"+x);
  6.         }
  7.         class Inner{
  8.                 private int x = 12;//内部类成员 x
  9.             public Inner(){
  10.                         int x = 20; //内部类局部变量 x
  11.                         System.out.println("Inner"+"-->"+x);
  12.                         System.out.println("Inner"+"-->"+this.x);
  13.                         System.out.println("Inner"+"-->"+Outer.this.x);

  14.                         System.out.println(y);//当发生调用时,其实是有一个Outer.this引用
  15.                 }
  16.         }
  17.         public static void main(String args[]){
  18.                 new Outer().new Inner();

  19.         }
  20. }
复制代码
  1. ---------- 运行java程序 ----------
  2. Outer-->10
  3. Inner-->20
  4. Inner-->12
  5. Inner-->10
  6. 100
  7. 输出完成 (耗时 0 秒) - 正常终止
复制代码
结论:
1,
当在非静态内部类的方法内访问某个变量时(以 y为例),系统优先在该方法内产值是否存该名字的局部
变量,如果存在该名字的局部变量,就使用该变量;如果不存在,则到该方法所在内部类中
查找是否存在该名字的属性,存在则使用该属性;不存在则到内部类所在的外部类中查找是
否存在该名字的数组,存在则使用。如果还是没找到,则编译报错。
2,当外部类属性、内部类属性与内部类方法的局部变量同名(如 x),则可以通过使用this
、外部类名.this来指定调用谁的x。当不指定时参考第一条

写在后面的

由于时间有限,还有很多细节没写。推荐一个本书《疯狂java讲义》第六章 面向对象 内部类。讲的很详细。就是给的程序太啰嗦。
我写的例子就是简单粗暴了点,主要是方便说明问题。
建议:
把继承 构造器  this super引用好好看懂。



评分

参与人数 1技术分 +2 收起 理由
袁梦希 + 2 神马都是浮云

查看全部评分

回复 使用道具 举报
对于非静态内部类可理解为外部类的一个实例成员,要使用它必须有一个外部类的实例对象 所以先new Outer(),再通过通过外部类实例调用内部类的构造器即new Outer().new Inner()
匿名内部类相当一次性筷子,只出现一次,用完就丢了,很难再在其他地方通过引用变量再使用,因为匿名类创建实例时都是直接new出来的,没有引用变量的定义。常见的是在GUI中使用匿名内部类充当监听器如:addXXXlistener(/*后面直接创建匿名内部类的实例*/ new XXXListenner({//*匿名内部类的类体,这里是抽象方法的实现*/
})/*一个匿名内部类对象创建完成,它的活动范围也仅限于此,不能再在其他地方使用*/);

评分

参与人数 1技术分 +1 收起 理由
袁梦希 + 1 赞一个!

查看全部评分

回复 使用道具 举报
这时我写博客总结的内部类,很详细,楼主可以看看:
http://blog.sina.com.cn/s/blog_8f5022200101a7om.html
回复 使用道具 举报
楼主你好,如果帖子没问题了,那么请把帖子的类型改为“已解决”。如果不会改,请看我的个性签名
回复 使用道具 举报
袁梦希 发表于 2013-5-30 10:46
楼主你好,如果帖子没问题了,那么请把帖子的类型改为“已解决”。如果不会改,请看我的个性签名 ...

好的谢谢
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马