Java的内部类区别

一.成员内部类

成员内部类是创建在一个类的中的,它的位置和此类的属性是同一级的,可以说是它的成员类,或成员属性

特点:

成员内部类可以访问外部类的静态属性,也可以访问其外部非静态属性

类方法如果要去访问其成员内部类的方法,还是需要才此类中去创建对象,实例化成员内部类,然后调用

在启动主方法调用成员内部类中的方法的时候,需要先实例化外部类对象,再实例化外部类的成员变量,从而拿到成员内部类对象

代码:

复制代码
class Person{
    private static String name="张三";
    private int age=18;

    class sex{
        private String sex="boy";
        public void sayName(){
            System.out.println("我的名字是:"+name);
            System.out.println("年龄是:"+age);
        }
    }

    public void saySex(){
        System.out.println("性别是:"+new sex().sex);
    }

}
复制代码

 

成员内部类:

    class sex{
        private String sex="boy";
        public void sayName(){
            System.out.println("我的名字是:"+name);
            System.out.println("年龄是:"+age);
        }
    }

 

实例化成员内部类的方式:

        //成员内部类的实例化方式
        Person.sex sex = new Person().new sex();

 

需要先实例化外部类,然后再实例化成员内部类

成员内部类的方法调用:

//内部类输出外部类的属性
        sex.sayName();

 

二.静态内部类

见名知意,这种内部类肯定是有static所修饰的成员内部类

特点:

类中的方法可以访问外部类的静态属性和方法,但是不能访问非静态的属性和方法

其它的特点和成员内部类一样

代码:

复制代码
class Person{
    private static String name="李四";
    private int age=16;

    public static class sex{
        private String sex="girl";
        public void sayName(){
            System.out.println("我的名字是:"+name);
//错误调用,不能调用非静态的属性 System.out.println("年龄是:"+age);
        }
    }
    public void saySex(){
        System.out.println("性别是:"+new sex().sex);
    }
}
复制代码

 

静态内部类:

    public static class sex{
        private String sex="girl";
        public void sayName(){
            System.out.println("我的名字是:"+name);
//错误调用,不能调用非静态的属性 System.out.println("年龄是:"+age);
        }
    }

 

这里主要是注意静态内部类的特点,就是外部类中的非静态属性是不能被访问的

静态内部类的实例化方法:

        //静态内部类的实例化方式
        Person.sex sex = new Person.sex();

 

三.局部内部类

局部内部类是定义在类的局部的类,局部指的是方法内部或代码块内部

特点:

局部内部类可以访问外部类的静态方法和属性,也可以访问非静态的方法和属性

这种类只能在局部使用,实例化的生命周期也在方法中,是出不了方法作用域的,所以叫局部内部类

代码:

复制代码
class Person{
    private static String name="王五";
    private int age=12;
    public void saySex(){
        class sex{
            private String sex="girl";
            public void sayName(){
                System.out.println("我的名字是:"+name);
                System.out.println("年龄是:"+age);
            }
        }
        System.out.println("性别是:"+new sex().sex);
        new sex().sayName();
    }
}
复制代码

 

方法中的局部内部类:

复制代码
    public void saySex(){
        class sex{
            private String sex="girl";
            public void sayName(){
                System.out.println("我的名字是:"+name);
                System.out.println("年龄是:"+age);
            }
        }
        System.out.println("性别是:"+new sex().sex);
        new sex().sayName();
    }
复制代码

 

实例化局部内部类只能在方法中,声明局部内部类的空间就是它的生命周期

四.匿名内部类

在类中定义的一个没有类名只有类体的类

这一类的定义多发生在抽象类和接口中,对于不同的实现方法的方式来构造不同的类

但是这些类都有一个很明显的特点,它们只是类名和方法体不一样,所以为了不频繁的创建类,我们可以直接使用匿名内部类,不创建类,在需要使用的地方,直接实现此类

第一种方式:普通类定义匿名内部类

普通的类内部的方法都是实现过的,如果使用原方法,则直接使用super关键字来指向父级,

如果需要重写方法那么就在匿名内部类中找到那个方法然后重写,然后通过实例化对象调用

普通类:

class Animal{
    private static String animal;
    private String kins;
    public void saySing(){
        System.out.println("动物在唱歌");
    }
}

 

匿名内部类的定义方式:

Animal animal=new Animal() {
            @Override
            public void saySing() {
                super.saySing();
            }
        };

 

如上:使用匿名内部类可以选择重写已经实现的方法,或者不重写,默认是不重写,如果重写就在方法体中重写代码段

根据上面可以看出匿名内部类把实例化对象和实现方法是写在一起了的,所以使用的使用直接使用对象调用就可以了

