JAVA day09 内部类(成员内部类,静态内部类,局部内部类,匿名内部类)

一、内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。

1.成员内部类

定义在类中的方法外的类。

class 外部类 {
class 内部类 {
}
}
特点:
  • 作为成员存在,可以被权限修饰符修饰。
  • 内部类可以直接访问外部类的成员,包括私有成员。
  • 外部类要访问内部类的成员,必须要建立内部类的对象。
主方法内创建内部类对象:
外部类名 . 内部类名 对象名 = new 外部类型 (). new 内部类型 ();
ps: 内部类仍然是⼀个独⽴的类,在编译之后会内部类会被编译成独⽴的 .class ⽂件,但是前⾯
冠以外部类的类名和 $符号 。比如:Person$Heart.class
代码说明
//外部类
public class Outer {
    //外部类成员变量
    int a = 1;
    private int b = 2;
    int e = 10;//相同的外部类的成员变量

    //外部类成员方法
    public void outM1(){
        //当外部类想访问内部类的成员时,需要创建内部类的对象
        Inner in = new Inner();
        System.out.println(in.c+","+in.d);//内部类的私有成员变量也能获取
        in.inM1();//内部类成员方法

        System.out.println("外部类的成员方法outM1");
    }

    //成员内部类
    public class Inner{
        //内部类成员变量
        int c = 3;
        private int d = 4;
        int e = 10;//相同的内部类的成员变量

        //内部类的成员方法
        public void inM1(){
            int e = 10;//相同的外部类的局部变量
            //在内部类里可以直接访问到外部类的成员,包括私有成员
            System.out.println(a+","+b);//private int b = 2;
            outM1();//直接调用外部类成员方法

            //若出先变量名相同的情况该如何获取到想要的变量
            //1.获取相同的内部类的局部变量
            System.out.println(e);
            //2.获取相同的内部类的成员变量
            System.out.println(this.e);
            //3.获取相同的外部类的成员变量
            System.out.println(Outer.this.e);

            System.out.println("内部类的成员方法inM1");
        }



    }
}
//无关类
public class Main {
    public static void main(String[] args) {
        //当无关类想获取内部类的成员
        //1.间接调用:在外部类成员方法里创建了内部类的对象,再在无关类创建外部类的对象,通过调用外部类成员方法,间接调用内部类
        Outer ou = new Outer();
        ou.outM1();

        //2.直接调用
       Outer.Inner inOu = new Outer().new Inner();
       inOu.inM1();//但如果想直接访问外部或者内部私有成员,还是需要创建get,set

    }
}

2.静态内部类

定义在类中的方法外的,被static关键词修饰的类。

class 外部类 {
static class 内部类 {
}
}
特点:
  • 作为静态成员属性存在,可以被任意权限修饰符修饰。
  • 可以直接访问外部类static相关的属性和方法。
  • 访问外部类普通属性和方法,则需要通过new外部类去访问。

代码说明

//静态内部类

public class Outer {
    //外部类
    //成员变量
    int a;
    //静态成员变量
    static int b;

    //成员方法
    public void m1(){
        System.out.println("成员方法m1");
    }

    //静态成员方法
    public static void  m2(){
        System.out.println("静态成员方法m2");
    }

    //静态内部类
    public static class inner1{
        int ina;
        static int inb;

        public void innerM1(){
            System.out.println(b);//可以直接访问外部类静态成员
            m2();
           // m1();//不可以直接访问外部类不是静态的成员

            //访问其他属性跟方法 需要实例化外部类
            Outer ou = new Outer();
            ou.a = 5;
            ou.m1();


        }
    }

}
public class Main {
    public static void main(String[] args) {
        //调用普通成员
        Outer ou1 = new Outer();
        ou1.m1();
        //调用静态的成员
        Outer.b = 23;
        Outer.m2();
        //访问内部类成员
        Outer.inner1 oi = new Outer.inner1();
        oi.innerM1();
        oi.ina = 5;
        //调用内部类静态成员
        Outer.inner1.inb = 6;

    }
}

3.局部内部类

定义在类中方法中的类。

class 外部类 {
public void m1(){
class 内部类 {
}
}
}
特点:
  • 存在方法之中,只能在方法中使用,类前不能有访问权限。
  • 局部内部类只在当前方法中有效。
  • 不能定义static成员,因为在方法结束后,内存需要释放。
  • 局部内部类中可以访问外部类的所有成员。
  • 可以直接访问方法的局部变量,但无法修改,编译会出错。

