Java 内部类 匿名类 匿名内部类
以下均来源于网络整理
一、内部类
https://www.cnblogs.com/wfq9330/p/8760031.html
定义:根据创建位置的不同,分为成员的、方法的、匿名的。接口中的内部类叫做接口内部类。
理解:在类的内部创建,那就是类的一部分,跟属性、方法同级。这也就解释了为何能访问外部私有成员,我是你的一部分,我当然可以访问了。
1、成员内部类
class Outer { private int i = 1; class Inner { public void fun() {System.out.println("Outer I=" + i)} } }
2、方法内部类
class Outer{ private String test; public void fun() { final int i = 1; // 被方法内部类访问的局部变量必须被final修饰 class Inner { // 方法内部类 不能有访问修饰符,比如public public void print() { System.out.println("Method I=" + i + test); } } } }
3、匿名内部类
interface USB { public abstract void start() } class Outer{ public void fun() { final int i = 1; // 被匿名内部类访问的局部变量必须被final修饰 new USB(){ @Override public void start(){ System.out.println("local_var_i=" + i); } }.start(); } }
4、静态内部类
class Outer{ private int i = 1; static class Inner{ // 不能访问外部类的非静态成员 public void fun() { } } }
5、接口内部类
interface USB { class Inner { // 默认是public static,即可以直接new USB.Inner(); } }
二、匿名内部类
https://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html
匿名内部类也就是没有名字的内部类
正因为没有名字,所以匿名内部类只能使用一次,当然也就不能有构造器
但使用匿名内部类:必须继承一个父类或实现一个接口
使用匿名内部类课使代码更加简洁、紧凑,模块化程度更高。
内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到,所以匿名内部类作用大
1、匿名内部类的基本实现
abstract class Person { public abstract void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } }
运行结果:eat something
红色加粗的代码,就是匿名内部类,继承了 Person 类,却没有给出这个类的名字,直接实例化它并赋值给 p
如果不用匿名内部类,我们会这样写
abstract class Person { public abstract void eat(); } class Child extends Person { public void eat() { System.out.println("eat something"); } } public class Demo { public static void main(String[] args) { Person p = new Child(); p.eat(); } } 运行结果:eat something
先定义一个类,名字叫Child,用到的时候,Person p = new Child(); 用它的名字实例化它,然后赋值给 p,对比发现,定义匿名内部类,后面有大括号接类的方法,普通的实例化,没有大括号的内容
2、在接口上使用匿名内部类
interface Person { public void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } }
运行结果:eat something
3、Thread类的匿名内部类实现
public class Demo { public static void main(String[] args) { Thread t = new Thread() { public void run() { for (int i = 1; i <= 5; i++) { System.out.print(i + " "); } } }; t.start(); } } 运行结果:1 2 3 4 5
4、Runnable接口的匿名内部类实现
public class Demo { public static void main(String[] args) { Runnable r = new Runnable() { public void run() { for (int i = 1; i <= 5; i++) { System.out.print(i + " "); } } }; Thread t = new Thread(r); t.start(); } } 运行结果:1 2 3 4 5
三、匿名类
我个人理解,一个没有名字的类--匿名类,必须依赖于一个现有的类中,才能存在,你在类外部定义一个匿名类,语法是通不过的,所以匿名类就是匿名内部类
链接:https://www.zhihu.com/question/49330534/answer/115478102
当你想使用一个类的protected 方法时,但是又不和这个类在同一个包下,你是没办法调用的。
这时候匿名类就派上用场了,你可以声明一个匿名类继承该类,并定义一个方法,在这个方法内使用super调用你想调用的那个方法(其实你也可以写个类继承这个类,就能调用父类的protected方法了,但是匿名类更简洁,因为你只想调用这个方法而已)
五、匿名对象与匿名内部类
匿名对象:没有名字的对象。
非匿名对象:
ClassName c=new ClassName();
c.run();
匿名对象:
new ClassName().run();
注意事项:
1、当对象对方法仅进行一次调用的时候,就可以简化成匿名对象。
2、两个匿名对象不可能是同一个对象。
3、一般不给匿名对象赋予属性值,因为永远无法获取到。
4、运行一次,直接就被回收掉了,节省内存空间。