匿名内部类的使用:

animal.saySing();

第二种方式:抽象类定义匿名内部类

抽象类是以abstract关键字定义的类,它的内部可以有实现的方法,也可以有未实现的抽象方法

这类的的匿名内部类必须要实现未实现的方法,不然是定义不成功的

抽象类:

复制代码
abstract class Person{
    private static String name="王五";
    private int age=12;
    public abstract void sayHigh();
    public void saySex(){
        class sex{ 
            public void sayName(){
                System.out.println("我的名字是:"+name);
                System.out.println("年龄是:"+age);
            }
        }
    }
}
复制代码

 

匿名内部类的定义:需要实现未实现的抽象方法

复制代码
Person person = new Person(){
            @Override
            public void sayHigh() {
                System.out.println("身高为:181cm,体重为:68kg");
            }
            @Override
            public void saySex() {
                super.saySex();
            }
        };
复制代码

 

这里重写了抽象方法sayHigh()因为它是抽象方法必须要实现,二另外一个方法则不需要实现,或者可以重写,我没有重写,而是直接使用父类的,还可以不用管他,默认使用父类

这也是实例化和方法实现一起定义的,所以调用方法时,也是对象 . 方法

匿名内部类使用:

        person.sayHigh();
        person.saySex();

 

第三种方式:使用接口定义匿名内部类

由于接口中只会存在未实现的抽象方法,所以使用结构定义的匿名内部类时,需要把接口中所用的方法都实现一遍

接口部分:

public interface TestClassInterface {
    void say();
    void sing();

}

 

主方法中定义匿名内部类:

复制代码
       TestClassInterface tci=new TestClassInterface(){
            @Override
            public void say() {
                System.out.println("有人在说话");
            }

            @Override
            public void sing() {
                System.out.println("有人在唱歌");
            }
        };
复制代码

 

需要实现接口中所有的方法,然后使用实例化对象去调用这些在主方法中实现的方法

匿名方法的使用:

依旧对象名 .  方法

tci.say(); 
tci.sing();

 

总结:

Java之所以有那么多内部类,原因在于提升了封装的隐藏细节的特点

我们已经讲过了,面向对象的三大特征继承,封装,多态,封装需要隐藏大量的实现细节,对于一个类的集合不能使用 private 关键字实现封装,所以很容易被发现类中的实现

但是内部类时完全隐藏的,它可以对所用外部类拥有访问权限,还能隐藏对这些属性的实现细节,这使得很大程度上提升了封装的特点

五.组合类

观点:组合优于继承

组合就是把一个类当作另一个类的成员属性

当使用继承的时候,两个类中有相同的方法名,很显然,继承中会重写这个方法,所以方法名相同的只能有一个存在,要么是父类的,要么是子类重写的

在组合中,两个两个相同的类名可以同时存在,只是调用的方式不一样,在自己类中的方法直接调用,组合的类需要使用组合类名 . 方法

组合类代码:

复制代码
class Dog{
    //组合类:类作为此类的属性
    private Animal animal;

    public Dog(Animal animal) {
        this.animal = animal;
    }

    public void say(){
        System.out.println("狗再叫~~");
        animal.saySing();
        System.out.println(animal.getKins());
    }
}
复制代码

 

这里组合了Animal这一个类,其中也使用了它的方法和属性

Animal类:

复制代码
class Animal{

    private static String animal="动物";
    private String kins="animal";

    public static String getAnimal() {
        return animal;
    }

    public static void setAnimal(String animal) {
        Animal.animal = animal;
    }

    public String getKins() {
        return kins;
    }

    public void setKins(String kins) {
        this.kins = kins;
    }

    public void saySing(){
        System.out.println("动物在唱歌");

    }
}
复制代码

 

使用组合类:

Dog dog = new Dog(new Animal());
dog.say();

 

由于Animal是它的属性类,所以需要传入一个Animal对象进去,否则会形成空指针异常

简单讲,组合就是讲类当作属性然后再另外一个类中一起使用,当然,使用被组合的类需要传入一个这个类的实例对象

 在Java中,组合类(Composition)是一种重用类代码的形式,它允许在一个类中使用已有的类的实例来定义新的类。这种组合的方式通常是将一个或多个现有类的对象嵌入到新类中,新类可以通过这些对象来使用现有类的功能

组合类也可以创建对象作为对象字段去创建新的组合类,这种过程被称为多级封装。同时,对于对象字段和非对象字段,我们也可以规定它们的访问权限,这被称为二次封装。

posted @   回忆也交给时间  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2022-11-13 SpringBoot - 基础学习 - 什么是SpringBoot
点击右上角即可分享
微信分享提示