顾名思义,这个类是匿名的。 用完之后,便隐去功名,像个扫地僧一样,默默地躲在深山中。 匿名内部类不仅没有名字,连class关键字都省略了,而且匿名内部类必须继承某个类或者实现某个接口,长这样:
new 父类(参数列表)|实现接口() { //匿名内部类的内部定义 }
我们举个栗子:
public abstract class Human { public abstract void walk(); }
这是一个抽象类,如果使用匿名内部类来继承它,它看起来是这样的:
public class AnonymousTest { public static void main(String[] args) { Human human = new Human(){ public void walk(){ System.out.println("AnonymousHuman can walk."); }; }; human.walk(); } }
简单粗暴,看起来像是一个本地内部类的简化版。 如果我们不使用匿名内部类会发生什么?
我们需要先创建一个类来继承这个抽象类:
public class Man extends Human { @Override public void walk() { System.out.println("Man can walk."); } }
然后再次使用这个类:
public class AnonymousTest { public static void main(String[] args) { Human human = new Man(); human.walk(); } }
因为一个单独的类往往放在一个单独的文件中,如果这个类只需要创建一个对象,就有点大材小用了。 从上面的栗子可以比较出匿名内部类的一个优点:类中只需要创建一个对象,比较简单方便。
再举个实际的栗子:
public class AnonymousTest { public static void main(String[] args) { Thread t = new Thread() { public void run() { for (int i = 0; i < 10; i++) { try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } } }; t.start(); } }
这里创建了一个继承自的匿名内部类,重写run方法,创建一个实例返回给t,然后调用run方法。 可以看出,一个匿名内部类中只能存在一个实例对象,因为new了一遍之后就不能再创建了。 你可能会觉得局部内部类已经很有限了。 为什么要有比本地内部类适用范围更小的匿名内部类呢? ,
你不明白这一点。 在Java的实际使用中,匿名内部类是非常有用的。 为什么要使用匿名内部类?
有时,我们创建的类只需要一个实例。 比如在多线程中,要使用多线程,一般都是先继承类或者实现接口,然后调用它的方法,每个任务一般都不一样。 每次都创建一个新类显然很难管理,因为每个类只使用一次然后就被丢弃了。 这时候使用匿名内部类就非常方便了。 不仅不需要管理一堆一次性的类,而且创建起来也简单粗暴。 就像上面的栗子一样,可以简化成这样:
public class AnonymousTest { public static void main(String[] args) { new Thread() { public void run() { for (int i = 0; i < 10; i++) { try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } } }.start(); } }
创建实例后直接调用run方法,简单粗暴。
匿名内部类不仅可以继承类,还可以实现接口,例如:
public class AnonymousTest { public static void main(String[] args) { new Thread(new Runnable() { public void run() { for (int i = 0; i < 10; i++) { try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } } }).start(); } }
当然,还有一些情况你必须使用内部类。 一个类只能继承自一个类。 如果一个类需要使用另一个包中另一个类的方法,但它已经继承自另一个类,那么此时一定不能使用。 没有内部类来解决它。
比如还有一个Woman(女人)类:
public class Woman { protected void dance(){ System.out.println("Woman can dance."); } }
这时候如果Man(男人)忍不住寂寞想跳舞(跳舞),怎么办呢? 继承Woman类? 显然不合逻辑,实现不了,因为已经继承了Human类,而我就是想跳舞,怎么办?
内部类的出现让这个问题变得非常简单:
public class Man extends Human { @Override public void walk() { System.out.println("Man can walk."); } public void dance(){ new Woman(){ public void manDance(){ super.dance(); } }.manDance(); } }
因为在不同的包下,不能直接使用Woman的dance方法,而是可以通过内部类继承,从而调用方法,然后放到Man的方法中,这样Man也可以像Woman一样跳舞:
public class AnonymousTest { public static void main(String[] args) { Man human = new Man(); human.walk(); human.dance(); } }
当然,使用匿名内部类还是有很多限制的:
1、匿名内部类必须继承一个类或实现一个接口,但不能两者兼有,只能继承一个类或实现一个接口。
2.匿名内部类不能定义构造函数。
3、匿名内部类中不能有任何静态成员变量和静态方法。
4、匿名内部类是特殊的局部内部类,所以局部内部类的所有限制对匿名内部类同样有效。
5. 匿名内部类不能是抽象的,它必须实现继承类或实现的接口的所有抽象方法。
那么问题来了,如何初始化一个匿名内部类呢? 毕竟,匿名内部类不能有构造函数。
当然,首先还是可以使用初始化块来实现,像这样:
public class AnonymousTest { public static void main(String[] args) { Human human = new Human() { private String name; { name = "human"; } @Override public void walk() { System.out.println(name + " walk."); } }; human.walk(); } }
但是这样显然比较死板,不够灵活,不能接受外部参数,那么如何灵活使用呢? 别着急,办法总是比问题多,还是有办法解决的:
public class AnonymousTest { public static void main(String[] args) { Human human = new AnonymousTest().getHumanInstance("Frank"); human.walk(); } public Human getHumanInstance(final String name){ return new Human() { private String nameA; { nameA = name; } @Override public void walk() { System.out.println(nameA + " walk."); } }; } }
这里,初始化块用于初始化匿名内部类。 注意,匿名内部类如果需要使用外部参数或者变量,一定要用final修饰,因为内部类使用的其实是参数的拷贝,而不是参数本身。 它明确表示参数是不可变的,编译器会要求使用final关键字来修饰需要使用的变量。
至此匿名内部类讲解完毕,欢迎大家继续关注!
以上就是Java内部类详解——匿名内部类详解内容。 更多关于Java匿名内部类的内容,请关注脚本之家其他相关文章!