代码说明

//局部内部类
public class Outer {
    //成员变量
    int a;

    //成员方法
    public void m1(){
        //局部变量
       int b=5;

        //局部内部类:存在于外部类的成员方法中
        //注意局部内部类的修饰词不能用访问修饰符 :4个
       class Inner{
            //局部内部类的成员变量
          int ina;
            //局部内部类的成员方法
            public void m2(){
                int inb =3;
                System.out.println("局部内部类的成员方法m2");

                //如果想在局部内部类中获取外部类成员方法的局部变量
                System.out.println(b);
                //b = 10;-->不能被修改因为此时的外部类方法中的局部变量默认被final修饰

                //局部内部类方法中的局部变量
                System.out.println(inb);//3
                inb = 8;
                System.out.println("inb"+inb);//8能被修改

            }

        };
        //想要使其他类获取局部内部类的成员
        //需要在外部类中,方法中,局部内部类外,创建局部内部类的对象
        Inner in = new Inner();
        //然后就能在方法里调用局部内部类的成员了
        System.out.println(in.ina);//局部内部类的成员变量
        in.m2();//局部内部类的成员方法

        System.out.println("外部类的成员方法m1");
    }


}
//无关类
public class Main {
    public static void main(String[] args) {
        Outer ou = new Outer();
        ou.m1();
    }
}

4.匿名内部类

跟局部内部类相似,但本质是一个为了继承抽象类,或者实现接口。

new ⽗类名或者接⼝名 () {
// ⽅法重写
@Override
public void method () {
// 执⾏语句
}
};
特点:
  • 没有类名的内部类,必须在创建时使用new语句来声明类。
  • 匿名类和局部内部类一样,存在方法中,可以访问外部类的所有成员。
  • 重写父类/接口中的抽象方法。
  • 匿名类中允许使用非静态代码块进行成员初始化操作。
  • 匿名类的非静态代码块会在父类的构造方法之后被执行。

代码说明(接口举例)


public interface InterfaceA {

    //接口的抽象方法
    public abstract  void a1();
    public abstract  void a2();

}
//匿名内部类
public class Outer {
    int num;

    public void m1(){
        //1.局部内部类里创建一个接口的实现类
        class InterfaceImpl implements InterfaceA{

            @Override
            public void a1() {
                System.out.println("m1,a1");

            }

            @Override
            public void a2() {
                System.out.println("m1,a2");
            }
        }
        //创建一个实现接口A类的对象
        InterfaceImpl in = new InterfaceImpl();
        in.a1();//这样就可以调用实现类接口A里重写的抽象方法
        in.a2();

    }

    //2.匿名内部类——>优化局部内部类
    public void m2(){
        //InterfaceImpl in = new InterfaceImpl();
        //多态  InterfaceA in = new InterfaceImpl();
        //下面这样的写法优化了局部内部类,称之为匿名内部类,因为class名不见了
        //接口是不能new对象的,但 InterfaceA in = new InterfaceA() {}; 不是new对象,new对象没有{};
        //它是对实现这个接口的实现类new的对象
        //可以理解成是个引用的实现类的方法
        InterfaceA in = new InterfaceA() {
            @Override
            public void a1() {
                System.out.println("m2,a1");
            }

            @Override
            public void a2() {
                System.out.println("m2,a2");
            }
        };
        in.a1();//直接调用
        in.a1();

    }
    //3.匿名对象
    public void m3(){
        //
        new InterfaceA(){//直接new接口A的实现类

            @Override
            public void a1() {
                System.out.println("m3,a1");
            }

            @Override
            public void a2() {
                System.out.println("m3,a2");
            }
        }.a1();//通过在分号前.方法名调用接口A的抽象方法,但每次只能调用一个方法,
        // 若想调用其他方法还需创建一个成员方法重写后调用,如 m4
    }
    public void m4(){
        new InterfaceA(){
            @Override
            public void a1() {
                System.out.println("m4,a1");
            }

            @Override
            public void a2() {
                System.out.println("m4,a2");
            }
        }.a2();
    }


}

public class Main {
    public static void main(String[] args) {
        Outer ou = new Outer();
        ou.num = 5;
        ou.m1();
        //m1,a1
        //m1,a2
        ou.m2();
        //m2,a1
        //m2,a1
        ou.m3();
        //m3,a1
        ou.m4();
        //m4,a2
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值