目录
一、内部类的定义
类的五大成分:成员变量、成员方法、构造器、代码块、内部类。
内部类就是定义在一个类里面的类,里面的类可以理解为(寄生),外部类可以理解成(宿主)。
调用格式
外部类名.内部类名 对象名 = new 外部类名.内部构造器
二、内部类的使用场景
当一个事务的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以使用内部类来设计。
例如:定义一个汽车类,而这个汽车类中有一个发动机类,整个系统又需要去关心发动机的一些信息,这个发动机就是一个内部类
三、内部类的作用
- 内部类通常可以方便访问外部类的成员,包括私有的成员。
- 内部类提供了更好的封装性,内部类本身就可以用private、protected修饰,封装性可以做更多控制。
四、内部类的分类
-
静态内部类
静态内部类中可以直接访问外部类的静态成员,因为静态成员只有一份可以被共享访问。
静态内部类不可以直接访问外部类的实例成员,必须创建对象间接访问。
-
成员内部类
它是寄生在外部类的对象中,所以要先new外部对象再new内部对象。
静态内部类中可以直接访问外部类的静态成员,因为静态成员只有一份可以被共享访问。
静态内部类可以直接访问外部类的实例成员,因为先必须创建外部类对象才能有内部类对象。
面试例题:
public class Outclass {
private int heart = 150;
public class Inner{
//成员内部类
private int heart = 110;
public void show(){
int heart = 78;
//输出78
System.out.println();
//输出110
System.out.println(); //110是成员内部类Inner的对象变量。用this.heart访问当前对象
//输出150
//访问外部类对象
System.out.println(); //150是外部类的Outclass的对象变量,要通过外部对象来访问外部对象变量 Outclass.this.heart
}
}
}
-
局部内部类
五、匿名内部类
本质上是一个没有名字的局部内部类,定义在方法中、代码块中等。
作用:方便创建子类对象,最终目的为了简化代码编写
1、匿名内部类的创建:
public class Innear {
public static void main(String[] args) {
Animal a = new Animal() {
//通过匿名内部类,不需要创建子类对象完成
//通过匿名内部类创建的对象不是父类的对象,而是匿名内部类自己的对象
//匿名内部类的对象类型相当于是当前new的对象的子类类型
//它既是一个类又是一个对象
@Override
public void run() {
System.out.println("老虎跑的快");
}
};
a.run();
}
}
//class Dog extends Animal{
// //创建子类对象执行run方法
// @Override
// public void run() {
// System.out.println("老虎跑的快");
// }
//}
abstract class Animal{
public abstract void run();
}
2、匿名内部类的常见形式
public class TestDemo {
public static void main(String[] args) {
/*//接口不能创建对象,此处创建的是匿名类的对象
Swimming s = new Swimming() {
@Override
public void swim() {
System.out.println("学生仰泳");
}
};
go(s);*/
//简化写法:
//直接将整个对象传给go方法,匿名对象直接作为参数交给go方法,它代表的就是匿名对象s,相当于直接将s传进来
go(new Swimming() {
@Override
public void swim() {
System.out.println("学生仰泳");
}
});
}
public static void go(Swimming s){
System.out.println("开始");
s.swim();
System.out.println("结束");
}
}
3、匿名内部类的使用
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUITest {
public static void main(String[] args) {
//通过GUI编程理解匿名内部类
//1、创建窗口
JFrame win = new JFrame("登录界面");
//2、创建一个桌布
JPanel panel = new JPanel();
//3、将桌布添加到窗口
win.add(panel);
//4、创建一个按钮对象
JButton btn = new JButton("登录");
//匿名内部类实现点击功能
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(win,"点击成功");
}
});
//5、把按钮对象添加到桌布
panel.add(btn);
//6、展示窗口
win.setSize(400,300);
win.setLocationRelativeTo(null);
win.setVisible(true);
}
}
使用总结:
开发中不是我们主动去定义匿名内部类的,而是别人需要我们写或者我们可以写的时候才会使用。
匿名内部类的代码可以实现代码进一步的简化。
六、Lambda表达式
作用:简化匿名内部类的代码写法
public static void main(String[] args) {
//Swimming s = new Teacher();
//接口底线是不能创建对象,此处创建的是匿名内部类对象
Swimming s = new Swimming() {
@Override
public void swin() {
System.out.println("老司机游得快");
}
};
//用Lambda表达式简化
//只能简化函数式接口且只有一个抽象方法
Swimming s1 = () -> {
System.out.println("老司机游得快");
};
//匿名内部类对象做方法入参
go(new Swimming() {
@Override
public void swin() {
System.out.println("老司机游得快");
}
});
//简化
go(() -> {
System.out.println("老司机游得快");
});
}
public static void go(Swimming s){
System.out.println("开始");
s.swin();
}
}
@FunctionalInterface //函数式接口
interface Swimming {
void swin();
Lambda实战
Lambda简化Compaeator
Lambda简化按钮监听器
Lambda省略规则
Integer[] a = {11,22,33,44};
Arrays.sort(a, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
//简化1 Lambda
Arrays.sort(a,(Integer o1, Integer o2) -> {
return o1 - o2;
});
//简化2
Arrays.sort(a,(o1,o2) -> {
return o1 - o2;
});
//简化3
Arrays.sort(a,(o1,o2) -> o1 - o2
);