java中的内部类

java中的内部类主要分为两类四种:

第一类:定义在外部类局部位置上,分为局部内部类( 有 类名)、匿名内部类(没有类名)。

第二类:定义在外部类的成员位置上,分为成员内部类(没有static修饰)、静态内部类(使用static修饰)。

一:局部内部类

局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。

局部内部类的使用

1.局部内部类可以直接访问外部类的所有成员,包含私有的,访问方式——直接访问。

2.不能添加访问修饰符,因为它的地位就是一个局部变量,局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final。

3.作用域仅仅在定义它的方法或代码块中

4.外部类访问局部内部类,访问方式:创建对象,在访问(注意:必须在作用域内)

对上面的使用以代码的形式呈现:

public class TestDemo {
    public static void main(String[] args) {
        Person person = new Person();
        person.method2();
    }
}
class Person{//外部类
    private String name = "张三";
    private int age = 20;

    private void method1(){
        System.out.println("外部类中的method1方法");
    }

    public void method2(){
        final class Student{//局部内部类可以加fianl关键字
            private String name = "王五";
            public void method3(){
                method1();//可以访问外部类中的成员
            }
        }
        /**
         * 外部类访问局部内部类的方式:创建对象再访问
         */
        Student student = new Student();
        student.method3();
    }
}

 

5.外部其他类不能直接访问局部内部类(因为局部内部类是一个局部变量) 

6.如果外部类和局部内部类的成员重名时,默认遵循就近访问原则,如果打破原则访问外部类成员,则可以使用(外部类名.this.成员)去访问。

代码演示上面两个使用:

public class TestDemo {
    public static void main(String[] args) {
        Person person = new Person();
        person.method2();
        //不能直接访问局部内部类
        //person.student;//报错:Cannot resolve symbol 'student'
    }
}
class Person{//外部类
    private String name = "张三";
    private int age = 20;

    private void method1(){
        System.out.println("外部类中的method1方法");
    }

    public void method2(){
        final class Student{//局部内部类可以加fianl关键字
            private String name = "王五";
            public void method3(){
                System.out.println(name);//遵循就近原则
                System.out.println(Person.this.name);//同名时访问外部成员
                method1();//可以访问外部类中的成员
            }
        }
        /**
         * 外部类访问局部内部类的方式:创建对象再访问
         */
        Student student = new Student();
        student.method3();
    }
}

 

二:匿名内部类 

上面四种内部类中只需要掌握这一种即可,这是以后代码中经常会用到的,很重要。

匿名内部类的定义

匿名内部类是没有名称的内部类。在Java中调用某个方法时,如果该方法的参数是接口类型,除了可以传接口实现类外,还可以使用实现接口的匿名内部类作为参数,在匿名内部类中直接完成方法的实现。

通过一段代码来解释匿名内部类:

public class TestDemo02 {
    public static void main(String[] args) {
        People people = new People();
        people.method();
    }
}
class People{
    private String name;
    public void method(){
        class Student implements behavior{
            @Override
            public void eat() {
                System.out.println("学生韩梅梅正在吃饭");
            }
        }
        Student student = new Student();
        student.eat();


        class Teacher implements behavior{
            @Override
            public void eat() {
                System.out.println("老师李华正在吃饭");
            }
        }
        Teacher teacher = new Teacher();
        teacher.eat();
    }
}
interface behavior{
    public void eat();
}

 

从上面可以看到People类里面有两个内部类Student、Teacher,两个类都实现了behavior接口并实现了里面吃这个行为。 

细心的朋友已经观察到了,上面的代码不是局部内部类吗,和匿名内部类与啥关系。在这里我们通过局部内部类主要是为了引出匿名内部类。观察上面的代码,发现为了调用内部类里面的方法,就必须实例化对象,然后在调用。如果内部类一多,比如现在有Father、Marther.......众多的内部类,难道都要一个个实例吗,为了简化开发,java开发者就创建了匿名内部类,看下面的代码。

public class TestDemo02 {
    public static void main(String[] args) {
        People people = new People();
        people.method();
    }
}
class People{
    private String name;
    public void method(){
        Behavior student = new Behavior() {
            @Override
            public void eat() {
                System.out.println("学生韩梅梅正在吃饭");
            }
        };
        student.eat();
        Behavior teacher = new Behavior() {
            @Override
            public void eat() {
                System.out.println("老师李华正在吃饭");
            }
        };
        teacher.eat();
    }
}
interface Behavior{
    public void eat();
}

上面的代码就是利用匿名内部类实现多对象的创建,合理使用匿名内部类可以很大程度简化代码量。

为看懂上面的代码,现在作如下分析:

1.分析上面student的编译类型和运行类型,编译类型为Behavior,运行类型正是匿名内部类。可能有的人会很以为,这个匿名内部类在哪里,怎么没看见。所谓匿名内部类,就是没有名字的类,也不能说没有名字吧,jdk底层给这个类分配了一个名字,就叫做People$1,只不过不显示出来,看如下代码就知道了:

public class TestDemo02 {
    public static void main(String[] args) {
        People people = new People();
        people.method();
    }
}
class People{
    private String name;
    public void method(){
        Behavior student = new Behavior() {
            @Override
            public void eat() {
                System.out.println("学生韩梅梅正在吃饭");
            }
        };
        student.eat();
        System.out.println(student.getClass());//获取全路径类名
    }
}
interface Behavior{
    public void eat();
}

 

