JavaRush /Java Blog /Random-TW /類別、嵌套類別的類型及範例
Ярослав
等級 40
Днепр

類別、嵌套類別的類型及範例

在 Random-TW 群組發布
大家好。在這個主題中,我想詳細討論 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