Java内部类和匿名内部类的用法

    【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/51981163
一、内部类: 
      (1)内部类的同名方法
        内部类可以调用外部类的方法,如果内部类有同名方法必须使用"OuterClass.this.MethodName()"格式调用(其中OuterClass与MethodName换成实际外部类名及其方法;this为关键字,表示对外部类的引用);若内部类无同名方法可以直接调用外部类的方法。
        但外围类无法直接调用内部类的private方法,外部类同样无法直接调用其它类的private方法。注意:内部类直接使用外部类的方法与该方法的权限与是否static无关,它取决于内部类是否有同名方法。
package innerclass;
public class OuterClass {private void outerMethod() {System.out.println("It's Method of OuterClass");}public static void main(String[] args) {OuterClass t = new OuterClass();OuterClass.Innerclass in = t.new Innerclass();in.innerMethod();}class Innerclass {public void innerMethod() {OuterClass.this.outerMethod();// 内部类成员方法与外部类成员方法同名时,使用this调用外部类的方法outerMethod();// 内部类没有同名方法时执行外部类的方法}private void outerMethod() {System.out.println("It's Method of Innerclass");}}
}

     输出结果为:
It's Method of OuterClass
It's Method of Innerclass
    (2)内部类访问外部类的变量必须声明为final
      方法中的局部变量,方法结束后这个变量就要释放掉,final保证这个变量始终指向一个对象。
   首先,内部类和外部类其实是处于同一个级别,内部类不会因为定义在方法中就会随着方法的执行完毕而跟随者被销毁。问题就来了,如果外部类的方法中的变量不定义final,那么当外部类方法执行完毕的时候,这个局部变量肯定也就被GC了,然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话,由于final所修饰的值始终无法改变,所以这个变量所指向的内存区域就不会变。
     注意,若使用JDK1.8,方法中内部类的方法是可以直接访问外部类的方法的局部变量,并且不需要声明为final类型。
public class OuterClass {int num1 = 0;// 成员变量private void outerMethod() {int num2 = 0;// 方法内的局部变量class Innerclass_1 {public void innerMethod() {System.out.println(num1);// 方法中内部类的方法,可以正常访问外部类的成员变量System.out.println(num2);// JDK1.8以前,方法中内部类的方法,不能直接访问外部类的方法的局部变量,必须声明为final}}}
}
如果使用JDK1.8以前的版本,Eclipse会出现如下错误提示:

