一.内部类概述
- 内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)。
public class People{ // 内部类 public class Heart{ } }
内部类的使用场景
- 当一个事物的内部,还有一个部分需要一个完整的结构进行描述时,而这个内部的完整结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计。
内部类的作用
- 内部类通常可以访问外部类的成员,包括私有的成员。
- 内部类提供了更好的封装,内部类本身就可以用private,protected等修饰,封装性可以做更多控制。
- 内部类属于类的5大成分之一,外部类它只能用public或者缺省,外部类不能用private修饰。
- Java设计类的目的就是与现实世界进行对接,因为现实世界也有内部和外部。
内部类的分类
- 静态内部类
- 成员内部类(非静态内部类)
- 局部内部类
- 匿名内部类
二.静态内部类
什么是静态内部类
- 有static修饰,属于外部类本身。
- 它的特点和使用普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已。
静态内部类创建对象的格式:
- 格式:外部类名.内部类名 对象名 = new 外部类名.内部类构造器();
1.静态内部类中是否可以直接访问外部类的静态成员?
- 静态内部类可以直接访问外部类的静态成员,因为外部类的静态成员只有一份可以被共享访问。
2.静态内部类中是否可以直接访问外部类的实例成员?
- 静态内部类不可以直接访问外部类的实例成员,因为外部类的实例成员必须用外部类对象访问。
package com.gch.d5_innerclass_static;
/**
外部类
*/
public class Outer {
// 静态成员
public static int a = 100;
// 实例成员,属于每个对象的
private String hobby;
/**
学习静态成员内部类
*/
public static class Inner{
private String name;
private int age;
public static String schoolName;
public void show(){
System.out.println("名称:" + name +"\t年龄:" + age);
// 静态内部类可以直接访问外部类的静态成员
System.out.println(a);
// 静态内部类不能直接访问外部类的实例成员
// System.out.println(hobby); 报错
Outer o = new Outer();
System.out.println(o.hobby); // 间接访问
}
public Inner() {
}
public Inner(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
package com.gch.d5_innerclass_static;
public class Test {
public static void main(String[] args) {
Outer.Inner in = new Outer.Inner();
in.setName("小明");
in.setAge(20);
in.show();
}
}
三.成员内部类
什么是成员内部类?
- 无static修饰,属于外部类的对象。
成员内部类创建对象的格式:
- 格式:外部类名.内部类名 对象名 = new 外部类构造器().new 内部类构造器();
- 范例:Outer.Inner in = new Outer().new Inner();
1.成员内部类中是否可以直接访问外部类的静态成员?
- 成员内部类可以直接访问外部类的静态成员,外部类的静态成员只有一份可以被共享访问。
2.成员内部类的实例方法中是否可以直接访问外部类的实例成员?
- 成员内部的实例方法中可以直接访问外部类的实例成员,因为必须有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员。
package com.gch.d6_innerclass;
/**
外部类
*/
public class Outer {
private char sex;
public static int onlineNumber = 120;
/**
成员内部类:不能加static修饰 属于外部类对象的
*/
public class Inner{
private String name;
private int age;
public void show(){
System.out.println("姓名:" + name + "\t年龄:" + age);
// 成员内部类可以直接访问外部类的静态成员
System.out.println("在线人数:" + onlineNumber);
// 成员内部类可以直接访问外部类的实例成员
System.out.println("性别:" + sex);
}
public Inner() {
}
public Inner(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
四.成员内部类笔试题
package com.gch.d6_innerclass;
public class Test2 {
public static void main(String[] args) {
People.Heart h = new People().new Heart();
h.show();
}
}
class People{
private int heartbeat = 150;
public class Heart{
private int heartbeat = 110;
public void show(){
int heartbeat = 78;
System.out.println(heartbeat); // 78
System.out.println(this.heartbeat); // 110
System.out.println(People.this.heartbeat); // 150
// System.out.println(new Heart().heartbeat); // 110
// System.out.println(new People().heartbeat); // 150
}
}
}
五.匿名内部类
匿名内部类:
- 本质上是一个没有名字的局部内部类。
- 作用:方便创建子类对象,最终目的是为了简化代码编写。
特点总结:
- 匿名内部类是一个没有名字的内部类,同时也代表一个对象。
- 匿名内部类产生的对象类型,相当于是当前new的那个类型的子类类型。
- 匿名内部类可以作为一个对象,直接传输给方法。
package com.gch.d7_innerclass_anonymous;
/**
目标:掌握匿名内部类的使用形式(语法)
*/
public class Test2 {
public static void main(String[] args) {
Swimming s = new Swimming(){
@Override
public void swim(){
System.out.println("学生快乐的游泳~~~");
} // 是匿名内部类的对象而不是接口的对象
};
go(s);
System.out.println("-----------------------");
Swimming s1 = new Swimming(){
@Override
public void swim(){
System.out.println("老师快乐的游泳~~~");
} // 是匿名内部类的对象而不是接口的对象
};
go(s1);
System.out.println("---------------------------");
// 匿名内部类可以作为方法的实际参数进行传输
go(new Swimming(){
@Override
public void swim(){
System.out.println("运动员快乐的游泳~~~");
} // 是匿名内部类的对象而不是接口的对象
});
}
/**
学生、老师、运动员可以一起参加游泳比赛
*/
public static void go(Swimming s){
System.out.println("开始...");
s.swim();
System.out.println("结束...");
}
}
class Student implements Swimming{
@Override
public void swim() {
System.out.println("学生快乐的游泳~~~");
}
}
interface Swimming{
void swim();
}
- 匿名内部类通常是在开发中调用别人的方法时,别人需要我们写的时候才会定义出来。
- 将来:匿名内部类还可以实现进一步的简化代码。
package com.gch.d7_innerclass_anonymous;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
目标:通过GUI编程 理解匿名内部类的真实使用场景
*/
public class Test3 {
public static void main(String[] args) {
// 1.创建窗口
JFrame win = new JFrame("登陆界面");
JPanel panel = new JPanel();
win.add(panel); // 桌布可以自适应布局
// 2.创建一个按钮对象
JButton btn = new JButton("登录");
// 注意:讲解匿名内部类的使用
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(win,"点我一下,说明爱我!");
// System.out.println("点击!");
}
});
// btn.addActionListener(e -> JOptionPane.showMessageDialog(win,"别说话,吻我!"));
// 3.把按钮对象添加到桌布上展示
panel.add(btn);
// 4.展示窗口
win.setSize(500,400);
win.setDefaultCloseOperation(3);
win.setLocationRelativeTo(null);
win.setVisible(true);
}
}