大家好。在這個主題中,我想詳細討論 Java 類別及其類型,以幫助初學者理解這個主題,或許非新手也能學到新東西。在可能的情況下,所有內容都將使用現實生活中的範例以及隨附的程式碼範例來顯示。讓我們開始吧。 我想指出的是,主要的是了解前兩種類型的類,本地類和匿名類只是內部類的子類型。
什麼是班級?
類別是某事物的邏輯描述,是一個模板,您可以使用它來創建該事物的真實實例。換句話說,它只是對創建的實體應該是什麼樣子的描述:它們應該具有什麼屬性和方法。 屬性是實體的特徵,方法是實體可以執行的操作。現實生活中類別的一個很好的例子可以被認為是繪圖,它可以幫助您理解類別是什麼:繪圖用於描述結構(彈射器、螺絲起子),但繪圖不是設計。正如工程師使用藍圖來創建設計一樣,程式設計使用類別來建立描述屬性和方法的物件。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 個種類包含在另一個類別中:-
巢狀內部類別是外部類別內部的非靜態類別。
-
巢狀靜態類別是外部類別內部的靜態類別。
-
Java 本機類別是方法內的類別。
-
匿名 Java 類別是動態建立的類別。
外部類別中的非靜態類
首先,我想讓你透過一個真實的例子來理解這是什麼,因為這樣比較容易理解。所以現在我們將把一個真正的大東西分解成更小的部件,我們將拆解一架飛機!然而,為了舉例,展示一點就足夠了;我們不會完全分解它。為了形象化這個過程,我們將使用飛機圖。 首先,我們需要建立一個類,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類別的特點:
- 它們僅存在於物件中,因此要建立它們,您需要一個物件。換句話說:我們將機翼設計為飛機的一部分,因此要創建機翼,我們需要飛機,否則我們不需要它。
- Java 類別中不能有靜態變數。如果您需要一些常數或其他靜態內容,則需要將它們移至外部類別。這是由於非靜態嵌套類別與外部類別的緊密耦合所致。
- 該類別可以完全存取外部類別的所有私有欄位。此功能有兩種工作方式。
- 您可以獲得外部類別實例的參考。範例: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 個完全不同的類別。 這種方法的優點:
- 班級數量減少了。
- 所有類別都位於其父類別內。我們能夠追蹤整個層次結構,而無需單獨開啟每個類別。
- 我們可以參考Building類,IDE已經提示了該類別所有子類別的完整清單。這將使您更容易找到所需的課程,並更全面地展示整個情況。
Building.Shop myShop = new Building.Shop(“Food & Fun!”, “Kalyaeva 8/53”);
我還想指出,此策略在 AWT 2D 類別中用於描述形狀,例如 Line2D、Arc2D、Ellipse2D 等。
本地課程
這些類別在其他方法中聲明。事實上,它們具有非靜態嵌套類別的所有屬性,只是它們的實例只能在方法中創建,並且該方法不能是靜態的(要創建它們,您需要一個外部類別的實例,對呼叫物件的實例隱式傳遞給非靜態方法,並且在靜態方法中沒有此連結的方法)。 但他們也有各自的特色:- 本地類別只能使用最終方法變數。問題是,本地類別的實例可以在方法完成後儲存在堆中,並且可以刪除變數。如果該變數被宣告為final,則編譯器可以保存該變數的副本以供物件稍後使用。還有一件事:從 Java 8+ 版本開始,您可以在本地類別中使用非最終變量,但前提是它們不會改變。
- 局部類別不能用存取修飾符聲明。
- 本地類別可以存取方法變數。
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
)。否則,我們需要單獨創建類別並使用更長的構造來實現相同的結果。 在許多情況下,使用匿名類別是合理的,特別是在以下情況下:
- 班級體很短;
- 僅需要該類別的一個實例;
- 該類別在創建它的地方或在創建它之後立即使用;
- 類別名稱並不重要,也不會讓程式碼更容易理解。
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("Кнопка нажата!"));
文章結束 感謝大家的關注,我希望您學到一些新的東西或理解一些您以前不理解的東西。我還想澄清一下,這篇文章屬於「注重細節」類別。這是我的第一篇作品,所以我希望它對某人有用。在不久的將來,當新的想法出現時,我會嘗試寫點別的東西,我只有一個想法......祝大家好運,編程成功:)
GO TO FULL VERSION