2.jdk底层创建完匿名内部类以后马上就实力化了该类的对象,也就是说底层一共做了两步动作,第一是创建匿名内部类,第二步是实力化对象。

3.上面的匿名内部类的操作步骤和局部内部类是一样的,只不过简化了代码而已。 

匿名内部类的语法

new 接口或类(参数列表){
       类体;
};

 下面在演示其他两种不同的匿名内部类:

一:基于类的匿名内部类

public class TestDemo02 {
    public static void main(String[] args) {
        new People("张三").method();
    }
}
class People{
    private String name;

    public People(String name) {
        this.name = name;
    }
    public void method(){
        Father father = new Father("张三"){
            @Override
            public void sleep() {
                System.out.println("匿名内部类中的sleep方法");
            }
        };
        father.sleep();
    }
}
class Father{
    private String name;
    public Father(String name){
        this.name = name;
    }
    public void sleep(){
        System.out.println("正在睡觉");
    }
}

上面的匿名内部类是继承至Father这个类的,当匿名内部类调用sleep方法的时候,根据继承机制他首先在本类中找,刚好本类中有一个sleep方法,他就会执行本类中的方法,结果如下:

这里需要重点提一下:有得朋友可能会想,既然匿名内部类也是一个类,那么在类里面写一些方法,然后实力化调用这些方法是不是也行。这里需要指出,匿名内部类里面确实可以写自己的方法,但是不能调用,因为根据继承机制(实现接口也相当于继承,因为接口是一种特殊的类),匿名内部类作为一个子类,他是无法调用自身特有的方法的。这里也不能强转,因为你根本就不知道匿名内部类的运行类型是啥。所以综上,匿名内部类里面只能重写父类中的方法,然后调用。 

二:基于抽象类的匿名内部类

public class TestDemo02 {
    public static void main(String[] args) {
        People people = new People();
        people.method();
    }
}
class People{
    private String name;
    public void method(){
       Animal dog = new Animal() {
           @Override
           void eat() {
               System.out.println("小狗吃东西");
           }
       };
       dog.eat();
    }
}
abstract class Animal{
    abstract void eat();
}

 

匿名内部类的使用

1.匿名内部类既是一个类,又是一个对象,既有定义类的特征,又有创建对象的特征。所以可以调用匿名内部类中的方法。

匿名内部类的使用和局部内部类一样,除了第四条。

 

 匿名内部类的使用场景

 一:当做实参直接传递

public class TestDemo02 {
    public static void main(String[] args) {
        show(new Peopel() {
            @Override
            public void dance() {
                System.out.println("全名制作人们大家好,我是练习时长两年半的个人练习生蔡徐坤");
            }
        });
    }
    public static void show(Peopel peopel){
        peopel.dance();
    }
}
interface Peopel{
    public void dance();
}

 

二:在多态中的应用

public class TestDemo02 {
    public static void main(String[] args) {
        Ikun ikun = new Ikun();
        ikun.show(new Peopel() {
            @Override
            public void dance() {
                System.out.println("你们都是黑子,只有我才是真爱粉");
            }
        });
        ikun.show(new Peopel() {
            @Override
            public void dance() {
                System.out.println("会唱、跳、rap的才是ikun");
            }
        });
    }
}
class Ikun{
    public void show(Peopel peopel){
        peopel.dance();//这里会发生动态绑定
    }
}
interface Peopel{
    public void dance();
}

 

 

三:成员内部类

成员内部类的概念 

成员内部类是定义在外部类的成员位置上,并且没有static修饰

成员内部类的使用 

1.可以直接访问外部类的所有成员,包括私有的。外部类访问成员内部类访问方式:创建对象,再访问;

2.可以添加任意访问修饰符,因为它的地位就是一个成员;

3.作用域和外部类的其他成员一样,为整个类体

4.如果外部类和内部类的成员重名时,内部类访问的话,遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问。

5.外部其他类访问成员内部类有三种方式:第一种实例化外部类,然后访问;第二种将内部类作为外部类的成员实例化然后访问;第三种在外部类里面编写一个方法,可以返回内部类对象。

下面用代码演示上面的使用:

public class TestDemo02 {
    public static void main(String[] args) {
        People people = new People();
        people.method();//访问的第一种方式实例化外部类,通过外部类里面的方法访问
        //People.Student student = people.new Student();//访问的第二种方式,将内部类作为外部类的成员实例化然后访问
        /**
         * 访问的第三种方式
         * People.Student getStudent = people.getStudent();
         * getStudent.say();
         */
    }
}
class People{//外部类
    private String name = "张三";
    private int age = 20;

    private void hi(){
        System.out.println("打招呼");
    }

    public class Student{//内部类
        private String name = "李四";
        private int age = 21;
        public void say(){
            System.out.println("name="+name+" age="+People.this.age);
        }
    }

    //返回Student类
    public Student getStudent(){
        return new Student();
    }

    public void method(){//外部类访问内部类
        Student student = new Student();
        student.say();
    }
}

 

 

四:静态内部类 

静态内部类的概念 

静态内部类是定义在外部类的成员位置上,并且有static修饰

静态内部类的使用

1.可以直接访问外部内的所有静态成员,包含私有的,但不能直接访问非静态的成员 

2.可以添加任意访问修饰符,因为它的地位就是一个成员;

3.作用域和外部类的其他成员一样,为整个类体

4.如果外部类和内部类的成员重名时,内部类访问的话,遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问。

这些都不重要就不演示了。

  • 27
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼吐泡泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值