内部类:如果一个事物的内部有同事包含另一个事物,那么这就是一个类的内部包含另一个类的关系。例如身体和心脏的关系 has-a关系,包含关系。心脏属于身体的一部分,身体包含心脏。
分类:
1.成员内部类
2.局部内部类
成员内部类定义格式
修饰符 class 外部类名称{
//...
修饰符 class 内部类名称{
//...
}
}
备注:内部类访问外部类信息,可以随意访问,但是当外部类想要访问内部类的信息,需要创建内部类对象,之后才可以访问。
如何使用成员内部类?两种方式:
1.间接使用:在外部类的方法当中使用内部类
2.直接方式:公式
外部类类名.内部类类名 对象名 =new 外部类类名().new 内部类类名();
例如:
public class Body{// 外部类
public class Heart{// 内部类
//内部类普通方法
public void beat(){
System.out.println("心脏怦怦跳");
//在内部类中访问外部类的成员变量
System.out.println("我叫"+name);//直接使用
}
}
private String name;// 系统自动赋值null
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 外部类的普通方法
public void methodBody(){
System.out.println("这是外部类的方法");
//在外部类的普通方法内访问内部类的普通方法,new 对象
Heart heart=new Heart();
heart.beat();
//如果只调用一次,可以使用匿名对象的方式
new Heart().beat();
}
}
// 定义测试类
public class InnerClassDemo01 {
public static void main(String[] args) {
//访问Heart中的beat()方法
/*Heart heart=new Heart();
heart.beat();*/ //语法错误
//创建外部类对象,访问
Body.Heart heart=new Body().new Heart();
heart.beat();
//匿名调用
new Body().new Heart().beat();
//访问外部类的普通方法
Body body=new Body();
body.merhodBody();
body.new Heart().beat();
}
}
局部内部类
当一个类是定义在方法的内部,那么这个类就是一个局部内部类。
“局部:”只有当前所属的方法可以使用,出了这个方法外面就不能使用了
定义格式
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
//....
}
}
}
局部内部类:如果希望访问所在方法的局部变量,那么这个局部变量必须是有效final的。
原因:
- new出来的对象保存在堆内存当中
- 局部变量是随着方法的压栈而在内存当中储存
- 方法运行结束后,立刻弹栈,局部变量就在内存当中消失了
- 但是new出来的对象并不会随着方法的弹栈而立刻消失,直到JVM把它认为是垃圾时才会回收消失
备注:从JDK1.8+开始,只要局部变量事实不变,那么final关键字可以省略不写。
public class OuterClass { // 外部类
/*private class InnerClassDemo{
}*/
// 定义外部类方法
public void methodOuter() {
final int num;// 所在方法的局部变量 默认是有final关键字修饰的
num = 20;
// 定义局部内部类
class InnerClass {
// 定义局部内部类的方法
public void methodInner() {
System.out.println(num);// 10
}
}
// 在方法内部使用它
InnerClass innerClass = new InnerClass();
innerClass.methodInner();
}
}
匿名内部类
以往想要使用接口当中的方法,需要4步操作:
- 定义接口实现类
- 重写所有抽象方法
- 构建子类对象把子类赋值给父接口变量
- 通过父接口变量调用接口当中的方法
匿名内部类的定义格式
接口名称 对象名 =new 接口名(){
// 覆盖重写接口当中的所有抽象方法
};
如果接口当中的实现类或者是父类的子类在程序当中只需要使用唯一的一次,在这种情况下我们就可以省略掉该类的定义,而改为使用匿名内部类。
对格式的分析:
1.new 创建对象
2.接口名称就是匿名内部类需要实现的哪个接口,同时需要创建哪个接口实现类的内容
3.{ } 这是匿名内部类的内容
使用匿名内部类的注意事项
- 匿名内部类在创建对象时,只能使用唯一一次,如果希望多次创建对象,而类的内容是一样的,建议单独定义实现类。
- 匿名对象在调用方法时,只能使用一次,如果希望同一个对象调用多次方法,建议给对象起名字。
- 匿名内部类是省略【实现类】和【子类名称】,但是匿名对象省略了对象名。
public class Test {
public static void main(String[] args) {
//采用多态方式
//多态的表现形式
/*MyInterfaceClass interfaceClass=new MyInterfaceClassimpl();
interfaceClass.method1();
interfaceClass.method2();*/
//匿名对象
//匿名内部类 他不是匿名对象 对象名是one
MyInterfaceClass one=new MyInterfaceClass( ) {
//重写父接口中抽象方法
@Override
public void method1() {
System.out.println("匿名内部类实现了该接口当中的方法");
}
};
//调用接口当中的method方法
one.method1();
new MyInterfaceClass( ) {
//重写父接口中抽象方法
@Override
public void method1() {
System.out.println("匿名内部类实现了该接口当中的方法");
}
}.method1();
}
}