内部类
- 内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解为(宿主)
public class People{
public class Heart{
}
}
内部类的使用场景、作用
- 当一个事务的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计。
- 内部类通常可以方便访问外部类的成员,包括私有的成员。
- 内部类提供了更好的封装性,内部类本身就可以用private protected等修饰,封装性可以做更多控制
内部类的分类
- 静态内部类
- 成员内部类(非静态内部类)
- 局部内部类
- 匿名内部类
静态内部类
- 有static修饰,属于外部类本身
- 它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已
public class Outer{
public static class Inner{}
}
静态内部类创建对象的格式
格式:外部类名.内部类名 对象名=new 外部类名.内部类名
Outer.Inner in=new Outer.Inner();
静态内部类可以直接访问外部类的静态成员,但是不能直接访问外部类的实例成员,外部类的实例成员必须用外部类对象访问
public class Person {
private String trait;
public static String school="父母";
public void eat(){
System.out.println("人是铁饭是钢");
}
public static class Inner{
private String name;
private int 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;
}
public static String header="头部";
public Inner(){
System.out.println("内部类的无参数构造器");
}
public Inner(String name,int age){
this.name=name;
this.age=age;
System.out.println(this.name+this.age+"\t\t内部类的有参数构造器");
}
public void show(){
System.out.println("Person.Inner的show方法");
System.out.println(name+age);
//System.out.println(trait); 静态内部类不可以访问外部类的实例成员
//eat();
System.out.println("school:"+school); //静态内部类可以访问外部类的静态成员
}
}
}
public class Test {
public static void main(String[] args) {
Person.Inner a=new Person.Inner();
a.setName("张三");
a.setAge(15);
a.show();
System.out.println("内部类的静态成员:"+Person.Inner.header);
Person.Inner b=new Person.Inner("李四",20);
b.show();
}
}
成员内部类
- 无static修饰,属于外部类的对象
- JDK16之前,成员内部类不能定义静态成员,JDk16开始也可以定义静态成员了
public class Outer{
public class Inner{
}
}
成员内部类创建对象的格式:
格式: 外部类名.内部类名 对象名=new 外部类构造器.new 内部类构造器
Outer.Inner in=new Outer().new Inner();
成员内部类可以直接访问外部类的静态成员,外部类的静态成员只有一份可以共享访问
成员内部类的实例方法可以直接访问外部类的实例成员,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员
public class Animal {
private String name;
public static String hobby="吃饭";
public Animal(String name) {
this.name = name;
}
public Animal() {
}
public class Dog{
private int age;
public void show(){
System.out.println("Animal名字叫:"+name+age+"能"+hobby);
}
public String getName() {
return name;
}
public void setName(String dogName) {
name = dogName;
}
public Dog(int age) {
this.age = age;
}
public Dog(){
System.out.println("内部类的无参数构造器");
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
public class demo {
public static void main(String[] args) {
Animal.Dog a=new Animal().new Dog();
a.setName("笨笨");
a.setAge(2);
a.show();
System.out.println("---------------");
Animal.Dog b=new Animal("奇奇").new Dog(2);
b.show();
System.out.println("Animal.hobby:"+Animal.hobby);
}
}
在成员内部类中访问所在外部类对象,格式:外部类名.this
public 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
}
}
}
class demo1{
public static void main(String[] args) {
People.Heart p=new People().new Heart();
p.show();
}
}
局部内部类
- 局部内部类放在方法、代码块、构造器等执行体中
- 局部内部类的类文件名:外部类$N内部类.class
public class Demo1 {
public static void main(String[] args) {
//局部内部类
class Dog{
private String name;
private int 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;
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public Dog() {
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Dog d=new Dog();
d.setName("笨笨");
d.setAge(2);
System.out.println(d.toString());
Dog d1=new Dog("奇奇",2);
System.out.println(d1.toString());
}
}
匿名内部类
- 本质上是一个没有名字的局部内部类,定义在方法中,代码块中,等
- 作用:方便创建子类对象,最终目的为了简化代码编写。
格式
new 类|抽象类名|或者接口名(){
重写方法;
}
Employee a=new Employee(){
public void work(){
}
};
a.work();
特点总结:
- 匿名内部类是一个没有名字的内部类
- 匿名内部类写出来就会产生一个匿名内部类的对象
- 匿名内部类的对象类型相当于是当前new的那个类型的子类类型
abstract class Animal{
public abstract void run();
}
interface Person{
public void eat();
}
public class demo {
public static void main(String[] args) {
// Animal a = new Tiger(); 多态
// a.run();
Animal b=new Animal(){
@Override
public void run() {
System.out.println("老虎跑的贼快~");
}
};
b.run();
Person c=new Person(){
@Override
public void eat() {
System.out.println("女的要吃饭");
}
};
c.eat();
}
}
//class Tiger extends Animal{
// @Override
// public void run() {
// System.out.println("老虎跑的真快~");
// }
//}
匿名内部类常见使用形式
- 某个学校需要让老师,学生,运动员一起参加游泳比赛
public class demo01 {
public static void main(String[] args) {
goSwimming(new Swimming(){
@Override
public void swim() {
System.out.println("老师游的比较快");
}
});
System.out.println("---------------------");
goSwimming(new Swimming(){
@Override
public void swim() {
System.out.println("学生游得很快");
}
});
System.out.println("---------------------");
goSwimming(new Swimming() {
@Override
public void swim() {
System.out.println("运动员游得最快");
}
});
}
public static void goSwimming(Swimming swimming){
System.out.println("开始");
swimming.swim();
System.out.println("结束");
}
}
匿名内部类真实使用场景
- 给按钮绑定点击事件
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class demo02 {
public static void main(String[] args) {
JFrame win=new JFrame("登录界面");
Panel panel=new Panel();
win.add(panel);
JButton btn=new JButton("登录");
panel.add(btn);
//匿名内部类 实现接口AbstractAction
btn.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(win,"登录成功!");
}
});
//展示页面
win.setSize(400,300);
win.setLocationRelativeTo(null);
win.setVisible(true);
}
}