Java匿名类

匿名内部类

  • 概念:即内部类的简化写法
  • 前提:存在一个类(可以是具体类也可以是抽象类)或接口
  • 格式:new 类名或接口名{重写的方法}
  • 本质:创建的是继承了类或实现了接口的子类匿名对象。

内部类

匿名类是内部类,首先看一下什么是内部类。根据内部类的不同位置,可将内部类分为:

  • 成员内部类
  • 局部内部类(位于外部类方法内)
1
2
3
4
5
6
7
8
9
10
class C{

//成员内部类
class B{}

public void show{
//局部内部类
class D{}
}
}

1. 成员内部类的访问格式:C.B b = new C().new B()
实际开发中,常将内部类设为私有成员以保护数据安全。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class C{

private class B{
public void methodB(){}
}

public void method(){
B b = new B();
b.methodB();
}
}

通过
C c = new C();
C.method();
来访问内部类函数成员。

或者,将内部类设置为静态类。 静态内部类在访问外部类成员时,只能访问外部类的静态成员。
private让数据更安全,static让数据访问更方便

1
2
3
4
5
6
7
8
9
10
11
12
class Outer{
public int num = 10;
class Inner{
public int num = 20;
public void show(){
int num = 30;
System.out.println(num);//访问本方法的num=30
System.out.println(this.num);//访问Inner类的num=20
System.out.println(Outer.this.num); //添加外部类对象,访问外部类Outer的num=10
}
}
}

2. 局部内部类
可以直接访问外部类的成员。 局部内部类访问的外部变量必须定义为final或static类型。

内部类和外部类其实是处于同一级别的,局部内部类不会因为方法的执行完毕而销毁。那么问题就来了:

  • 如果外部类的方法中的变量不定义为final,当外部类方法执行完毕的时候,这个变量就被销毁了。 然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。 【在多线程工作时经常出现】如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话final修饰的值始终无法改变,这个变量所指的内存区域就不会改变。

匿名内部类

  • 概念:即内部类的简化写法
  • 前提:存在一个类(可以是具体类也可以是抽象类)或接口
  • 格式:new 类名或接口名{重写的方法}
  • 本质:创建的是继承了类或实现了接口的子类匿名对象。
1
2
3
4
5
6
7
8
9
10
11
12
匿名类的声明是由java编译器自动派生一个类实例创建表达式。
匿名类永远不能是抽象的。
匿名类总是隐式的final。
匿名类总是一个内部类,并且不能使static。
在所有的情况下,匿名构造函数的throws语句必须列出所有的检查异常。包括父类构造函数显示调用语句跑出的和匿名类的实例初始化或者变量初始化抛出的异常。

实际使用的时候要注意:
1. 使用匿名类时,我们必须是继承一个类或者实现一个接口。但二者不能兼得,同时也只能继承 _一个_ 类或实现 _一个_ 接口。
2. 匿名类不能定义构造函数
3. 匿名类中不能存在任何的静态成员变量或静态方法。
4. 匿名类是局部内部类,所以局部内部类的所有限制对匿名类同样生效。
5. 匿名类不能是抽象的,必须要实现继承类或接口的所有抽象方法。

匿名类的语法:

1
2
3
4
5
Runnable hello = new Runnable(){ //1.new操作符; 2.接口名称 3. ()中构造函数的参数列表。
public void run(){ //4. 匿名类的结构
System.out.prinln("hello");
}
}

访问权限:

  • 外部class里的字段
  • 不能访问外部类的本地变量,除非是final
  • 如果内部类的名称与外部能访问的名称相同,就近原则。
  • 不能定义静态初始化代码块
  • 不能在匿名类里定义接口
  • 不能再匿名类里定义构造函数

匿名类方法的访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
方法1:直接在new 匿名类后边加.method()。这样访问如果方法多了调用很麻烦

new D(){
@Override
public void method(){}
}.method();

方法2:通过创建对象来访问,多态思维
D d = new D(){
@Override
public void method(){}
}
d.method();

匿名类在开发中,一般是方法参数为接口的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
interface D{
void showD();
}

class B{
//参数为接口对象
public void show(D d){
d.showD();
}
}

public class niming{
public static void main(String[] args){
B b = new B();
b.show(new D(){
@Override
public void showD(){
...
}
});
}
}