【java内部类】Java:内部类介绍

本文详细介绍了Java中的四种内部类:成员内部类、局部内部类、静态内部类和匿名内部类。通过示例代码展示了它们的创建、访问外部类属性以及实例化的方式。重点讨论了静态内部类只能访问外部静态属性,以及匿名内部类在接口实现中的高效应用。
摘要由CSDN通过智能技术生成

成员内部类

成员内部类,顾名思义在类的成员位置上,我们创建了一个Java类,这个类在已有类的内部。
编写一个S类作为示例,S类有属性和行为。相比于普通类,其中我们在S类的内部加上了一个Z类,Z类就是一个成员内部类。在z类里一样有属性和行为(方法)。在内部类Z类的方法里我们尝试输出外部类的属性,在外部类S类,我们同样尝试用过方法输出内部类的属性。由于外部类方法直接访问内部类属性时,软件提示错误,于是我们这里试着通过实例化一个对象来访问。然后试着运行。

public class S {
    static String Name="张三";
    int age =12;
    class Z{
        String id="001";
        public void say(){
            System.out.println("名字"+Name);
            System.out.println("年龄"+age);
        }
    }
    Z z=new Z();
    public void say1(){
        System.out.println("编号"+z.id);
    }

编写一个main方法来测试以上代码是否能够正常运行,由于Z类在S类的内部,所以我们不能正常实例化一个对象,需要通过外部的对象进行实例化。

    public static void main(String[] args) {
        S s=new S();
        Z z= s.new Z();//需通过外部对象实例化
        s.say1();
        z.say();
    }

可以看到我们运行的结果,可以知道内部类的方法成功的访问了外部类的属性,并且外部类静态的和非静态的都输出了出来,同时外部类的方法也成功通过对象访问了内部的数据属性。
在这里插入图片描述
通过以上运行结果,可以总结出以下特点:成员内部类,可访问外部静态或非静态的属性,其次外部方法访问成员内部类,须通过实例化对象才能够访问,还有内部类实例化对象需要听过外部类的对象。

局部内部类

局部内部类,也叫方法内部类,也就是说在类的方法里面创建了一个类。依旧用上面的程序,我们将Z类移动到S类的方法里面去。局部内部类于成员内部类有异曲同工之妙。由于局部内部类在类的方法里面,所以它相较于成员内部类的作用域要小很多。
通过具体示例体现:

public class S {
    static String Name="张三";
    int age =12;
    public void say1(){
        class Z{
            String id="001";
            public void say(){
                System.out.println("名字"+Name);
                System.out.println("年龄"+age);
            }
        }
        Z z=new Z();
        z.say();
        System.out.println("编号"+z.id);
    }

可以看到Z类在S类的方法里面,方便比较,所以其余并没有变化。

    public static void main(String[] args) {
        S s=new S();
        s.say1();

    }

由于Z类在S类的方法里面,所以在main方法里不需要在给内部类实例化,也可以调用。
在这里插入图片描述
可以看到运行结果与成员内部类结果一样。依据运行结果和代码,我们可以总结出局部内部类的特点;局部内部类可以直接访问外部类的属性数据,外部类输出局部内部类的属性数据需要通过实例化的对象才可以。其次局部内部类实例化数据必须在局部的方法里面。

静态内部类

静态内部类,是在外部类里面用static关键字进行修饰的类。
简单回顾static关键字的用法:

用法static
修饰成员变量变成类的成员属性,可类名.成员调用,不需new对象
修饰成员方法变成类的成员方法,可类名.方法调用,不需new对象
静态块类成员一起初始化
静态导包方法名调用(便捷)

熟悉了以上static的用法,我们可以猜测以下静态内部类的特点。
静态内部类只能访问外部静态的属性和方法。
其次static修饰了,可能可以直接实例化对象,不需要通过外部的实例化对象
通过示例尝试:
依旧用上面的Z类和S类,在S类里添加一个用static修饰的Z类,其他依旧和以前一样,以方便对比。

public class S {
    static String Name="张三";
    int age =12;

    static class Z{
        String id="001";
        public void say(){
            System.out.println("名字"+Name);
        }
    }
    Z z=new Z();
    public void say1(){
        System.out.println("编号"+z.id);
    }

编写一个main方法来运行,看能否正常运行。

    public static void main(String[] args) {
        S s=new S();
        Z z= new Z();
        s.say1();
        z.say();

    }

运行结果如图,可以知道我们以上的内外部类之间的属性和方法的访问,能够正常运行。说明我们的猜测是正确的。
在这里插入图片描述
总结一下,static修饰的静态内部类只能访问外部静态的属性。非静态的属性不能访问,
其次,静态内部类可以直接进行对象的实例化,不需要通过外部类实例化的对象。

匿名内部类

匿名内部类是掌握的重点,前面的理解就行,匿名内部类在接口中使用能够带来极大的方便。
匿名内部类顾名思义,隐藏起来的内部类。
通过一个示例来理解:
写一个抽象的Animal的类:有属性,有抽象和非抽象的方法

public abstract class Animal{
    String Name;
    public void say(){
        System.out.println("非抽象方法");
    }
    public abstract void eat();
}

在写cat类,dog类等去继承Animal这个类,重写eat方法,在main方法里面输出出来。

class cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
class dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}

在main方法里面,通过父类引用指向子类的对象输出。

public static void main(String[] args) {
        Animal a1=new cat();
        a1.eat();
        Animal a2=new dog();
        a2.eat();
        }

运行结果如下:

可以看到输出了我们希望的结果。
但是如果有很多这样的类,,为了需要我们创建了一个一个的子类,但是子类之间只有一两处不同,就会发现程序非常的冗余。如果有一个方法让我们不需要定义子类,就可以输出想要的。
于是就有了匿名的内部类,隐含实现一个接口或实现一个类
我们在原程序上写一个这样的代码,再次运行:

        Animal a3=new Animal(){
            @Override
            public void eat() {
                System.out.println("兔子吃草");
            }
        };
        a3.eat();

可以看到运行结果多了一个兔子吃草,正是以上代码输出的内容
在这里插入图片描述

要知道Animal是抽象的,不可以实例化,但是我们在后面加一个{}就可以继续代码的编写。
我们可以看到运行结果与我们写一个子类的效果一样。
这就是匿名内部类,我们不知道这个类的名称,但是实现了与定义一个子类一样的效果。
`所以说匿名内部类隐含实现一个接口或实现一个类。
我们尝试定义一个接口,在接口里使用匿名内部类。
接口类:Animal类——有两个方法

public interface Animal {
    void feed();
    void eat();
}

实现类:cat类

class cat implements Animal{
    @Override
    public void feed() {
        System.out.println("给猫喂水");
    }

    @Override
    public void eat() {
        System.out.println("猫喝水");
    }
}

写一个匿名实现类,看我们的运行结果是不是一样的。

        Animal a2=new Animal() {
            @Override
            public void feed() {
                System.out.println("买饭吃");
            }

            @Override
            public void eat() {
                System.out.println("吃饱了");
            }
        };

在main方法里运行,结果如下:
在这里插入图片描述
可以看到两种方法出来的结果是一样的,匿名实现类免去了创建子类的麻烦,使得程序更加的高效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值