一、概念
1.内部类:在一个类的内部,定义一个完整类。
class Student{//外部类
class Inner{}//内部类
}
2.内部类编译之后会生成独立的.class文件,class文件命名方式为:外部类的类名$内部类的类名.class
3.内部类可以直接访问外部类的成员;通常将内部类作为外部类的组建构成。
4.内部类的分类:成员内部类、静态内部类、局部内部类、匿名内部类。
二、成员内部类(类比于 实例变量)
1.位置:定义在类以内,方法以外
2.成员内部类对象的创建:依赖于外部类的对象创建:
Outer o = new Outer();//创建外部类的对象
Outer.lnner i = o.new lnner();//创建成员内部类对象
3.成员内部类可以直接访问外部类属性和方法(私有的也可以访问)
4.外部类的类名.this:代表当前外部类的对象
外部类类名.this.属性:访问外部类的属性
外部类类名.this.成员方法(实参);:访问外部类的成员方法。
5.成员内部类不能定义静态成员(静态属性、静态的方法、静态代码块)
三、静态内部类(类比于:静态变量)【了解:阅读底层源码时认识】
1.位置:定义在类以内,方法以外,被static修饰的内部类
2.静态内部类中可以定义在实例变量和静态变量(方法也是一样)
3.创建静态内部类的对象:
外部类类名.静态内部类的类名 引用名 = new 外部类类名.静态内部类名();
4.访问静态内部类的静态成员:可以直接通过类名访问
外部类类名.静态内部类类名.静态属性:访问静态内部类的静态属性
外部类类名.静态内部类类名.静态方法(实参):访问静态内部类的方法
5.静态内部类只能直接访问外部类静态成员(静态属性和静态方法);静态内部类中不能直接访问外部类的非静态成员。
四、局部内部类(类比于:局部变量)
1.位置:方法在函数、方法以内
2.创建局部内部类的对象,需要在定义他的方法内部完成对象的创建,同时创建对象应该在类定义以后的位置(先定义类,在创建对象)
3.注意:局部内部类既可以定义在成员方法,也可以定义在静态方法。
4.局部内部类可以直接访问外部类成员方法(静态成员+非静态成员)
注意:此时距内部类定义在成员方法中情况。
5.局部内部类可以访问定义它的方法内部的局部变量,但是局部变量必须被final修饰,才能被局部内部类访问。
JDK8.0版本及以上,如果JVM检测一个方法中局部变量被此方法内部的局部内部类方法,jvm默认在此局部变量前面加final,此语法被称为语法糖。
public class TestLocalInner {
public static void main(String[] args) {
ClassA ca = new ClassA();
ca.outer_method(); } }
class ClassA{ int n = 3;
// 实例变量
static int f = 8;
public void outer_method() {
System.out.println("外部类的成员方法....");
int m = 6; // 局部变量
System.out.println("m="+m);
// 局部内部类 class Inner{
int a = 1;
public void inner_method() {
System.out.println("局部内部类的成员 方法...");
System.out.println("n="+n);
System.out.println("m="+m); // final } }
// 局部内部类的对象
Inner i =new Inner();
System.out.println(i.a);
i.inner_method(); }
public void test() {
// System.out.println("m="+m);
}
}
五、匿名内部类【根据自身能力可选内容-简化代码】
- 匿名内部类:是一种特殊的局部内部类
- 特点:
(1) 匿名内部类的定义必须继承一个父类或是实现一个接口
int a = 1; public void inner_method() { System.out.println(“局部内部类的成员 方法…”); System.out.println(“n=”+n); System.out.println(“m=”+m); // final } }// 局部内部类的对象 Inner i =new Inner(); System.out.println(i.a); i.inner_method(); }public void test() { // System.out.println(“m=”+m); } }
五、匿名内部类
1.匿名内部类:是一种特殊的局部类内部类
2.特点:
(1)匿名内部类的定义必须继承一个发骰子或是实现一个借口
(2)匿名内部类的定义和对象的创建一起完成;并且基于一个匿名内部类只能创建该类的一个对象
3.语法:
interface A{
void m1();
void m2();
}
//匿名内部类实现一个接口
IA ia = new IA(){
public void m1(){//方法实现的部分}
public void m2(){//方法实现的部分}
}
4.匿名内部类的优缺点:
(1)缺点:可读性不高
(2)优点:减少代码量,提高编码效率
六、Lambda表达式(JDK8.0开始有的应用)
1.Lambda表达式:实现函数式接口并完成对象的创建,是匿名内部类的简化形式。
2.应用场景:当接口中只有一个抽象方法时(静态方法、默认方法不在其中)
3.语法:
接口名 引用 = (形参列表)->{//方法实现部分};
语法解释:->是JDK8.0新引入一个语法符号
->左侧:Lambda表达式参数,即接口发放中形参部分
->右侧:指定Lambda表达式执行功能部分,即接口方法中实现部分。
(1)无参数、没有返回值
a.语法结构:接口名 引用 = ()->{//方法实现部分};
b.注意:当{}中只有一行语句时,{}可以省略,但是不建议。
public class TestAnonymousInner3 {
public static void main(String[] args) {
IC ic = () -> {
System.out.println("这是方法实现部 分...");
};
ic.mc(); } }interface IC{
void mc();
}
(2)带有参数、没有返回值
a. 语法结构:接口名 引用 = (数据类型 变量名,数据类型 变量)->{// 方法实现部分 };
b. 注意:Lambda表达式形参列表的数据类型可以省略,编译器自行推断。
public class TestAnonymousInner3 {
public static void main(String[] args) {
ID id = (a, s) ->{
System.out.println("a="+a);
System.out.println("s="+s); };
id.md(2, "小龙"); }
}interface ID{
void md(int a,String str); }
(3) 带有返回值:
a. 语法结构:接口名 引用名 = (形参列表)->{ return xxx; };
b. 注意:如果{}中只有一条 return 语句,return语句和{}可以省略(一 起)。
public class TestAnonymousInner3 {
public static void main(String[] args) {
IE ie = (int a,int b) -> { return a+b;
};
System.out.println(ie.me(3, 5));
// 如果Lambda{}实现中只有 return 语句
IE ie2 = (int a,int b) -> a+b;
System.out.println(ie2.me(3, 5));
}
}
interface IE{
int me(int a,int b);
}