什么是内部类?
顾名思义~就是定义在一个类内部的类.
内部类的语法:
// 外部类
class Outer{
// 内部类
class Inner{}
}
内部类的特点:
(1) 内部类编译之后生成独立的 .class文件,文件名
Outer$Inner.class
(2) 内部类作为外部类的内部组成部分,内部类可以直接使用外部类的内容(属性和方法)
内部类的分类:
成员内部类 :(类比于成员变量)
(1) 位置:定义在类以内,方法以外的类
(2) 创建成员内部类的对象:需要依赖于外部类的对象
Outer o = new Outer();// 外部类的对象
Outer.Inner i = o.new Inner();// 创建成 员内部类对象
(3) 成员内部类可以直接访问外部类的私有成员
(4) 外部类类名.this 指向外部类当前对象
外部类类名.this.属性名 访问外部类当前属性
外部类类名.this.方法名(); 访问外部类当前方法
静态内部类 :(类比于静态变量)
(1) 位置:定义在类以内,方法以外,被static修饰的类
(2) 语法:
class Outer{
// 外部类的属性
// 外部类的方法
// 静态内部类
static class Inner{
// 静态内部类的属性
// 静态内部类的方法
}
}
(3) 静态内部类中既可以定义非静态成员也可以定义静态成员
(4) 创建静态内部类对象只需要依赖于外部类类名即可:
Outer.Inner i = new Outer.Inner();
(5) 访问静态内部类中静态成员时可以直接通过外部类类名.内部类类名.静态属性名(实参);
(6) 静态内部类中只能访问外部类的静态成员,不能直接访问非静态的成员
局部内部类 :(类比于局部变量)
(1) 位置:定义在方法以内的类
(2) 语法:
class Outer{
// 属性
// 成员方法
修饰符 返回值类型 方法名(形参列表){
// 方法的实现部分
// 局部内部类
class Inner{
// 属性
// 成员方法
}
}
}
(3) 局部内部类对象的创建需要在定义它的位置后面进行使用;
不能超过所在方法的 } 结束位置
(4) 局部内部类可以直接访问外部类的成员变量(私有的也可以)
(5) 局部内部类可以访问所在方法内部的局部变量,但是被局部内部类访问的局部变量;
需要被 final修饰(只允许使用,不允许改变),而且对局部变量加 final;
从jdk8.0版本自动默认添加,此语法被称为"语法糖".
匿名内部类 :(特殊局部内部类且无名)
(1) 特点:
a. 必须实现一个接口或是继承一个类
b. 基于匿名内部类只能创建该类的一个对象
c. 匿名内部类的定义和对象的创建一起完成
(2) 语法:
interface IA{
void m1();
}
匿名内部类可以基于接口进行完成实现类的定义:
IA ia = new IA(){
// 接口中方法的实现部分
public void m1(){}
}; // 分号不能省略
(3) 匿名内部类的优缺点:
a. 优点:简化代码,利用匿名内部类简化接口实现类的定义及对象创建
b. 缺点:可读性太低
Lambda表达式:
对匿名内部类的进一步简化,只能应用在函数式接口上(接口中有且只有一个抽象方法)
应用场景:接口中有且只有一个抽象方法时,利用Lambda表达式完成接口的实现
语法:
接口名 引用名 = (数据类型 参数名,数据类型 参数 名2)->{
// 方法的实现部分
};
基本语法:
a.没有参数、没有返回值
接口名 引用名 = ()->{
// 方法的实现部分
};
注意:如果实现部分有且只有一行语句时,{}可 以省略
b.有参数、没有返回值
接口名 引用名 = (数据类型 参数名,数据类型 参数名)->{
// 方法的实现部分
};
注意:()中的参数数据类型可以省略,编译器根据接口中方法参数类型自行推断
c.有参数、有返回值
接口名 引用名 = (参数名,参数名2)->{
// 方法实现部分
return 结果;
};
注意:如果{}中有且只有一行return语句时,将{}和return都省略
interface IA{
int m1(int n,int m);
}
IA ia = (n,m)->n+m; // 可读性差