    (3)内部类的实例化
内部类实例化不同于普通类,普通类可以在任意需要的时候实例化,而内部类必须在外层类实例化以后方可实例化,并与外部类建立关系
     因此在外部类中的非static方法中,是可以实例化内部类对象
    private void outerMethod() {System.out.println("It's Method of OuterClass");Innerclass in = new Innerclass();//在外部类的outerMethod方法中实例化内部类是可以啊}

但在static方法中,就要注意啦!!!!不能在static方法中直接new内部类,否则出现错误:

     No enclosing instance of type OuterClass is accessible. Must qualify the allocation with an enclosing instance of type OuterClass (e.g. x.new A() where x is an instance of OuterClass).
     这是因为静态方法是在类实例化之前就可以使用的,通过类名调用,这时动态内部类都还没实例化呢,怎么用,总不能调用一个不存在的东西吧。
     如果想在Static方法中new内部类,可以把内部类声明为Static

public class OuterClass {private void outerMethod() {System.out.println("It's Method of OuterClass");}public static void main(String[] args) {Innerclass in = new Innerclass();in.innerMethod();}static class Innerclass {//把内部类声明为staticpublic void innerMethod() {System.out.println("It's Method of innerMethod");}}}

当然,一般不使用static的方式,而是推荐这种方法:x.new A() ,其中 x是外部类OuterClass的实例,A是内部类Innerclass

package innerclass;
public class OuterClass {private void outerMethod() {System.out.println("It's Method of OuterClass");}public static void main(String[] args) {OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式in.innerMethod();}class Innerclass {public void innerMethod() {System.out.println("It's Method of innerMethod");}}
}

x.new A() ,其中 x是外部类OuterClass的实例,A是类部类Innerclass,当然可以拆分如下,这样就显然很明白啦:

    public static void main(String[] args) {OuterClass out = new OuterClass();//外部实例OuterClass.Innerclass in = out.new Innerclass();//外部实例.new 外部类in.innerMethod();}

    (4)什么情况下使用内部类
     典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外层类的对象。所以你可以认为内部类提供了某种进
入其外层类的窗口。
    使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外层类是否已经继承了某个(接口的)实
现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角
度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
   (5)在静态方法中实例化内部类例子:(内部类放在静态方法中)
package javatest2;
public class JavaTest2 {public static void main(String[] args) {class Boy implements Person {public void say() {// 匿名内部类自定义的方法saySystem.out.println("say方法调用");}@Overridepublic void speak() {// 实现接口的的方法speakSystem.out.println("speak方法调用");}}Person per = new Boy();per.speak();// 可调用per.say();// 不能调用}
}
interface Person {public void speak();
}

       per.speak()可调用,而per.say()不能调用,这时因为per是Person对象,要想调用子类的方法,可以强制向下转型为:((Boy) per).say();或者直接改为Boy per = new Boy();。从中可发现,要想调用内部类的自定义的方法,必须通过内部类的对象来调用。那么,匿名内部类连名字都没有,怎么调用内部类自定义的方法?

(二)匿名内部类
      匿名内部类也就是没有名字的内部类正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写,但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
关于匿名内部类还有如下两条规则:
    1)匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。
    2)匿名内部类不等定义构造器(构造方法),因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块,
    怎样判断一个匿名类的存在啊?看不见名字,感觉只是父类new出一个对象而已,没有匿名类的名字。
先看段伪代码

abstract class Father(){
....
}
public class Test{Father f1 = new Father(){ .... }  //这里就是有个匿名内部类
}

一般来说,new 一个对象时小括号后应该是分号,也就是new出对象该语句就结束了。但是出现匿名内部类就不一样,小括号后跟的是大括号,大括号中是该new 出对象的具体的实现方法。因为我们知道,一个抽象类是不能直接new 的,必须先有实现类了我们才能new出它的实现类。上面的伪代码就是表示new 的是Father的实现类,这个实现类是个匿名内部类。
    其实拆分上面的匿名内部类可为:

class SonOne extends Father{...       //这里的代码和上面匿名内部类,大括号中的代码是一样的
}
public class Test{Father f1 = new SonOne() ;
}

     先看一个例子,体会一下匿名内部类的用法:
运行结果:eat something
    可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上
public class JavaTest2 {public static void main(String[] args) {Person per = new Person() {public void say() {// 匿名内部类自定义的方法saySystem.out.println("say方法调用");}@Overridepublic void speak() {// 实现接口的的方法speakSystem.out.println("speak方法调用");}};per.speak();// 可调用per.say();// 出错,不能调用}
}interface Person {public void speak();
}

这里per.speak()是可以正常调用的,但per.say()不能调用,为什么呢?注意Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。其实匿名内部类连名字都没有,你咋实例对象去调用它的方法呢?但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的speak方法,因此可以借助Person的对象去调用。

        若你确实想调用匿名内部类的自定义的方法say(),当然也有方法:
      (1)类似于speak方法的使用,先在Person接口中声明say()方法,再在匿名内部类中覆写此方法。
      (2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和speak()方法;代码修改如下:

public class JavaTest2 {public static void main(String[] args) {new Person() {public void say() {// 匿名内部类自定义的方法saySystem.out.println("say方法调用");}@Overridepublic void speak() {// 实现接口的的方法speakSystem.out.println("speak方法调用");}}.say();// 直接调用匿名内部类的方法}
}
interface Person {public void speak();
}

Java内部类和匿名内部类的用法相关推荐

  1. Java基础(内部类和匿名内部类的用法)

    Java内部类和匿名内部类的用法 一.内部类:       (1)内部类的同名方法         内部类可以调用外部类的方法,如果内部类有同名方法必须使用"OuterClass.this. ...

  2. Java内部类(匿名内部类)

    Java内部类(匿名内部类) 一.内部类 二.静态内部类 三.成员内部类 四.局部内部类(了解即可) 五.匿名内部类(重要) 一.内部类 1.概述 内部类就是一个定义在一个类里面的类,里面的类可以理解 ...

  3. Java 内部类之匿名内部类

    1. 匿名内部类概述 匿名内部类 :是内部类的简化写法.他是一个隐含了名字的内部类.开发中,最常用到的内部类就是匿名内部类了. 2. 书写格式 new 类名或者接口名() { 重写方法; }; 包含了 ...

  4. Java 内部类和匿名内部类

    1.内部类 一个类定义在另外一个类的内部,这个该类就被称为内部类.内部类分为成员内部类(定义在外部类的成员位置)和局部内部类(定义在外部类的方法里面). (1) 成员内部类 class Outer { ...

  5. Java 内部类 和 匿名内部类

    From:https://www.cnblogs.com/geeksongs/p/9836154.html 一,内部类 其实内部类是十分简单的,我们根据其字里行间的意义就可以知道内部类应该是一个类当中 ...

  6. java匿名内部类runnable_Java内部类:匿名内部类(四)

    Java内部类分为4个部分进行阐述,分别为概览.成员内部类.局部内部类和匿名内部类. 在本文中是Java内部类的匿名内部类,主要讲述匿名内部类的概念.匿名内部类的好处.匿名内部类的使用前提.和匿名内部 ...

  7. java内部格式_详解java内部类的访问格式和规则

    详解java内部类的访问格式和规则 1.内部类的定义 定义一个类来描述事物,但是这个事物其中可能还有事物,这时候在类中再定义类来描述. 2.内部类访问规则 ①内部类可以直接访问外部类中的成员,包括私有 ...

  8. java中局部内部类_Java内部类详解--成员内部类,局部内部类,匿名内部类,静态内部类...

    一.内部类基础 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的内部类一般来说包括这四种:成员内部类.局部内部类.匿名内部类和静态内部类.下面就先来了解一 ...

  9. java接口匿名内部类_JAVA技术分享:接口,内部类,匿名内部类

    原标题:JAVA技术分享:接口,内部类,匿名内部类 接口: 接口中只有抽象方法,而没有非抽象方法 特点: 1:接口不能被实例化,只能通过多态的形式,让子类实例化 2:接口的子类 A:可以是具体类,但是 ...

最新文章

  1. Centos7 搭建 k8s 环境教程,一次性成功
  2. C++ Opengl 显示TGA文件和扩展名源码
  3. 深度学习搞CV?图像数据不足咋办?看这里!
  4. cheerio api
  5. python ljust 库_Python知识精解:str ljust()方法
  6. Qt文档阅读笔记-Qt Core的官方解析
  7. 如何将namedtuples序列化为JSON
  8. 牛客网——找出直系亲属
  9. 拼多多店铺的先用后付|盛天海科技
  10. 计算机一级插入页码,计算机一级WPS辅导:用WPSOffice2007插入特色页码
  11. 基础训练:龟兔赛跑预测
  12. 详细分析MySQL的日志(一)本文原创地址:博客园骏马金龙https://www.cnblogs.com/f-ck-need-u/p/9001061.html
  13. ARM到底是冯诺依曼结构还是哈佛结构?
  14. 数据结构实验报告—栈和队列
  15. 【c++并发编程】pthread_create的使用
  16. C++各种睡眠的区别
  17. 如何选择适合你的兴趣爱好(四十八),手风琴
  18. dnf mysql_CentOS7使用dnf安装mysql的方法
  19. 2021 年8月份最新数据库排行榜出炉
  20. 从软件公司的企业文化浅谈什么是管理能力

热门文章

  1. 我的世界挖钻石的最佳方式
  2. 毕业来北京要做的1000件事,第三十九,医治自己的错失恐惧症
  3. php发送邮件,邮件内容包含HTML标签
  4. jQuery的replaceWIth()与replaceAll()
  5. Android+webview+h5 拍照闪退问题
  6. java中堆和栈的区别!!!!
  7. [2008-NBA-视频直播]NBA常规赛
  8. 中国体育门户网新闻发布
  9. JACK的需求(一)【 测试用例】
  10. 「古人有瘾」“俗人”郑板桥:一个“中产”的奋斗史