JavaRush /Java 博客 /Random-ZH /类、嵌套类的类型及示例
Ярослав
第 40 级
Днепр

类、嵌套类的类型及示例

已在 Random-ZH 群组中发布
大家好。在本主题中,我想详细讨论 Java 类及其类型,以帮助初学者理解本主题,或许非新手也能学到新东西。在可能的情况下,所有内容都将使用现实生活中的示例以及随附的代码示例来显示。让我们开始吧。 类、嵌套类的类型及示例 - 1我想指出的是,主要的是了解前两种类型的类,本地类和匿名类只是内部类的子类型。

什么是班级?

是某事物的逻辑描述,是一个模板,您可以使用它创建该事物的真实实例。换句话说,它只是对创建的实体应该是什么样子的描述:它们应该具有什么属性和方法。 属性是实体的特征,方法是实体可以执行的操作。现实生活中类的一个很好的例子可以被认为是绘图,它可以帮助您理解什么是类:绘图用于描述结构(弹射器、螺丝刀),但绘图不是设计。正如工程师使用蓝图来创建设计一样,编程使用类来创建描述属性和方法的对象。
public class Student {
    private String name, group, specialty;

    public Student(String name, String group, String specialty) {
       this.name = name;
       this.group = group;
       this.specialty = specialty;
   }

   // getters/setters
}
在此示例中,我们创建了一个描述“学生”实体的 Java 类:每个学生都有一个姓名、小组和专业。现在,在程序的其他地方,我们可以创建此类的真实示例。换句话说:如果班级Student是学生应有的形象,那么创建的实例就是实际的学生本身。创建新学生的示例:new Student("Ivan", "KI-17-2", "Computer Engineering");操作符new搜索类Student,然后调用该类的特殊方法(构造函数)。构造函数返回一个现成的类对象Student- 我们亲爱的、饥饿的没有奖学金的学生:))

Java 中的类类型

在 Java 中,有 4 种类包含在另一个类中:
  1. 嵌套内部类是外部类内部的非静态类。

  2. 嵌套静态类是外部类内部的静态类。

  3. Java 本地类是方法内的类。

  4. 匿名 Java 类是动态创建的类。

我们将分别讨论它们。

外部类中的非静态类

首先,我想让你通过一个真实的例子来理解这是什么,因为这样更容易理解。所以现在我们将把一个真正的大东西分解成更小的部件,我们将拆解一架飞机!然而,为了举例,展示一点就足够了;我们不会完全分解它。为了形象化这个过程,我们将使用飞机图。 类、嵌套类的类型及示例 - 2 首先,我们需要创建一个类,Airplane在其中添加一些描述:飞机名称、识别码、航班。
public class Airplane {
    private String name, id, flight;

    public Airplane(String name, String id, String flight) {
        this.name = name;
        this.id = id;
        this.flight = flight;
    }

    // getters/setters
}
现在我们要添加翅膀。创建一个单独的类?如果我们有一个复杂的飞机设计程序,并且需要创建大量的派生类(与父类具有相同逻辑的类,即它们继承的类,但所以他们通过添加逻辑或更详细的特征来扩展父类),但是如果我们只有一个只有一架飞机的游戏怎么办?那么我们把整个结构放在一个地方(一个类)完成会更加合理。这就是非静态嵌套类发挥作用的地方。本质上,这是对我们外部类的一些细节的更详细的描述。在此示例中,我们需要为飞机创建机翼 - 左翼和右翼。让我们一起创造吧!
public class Airplane {
    private String name, id, flight;
    private Wing leftWing = new Wing("Red", "X3"), rightWing = new Wing("Blue", "X3");

    public Airplane(String name, String id, String flight) {
        this.name = name;
        this.id = id;
        this.flight = flight;
    }

    private class Wing {
        private String color, model;

        private Wing(String color, String model) {
            this.color = color;
            this.model = model;
        }

        // getters/setters
    }

    // getters/setters
}
Wing因此,我们在类(飞机)内 创建了一个非静态嵌套类(翼) Airplane,并添加了两个变量 - 左翼和右翼。每个翅膀都有自己可以更改的属性(颜色、型号)。这样您就可以根据需要为建筑物配备人员。注意:前面的图上有相当多的飞机部件,事实上,我们可以将所有部件划分为内部类,但这样的过程并不总是可取的。需要根据任务来追踪此类时刻。您可能根本不需要翅膀来解决问题。那么就没有必要做它们了。这就像将一个人切成腿、手臂、躯干和头部 - 这是可能的,但为什么如果这个类仅用于存储有关人的数据呢? 非静态嵌套Java类的特点:
  1. 它们仅存在于对象中,因此要创建它们,您需要一个对象。换句话说:我们将机翼设计为飞机的一部分,因此要创建机翼,我们需要飞机,否则我们不需要它。
  2. Java 类中不能有静态变量。如果您需要一些常量或其他静态内容,则需要将它们移至外部类。这是由于非静态嵌套类与外部类的紧密耦合所致。
  3. 该类可以完全访问外部类的所有私有字段。此功能有两种工作方式。
  4. 您可以获得对外部类实例的引用。示例:Airplane。这是飞机的链接,这是机翼的链接。

外部类中的静态类

这种类型的类与常规外部类没有什么不同,除了一件事:要创建此类类的实例,您需要列出从外部类到所需外部类的整个路径,并用点分隔。例如:Building.Plaftorm platform = new Building.Platform(); 静态类用于将相关类并排放置,以便逻辑结构更易于使用。例如:我们可以创建一个外部类Building,其中会有代表特定建筑物的特定类列表。
public abstract class Building {
    private String name, address, type;

