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