java 匿名类详解

匿名内部类

1.匿名内部类不能有构造方法,
2.匿名内部类不能定义任何静态成员,方法和类。
3.匿名内部类不能使用public,protected,private,static。
4.只能创建匿名内部类的一个实例,只能够使用一次,不能重复使用
5.一个匿名内部类一定时在 new 后面,匿名内部类不能是抽象类,用其隐含实现一个接口或实现一个类,两者不可兼得,它必须实现继承的类或者实现的接口的所有的抽象方法
6.需要传参数时,若参数在匿名内部类中被使用,则该参数需要被声明为final。

创建方式:
  1. new 父类构造器(参数列表)|实现接口()    
  2.     {    
  3.      //匿名内部类的类体部分    
  4.     }  

package Basement;

class Bird{
	private String name;
	public Bird(){}
	public Bird(String name){
		this.name = name;
	}
	public String getName(){
		return this.name;
	}
	public void SetName(String name){
		this.name = name;
	}
	public int fly(){
		return 0;
	}
}

public class J8 {  //测试匿名内部类
	
	public static void main(String[] args) {
		
		J8 j8 = new J8();
		//方法调用创建,无参
		j8.test(new Bird(){                   //用方法来创建一个匿名类
			public int fly(){
				return 10000;
			}
			public String getName(){
				return "大雁";
			}
		});
                //方法调用创建,有参
		String a = "我";
		j8.test(new Bird(a){
			public int fly(){
				return 2;
			}
		});
		//方法return创建,有参
		Bird Parambird = j8.getBird("yellow");
		System.out.println(Parambird.getName());
		//方法return创建,无参
Bird Parambird1 = j8.getBird1("blue");System.out.println(Parambird1.getName());}public void test(Bird bird){System.out.println(bird.getName() + "能够飞" + bird.fly() + "米");}public Bird getBird(final String _name){ //有参,被使用的形参需要定义为final,不被使用的则不需要为finalreturn new Bird(_name){String name = _name;public String getName(){return name;}};}public Bird getBird1(final String _name){return new Bird(){String name = _name;public String getName(){return name;}};}}

结果:

大雁能够飞10000米
我能够飞2米
yellow
blue

注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.classouter$inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。

为什么必须要为final呢?

      首先我们知道在内部类编译成功后,它会产生一个class文件,该class文件与外部类并不是同一class文件,仅仅只保留对外部类的引用。当外部类传入的参数需要被内部类调用时,从java程序的角度来看是直接被调用:


public class OuterClass {  

    public void display(final String name,String age){  

        class InnerClass{  

            void display(){  

                System.out.println(name);  

            }  

        }  

    }  

}  

      从上面代码中看好像name参数应该是被内部类直接调用?其实不然,在java编译之后实际的操作如下:


public class OuterClass$InnerClass {  

    public InnerClass(String name,String age){  

        this.InnerClass$name = name;  

        this.InnerClass$age = age;  

    }  

    public void display(){  

        System.out.println(this.InnerClass$name + "----" + this.InnerClass$age );  

    }  

}  

       所以从上面代码来看,内部类并不是直接调用方法传递的参数,而是利用自身的构造器对传入的参数进行备份,自己内部方法调用的实际上时自己的属性而不是外部方法传递进来的参数。

       直到这里还没有解释为什么是final?在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。

      简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。

      故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。

附:匿名内部类简单小栗子
http://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值