内部类
1、内部类的概念
(1) 定义在一个类内部的类称为内部类
//外部类class MyClass{
//内部类
class Inner{
}
}
2、内部类的特点:
(1) 内部类在编译之后会生成对应的 .class文件。
外部类名$内部类名.class
(2) 内部类是作为外部类的组成部分,可以直接使用外部类的属性和方法。
3、内部类的分类
(1) 成员内部类
(2) 静态内部类
(3) 局部内部类
(4) 匿名内部类
4、成员内部类(类比实例变量,属于对象)
(1) 位置:定义在类以内,方法以外
class MyClass{
//成员内部类
class Inner{
int m = 8; //成员内部类的方法
public void method(){
}
}
}
(2) 成员内部类对象的创建,依赖于外部类对象创建
//创建外部类对象
MyClass mc = new MyClass();
//成员内部类基于外部类的对象创建对象
MyClass.Inner in1 = new MyClass().new Inner();
MyClass.Inner in2 = mc.new Inner();
(3) 成员内部类可以直接访问外部类的属性和方法,私有也可以。
(4) 外部类类名.this :指向外部类当前对象
外部类类名.this.属性名:访问外部类属性
5、静态内部类(类比静态成员变量)
(1) 位置:定义在类以内方法以外,被static修饰
(2) 静态内部类对象的创建:依赖于外部类类名创建
Outer.Inner inner = new Outer.Inner();
(3) 访问静态内部类的静态成员可以直接通过类名访问:
Outer.Inner.静态属性名
Outer.Inner.静态方法名(实参);
(4) 静态内部类中只能访问外部类的静态成员,其他都访问不了,属于对象。
6、局部内部类(类比局部变量)
(1) 位置:定义在方法以内
(2) 局部内部类对象的创建,需要在定义它的方法内部及定义位置之后完成对象的创建。
(3) 局部内部类可以直接访问外部类的成员。
(4) 局部内部类可以访问所在方法内部的局部变量,但是局部变量必须被final修饰,jdk8.0开始自动将局部内部类访问的局部变量加final。(语法糖)
class Outer{
int a = 1;
public void m1(){
System.out.println("外部类的成员方法");
int m = 9; //局部变量
//局部内部类:定义在方法内
class Inner{
int n = 5; //实例成员变量
public void method(){
System.out.println("局部内部类的成员方法"); System.out.println(m);
//m = 10; 不可以
}
}
Inner inner = new Inner();
System.out.println(inner.n);
inner.method();
}
}
7、匿名内部类
(1) 匿名内部类:没有自己类名的类
(2) 特点:
a. 必须实现一个接口或是继承一个父类。
b. 基于匿名内部类,只能创建该类的一个对象。
c. 匿名内部类的定义和对象的创建一起完成。
interface IA{
void m1();
}
匿名内部类实现IA接口,同时完成对象的创建
就是个是接口的实现类
IA ia = new IA(){
@Override
public void m1(){
System.out.println("m1实现了");
}
}; //不要忘记分号
(4) 匿名内部类优缺点:
a. 缺点:可读性差
b. 优点:简化代码,利用匿名内部类完成接口实现类的定义和对象的创建。
Lambda表达式
(1) Lambda表达式:对匿名内部类进行进一步简化。
(2) 应用场景:只能应用在函数式接口中,接口中有且仅有一个抽象方法。
通常我们会在接口上加上一个**@FunctionalInterface**注解,标记该接口必须是满足函数式接口。
(3) 语法:
接口名 引用名 = (形参列表)->{ //方法的实现部分};
(4) 基本应用
(1)没有返回值、没有参数
接口名 引用名 = ()->{
//方法实现部分;
};
注意:如果{}只有一行语句,{}可以省略,但是不建议,可读性差。
(2)有参数、没有返回值
接口名 引用名 = (变量名,变量名)->{
//方法实现部分
};
(3)有参数、有返回值
接口名 引用名 = (参数)->{
return 返回值;
};
注意:如果{}里面只有一条return语句,则{}与return一同省略。
Lambda表达式的终极省略写法
- 参数类型可以省略不写
- 如果只有一个参数,参数类型可以忽略,同时()也可以忽略。
- 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!如果该行代码为return语句,必须省略return不写,同时也必须省略“;”不写。
Arrays.sort(arr,(Integer o1, Integer o2) -> {
return o1 - o2;
});
//省略后、、、
Arrays.sort(arr,(o1, o2) ->
o1 - o2
);