【50】java 匿名内部类剖析
匿名内部类介绍:
匿名内部类也就是没有名字的内部类
正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
匿名内部类的声明格式如下:
new ParentName(){
...// 内部类的定义
}
匿名内部类的使用场景:
.只用到类的一个实例 。 
·类在定义后马上用到。 
·类非常小(SUN推荐是在4行代码以下) 
·给类命名并不会导致你的代码更容易被理解。
匿名内部类的使用原则:
·匿名内部类不能有构造方法。 
·匿名内部类不能定义任何静态成员、静态方法。 
·匿名内部类不能是public,protected,private,static。 
·只能创建匿名内部类的一个实例。 
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。 
·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
匿名内部类的集中用法:
A、继承式的匿名内部类
public class Car {
public void drive(){
System.out.println("Driving a car!");
}
public static void main(String[] args) {
Car car = new Car(){
public void drive() {
System.out.println("Driving another car!");
}
};
car.drive();
}
}
结果输出了:Driving another car! Car引用变量不是引用Car对象,而是Car匿名子类的对象。
B、接口式的匿名内部类。
interface Vehicle {
public void drive();
}
class Test{
public static void main(String[] args) {
Vehicle v = new Vehicle(){
public void drive(){
System.out.println("Driving a car!");
}
};
v.drive();
}
}
上面的代码很怪,好像是在实例化一个接口。事实并非如此,接口式的匿名内部类是实现了一个接口的匿名类。而且只能实现一个接口。
C、参数式的匿名内部类。
class Bar{
void doStuff(Foo f){
f.foo();
}
}
interface Foo{
void foo();
}
class Test{
static void go(){
Bar b = new Bar();
b.doStuff(new Foo(){
public void foo(){
System.out.println("foofy");
}
});
}
}
注意事项
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2、匿名内部类中是不能定义构造函数的。
3、匿名内部类中不能存在任何的静态成员变量和静态方法。
4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
使用的形参为何要为final:
“这是一个编译器设计的问题,如果你了解java的编译原理的话很容易理解。 
首先,内部类被编译的时候会生成一个单独的内部类的.class文件,这个文件并不与外部类在同一class文件中。
public void dosome(final String a,final int b){
  class Dosome{public void dosome(){System.out.println(a+b)}};
  Dosome some=new Dosome();
  some.dosome();
}
从代码来看好像是那个内部类直接调用的a参数和b参数,但是实际上不是,在java编译器编译以后实际的操作代码是
class Outer$Dosome{
  public Dosome(final String a,final int b){
  this.Dosome$a=a;
  this.Dosome$b=b;
}
  public void dosome(){
  System.out.println(this.Dosome$a+this.Dosome$b);
}
}}  
内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。 
这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。”
(简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变)
匿名内部类初始化:
我们一般都是利用构造器来完成某个实例的初始化工作的,但是匿名内部类是没有构造器的!那怎么来初始化匿名内部类呢?使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果。
public class OutClass {
    public InnerClass getInnerClass(final int age,final String name){
        return new InnerClass() {
            int age_ ;
            String name_;
            //构造代码块完成初始化工作
            {
                if(0 < age && age < 200){
                    age_ = age;
                    name_ = name;
                }
            }
            public String getName() {
                return name_;
            }
            public int getAge() {
                return age_;
            }
        };
    }
    public static void main(String[] args) {
        OutClass out = new OutClass();
        InnerClass inner_1 = out.getInnerClass(201, "chenssy");
        System.out.println(inner_1.getName());
        InnerClass inner_2 = out.getInnerClass(23, "chenssy");
        System.out.println(inner_2.getName());
    }
}
欢迎入群:
公众号IT面试题汇总讨论群
如果扫描不进去,加我微信(rdst6029930)拉你。
扫我微信二维码加我
欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧,都是干货!
微信订阅号二维码如下:
参考: 
http://baike.baidu.com/view/7942850.htm 
http://android.blog.51cto.com/268543/384844 
http://www.cnblogs.com/chenssy/p/3390871.html 
http://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html
【50】java 匿名内部类剖析的更多相关文章
- Java基础-使用JAVA代码剖析MD5算法实现过程
		
Java基础-使用JAVA代码剖析MD5算法实现过程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
 - #随笔之java匿名内部类
		
随笔之java匿名内部类 从今天起开始每日一篇技术博客,当然这只是我当天所学的一些随笔,里面或多或少会有理解不当的地方,希望大家多多指教,一起进步! 在讲匿名内部类之前,先讲讲内部类的一些概念. 1. ...
 - 细谈 Java 匿名内部类 【分别 使用 接口 和 抽象类实现】
		
1.前言 匿名内部类是什么东西? 没有名字的内部类就是匿名内部类. 什么场景使用? 匿名内部类适合创建那种只需要一次使用的类. 这是个很有用的东西,可想而知,如果不使用匿名内部类,哪些只需要使用一次的 ...
 - 从一开始,说出事java匿名内部类
		
java内部类.匿名类原本以为它们的使用已经很滑, 成绩, 就在昨天晚上12指向时钟发生重大事故.事故的严重程度再说吧,那是因为我没有睡一晚睡眠. 那以下先用一段模拟代码来描写叙述下我出现的问题的: ...
 - (转)java匿名内部类详解
		
原文:http://android.blog.51cto.com/268543/384844/ 内部类是指在一个外部类的内部再定义一个类.类名不需要和文件夹相同. *内部类可以是静态static的 ...
 - 【Java学习笔记之二十六】深入理解Java匿名内部类
		
在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...
 - 【49】java内部类剖析
		
什么是内部类: 定义在其他类(outer class)中的类被称作内部类.内部类可以有访问修饰服,甚至可以被标记为 abstract 或 final. 内部类与外部类实例有特殊的关系,这种关系允许内部 ...
 - JAVA匿名内部类(Anonymous Classes)
		
1.前言 匿名内部类在我们JAVA程序员的日常工作中经常要用到,但是很多时候也只是照本宣科地用,虽然也在用,但往往忽略了以下几点:为什么能这么用?匿名内部类的语法是怎样的?有哪些限制?因此,最近,我在 ...
 - Java匿名内部类访问外部
		
匿名内部类访问外部局部变量必须是final修饰的,Java 1.8 会默认为其加上final 例子如下: public void send(String topicName, T obj) { Str ...
 
随机推荐
- 21 viewPager--- hzScrollView ----llContainer
			
结构: MainActivity.java package com.qf.day21_hsviewpagerfragment_demo5; import java.util.ArrayList; im ...
 - javascript之内置函数
			
1.常规函数 (1)alert函数:显示一个警告对话框,包括一个OK按钮. (2)confirm函数:显示一个确认对话框,包括OK.Cancel按钮. (3)escape函数:将字符转换成Unicod ...
 - 关于MT8127中sdk的编译出错问题
			
今天在看MTK提供的SDK编译文档,按照步骤做,结果出错了,文档如下: 2- Building an SDK for MacOS and Linux ------------------------- ...
 - 用API创建用户
			
DECLARE lc_user_name VARCHAR2(100) := 'PRAJ_TEST'; lc_user_password VARCHAR2(100) := 'Oracle123'; ld ...
 - Java基础---Java---IO流-----LineNumberReader方法及原理、自定义一个LineNumberReader、字节流、图片复制、mp3复制、
			
LineNumberReader 跟综行号的缓冲字符输入流,些类定义了setLineNumber(int)和getLineNumber(int),它们可分别用于设置和获取当前行号 import jav ...
 - 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数
			
本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...
 - markdown语法(看这张图就够了)
			
这是维基百科的一张图,基本就够用了 https://en.wikipedia.org/wiki/Markdown#Example
 - 【一天一道LeetCode】#119. Pascal's Triangle II
			
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...
 - 《java入门第一季》之tcp协议下的编程实现键盘录入数据不断地往服务器端发送数据案例
			
这里要封装通道流,封装键盘录入数据流. 同样地,还是两台电脑.一个客户端,一个服务器. 客户端代码: import java.io.BufferedReader; import java.io.Buf ...
 - Cocos2D旋转炮塔到指定角度(二)
			
增加如下代码到ccTouchesEnded方法中,就在你在导弹精灵上调用runAction之前: // Determine angle to face float angleRadians = ata ...