    Building(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public static class Platform extends Building {
        public Platform(String name, String address) {
            super(name, address);
            setType("Platform");
        }

        // some additional logic
    }

    public static class House extends Building {
        public House(String name, String address) {
            super(name, address);
            setType("House");
        }

        // some additional logic
    }

    public static class Shop extends Building {
        public Shop(String name, String address) {
            super(name, address);
            setType("Shop");
        }

        // some additional logic
    }

    // getters/setters
}
此示例演示静态类如何允许您将逻辑结构打包为更方便的形式。如果它们不存在,我们将需要创建 4 个完全不同的类。 这种方法的优点:
  1. 班级数量减少了。
  2. 所有类都位于其父类内。我们能够跟踪整个层次结构,而无需单独打开每个类。
  3. 我们可以参考Building类,IDE已经提示了该类所有子类的完整列表。这将使您更容易找到所需的课程,并更全面地展示整个情况。
创建嵌套静态类实例的示例:Building.Shop myShop = new Building.Shop(“Food & Fun!”, “Kalyaeva 8/53”); 我还想指出,此策略在 AWT 2D 类中用于描述形状,例如 Line2D、Arc2D、Ellipse2D 等。

本地课程

这些类在其他方法中声明。事实上,它们具有非静态嵌套类的所有属性,只是它们的实例只能在方法中创建,并且该方法不能是静态的(要创建它们,您需要一个外部类的实例,对调用对象的实例隐式传递给非静态方法,并且在静态方法中没有此链接的方法)。 但他们也有各自的特点:
  1. 本地类只能使用最终方法变量。问题是,本地类的实例可以在方法完成后存储在堆中,并且可以删除变量。如果该变量被声明为final,则编译器可以保存该变量的副本以供对象稍后使用。还有一件事:从 Java 8+ 版本开始,您可以在本地类中使用非最终变量,但前提是它们不会改变。
  2. 局部类不能用访问修饰符声明。
  3. 本地类可以访问方法变量。
本地类非常罕见,因为它们使代码难以阅读,并且除了访问方法变量之外没有任何优点。我不知道可以采取什么本地类的例子来展示它们的有效使用,所以我只展示我的例子。假设我们有一个类Person(假设这是一个人),其属性为street(街道)、house(房屋)。我们想返回一些对象来访问该人的位置。为此,我们创建了 AddressContainer 接口,该接口意味着存储有关人员位置的数据。
public class Person {
    private String name, street, house;

    public Person(String name, String street, String house) {
        this.name = name;
        this.street = street;
        this.house = house;
    }

    private interface AddressContainer {
        String getStreet();
        String getHouse();
    }

    public AddressContainer getAddressContainer() {
        class PersonAddressContainer implements AddressContainer {
            final String street = Person.this.street, house = Person.this.house;

            @Override
            public String getStreet() {
                return this.street;
            }

            @Override
            public String getHouse() {
                return this.house;
            }
        }

        return new PersonAddressContainer();
    }

    public static void main(String[] args) {
        Person person = new Person("Nikita", "Sholohova", "17");

        AddressContainer address = person.getAddressContainer();

        System.out.println("Address: street - " + address.getStreet() + ", house - " + address.getHouse());
    }

    // getters/setters
}
正如你所看到的,在方法内部,我们创建了一个类来实现人员位置的存储,在那里创建了常量变量(以便在退出方法后,变量被存储在一个对象中),并实现了一个用于获取地址和位置的方法。房子。现在我们可以在程序的其他地方使用这个对象来获取一个人的位置。我知道这个例子并不理想,简单地把 getter 留在类中会更正确Person,但是,已经显示了这个类的创建及其可能的用途,然后就由你决定了。

匿名类

在幕后,匿名类只是常规的非静态嵌套类。它们的特点是易于使用。您可以在创建另一个类的实例时直接编写您的类。
public class Animal {
    public void meow() {
        System.out.println("Meow!");
    }

    public static void main(String[] args) {
        Animal anonTiger = new Animal() {
            @Override
            public void meow() {
                System.out.println("Raaar!");
            }
        };

        Animal notAnonTiger = new Animal().new Tiger();

        anonTiger.meow(); // будет выведено Raaar!
        notAnonTiger.meow(); // будет выведено Raaar!
    }

    private class Tiger extends Animal {
        @Override
        public void meow() {
            System.out.println("Raaar!");
        }
    }
}
本质上,我们只是将两件事组合在一个地方:创建一个类的实例 ( Animal) 并创建其继承者内部类的实例 ( Tiger)。否则,我们需要单独创建类并使用更长的构造来实现相同的结果。 在许多情况下,使用匿名类是合理的,特别是在以下情况下:
  • 班级体很短;
  • 仅需要该类的一个实例;
  • 该类在创建它的地方或在创建它之后立即使用;
  • 类名并不重要,也不会让代码更容易理解。
GUI 中经常使用匿名类来创建事件处理程序。例如,要创建一个按钮并对其单击做出反应:
JButton b2 = new JButton("Click");
b2.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Кнопка нажата!");
    }
});
然而,在 Java 8 之后,他们开始使用 lambda 表达式,但仍然有很多代码是在版本 8 之前编写的,您可能会遇到(并且在 JavaRush 培训期间也会遇到)这样的铭文。\ 与 lambda 类似:
JButton b2 = new JButton("Click");
b2.addActionListener(e -> System.out.println("Кнопка нажата!"));
文章结束 感谢大家的关注,我希望您学到一些新的东西或理解一些您以前不理解的东西。我还想澄清一下,这篇文章属于“注重细节”类别。这是我的第一篇作品,所以我希望它对某人有用。在不久的将来,当新的想法出现时,我会尝试写点别的东西,我只有一个想法......祝大家好运,编程成功:)
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION