0

0

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

高洛峰

高洛峰

发布时间:2016-12-15 13:15:18

|

3117人浏览过

|

来源于php中文网

原创

一、内部类: 

(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)内部类的实例化

内部类实例化不同于普通类,普通类可以在任意需要的时候实例化,而内部类必须在外层类实例化以后方可实例化,并与外部类建立关系

因此在外部类中的非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 {//把内部类声明为static
        public 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();
}

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

(4)在静态方法中实例化内部类例子:(内部类放在静态方法中)

package javatest2;
public class JavaTest2 {
    public static void main(String[] args) {
        class Boy implements Person {
            public void say() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
            @Override
            public void speak() {// 实现接口的的方法speak
                System.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();。从中可发现,要想调用内部类的自定义的方法,必须通过内部类的对象来调用。那么,匿名内部类连名字都没有,怎么调用内部类自定义的方法?

LANUX蓝脑商务网站系统
LANUX蓝脑商务网站系统

LANUX V1.0 蓝脑商务网站系统 适用于网店、公司宣传自己的品牌和产品。 系统在代码、页面方面设计简约,浏览和后台管理操作效率高。 此版本带可见即可得的html编辑器, 方便直观添加和编辑要发布的内容。 安装: 1.解压后,更换logo、分类名称、幻灯片的图片及名称和链接、联系我们等等页面。 2.将dbconfig.php里面的数据库配置更改为你的mysql数据库配置 3.将整个文件夹上传至

下载

 

(二)匿名内部类

匿名内部类也就是没有名字的内部类正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写,但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
关于匿名内部类还有如下两条规则:
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() ;
}

先看一个例子,体会一下匿名内部类的用法:

1.png

运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上

public class JavaTest2 {
    public static void main(String[] args) {
        Person per = new Person() {
            public void say() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
            @Override
            public void speak() {// 实现接口的的方法speak
                System.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() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
 
            @Override
            public void speak() {// 实现接口的的方法speak
                System.out.println("speak方法调用");
            }
        }.say();// 直接调用匿名内部类的方法
    }
}
interface Person {
    public void speak();
}

更多内部类和匿名内部类的用法相关文章请关注PHP中文网!

相关专题

更多
php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

203

2025.12.31

php网站源码教程大全
php网站源码教程大全

本专题整合了php网站源码相关教程,阅读专题下面的文章了解更多详细内容。

111

2025.12.31

视频文件格式
视频文件格式

本专题整合了视频文件格式相关内容,阅读专题下面的文章了解更多详细内容。

123

2025.12.31

不受国内限制的浏览器大全
不受国内限制的浏览器大全

想找真正自由、无限制的上网体验?本合集精选2025年最开放、隐私强、访问无阻的浏览器App,涵盖Tor、Brave、Via、X浏览器、Mullvad等高自由度工具。支持自定义搜索引擎、广告拦截、隐身模式及全球网站无障碍访问,部分更具备防追踪、去谷歌化、双内核切换等高级功能。无论日常浏览、隐私保护还是突破地域限制,总有一款适合你!

93

2025.12.31

出现404解决方法大全
出现404解决方法大全

本专题整合了404错误解决方法大全,阅读专题下面的文章了解更多详细内容。

663

2025.12.31

html5怎么播放视频
html5怎么播放视频

想让网页流畅播放视频?本合集详解HTML5视频播放核心方法!涵盖<video>标签基础用法、多格式兼容(MP4/WebM/OGV)、自定义播放控件、响应式适配及常见浏览器兼容问题解决方案。无需插件,纯前端实现高清视频嵌入,助你快速打造现代化网页视频体验。

19

2025.12.31

关闭win10系统自动更新教程大全
关闭win10系统自动更新教程大全

本专题整合了关闭win10系统自动更新教程大全,阅读专题下面的文章了解更多详细内容。

15

2025.12.31

阻止电脑自动安装软件教程
阻止电脑自动安装软件教程

本专题整合了阻止电脑自动安装软件教程,阅读专题下面的文章了解更多详细教程。

6

2025.12.31

html5怎么使用
html5怎么使用

想快速上手HTML5开发?本合集为你整理最实用的HTML5使用指南!涵盖HTML5基础语法、主流框架(如Bootstrap、Vue、React)集成方法,以及无需安装、直接在线编辑运行的平台推荐(如CodePen、JSFiddle)。无论你是新手还是进阶开发者,都能轻松掌握HTML5网页制作、响应式布局与交互功能开发,零配置开启高效前端编程之旅!

3

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
php初学者入门课程
php初学者入门课程

共10课时 | 0.6万人学习

JavaScript基础精讲视频教程
JavaScript基础精讲视频教程

共36课时 | 7.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号