[英]Some classes need initialization and some don't
我已經嘗試搜索“使用新關鍵字”的答案,但沒有找到我的具體問題的答案。
為什么有些類必須使用關鍵字new創建,有些則不需要
例如 :
import java.io.BufferedReader
如果要使用此功能,則必須創建新實例
BufferedReader read = new BufferedReader (..............)
但是例如使用system.console
也需要import java.io.console
。 當你想使用它時你只需鍵入Console c = system.console()
我是Java和OO編程的初學者,在我的書中找到了幾個這樣的例子。
謝謝你的幫助
在java中,字段(aka Attributes)始終與實例或類相關聯。
可能有很多類的實例,要創建實例,您必須使用new
運算符。 要訪問與實例相關的屬性,您需要創建一個,這將作為訪問
ClassName instanceName = new ClassName();
instanceName.methorOrAttributeNameGoesHere
對於類關聯屬性,靜態屬性可以直接訪問為ClassName.methorOrAttributeNameGoesHere
這些是Java的基礎知識,你可能應該首先閱讀一些關於Java和OOP的好書,比如'Head First Java'
對此的簡單回答是,像new BufferedReader()
這樣的實例化每次調用時都會創建一個不同的實例; 調用System.console()
類的方法可能會也可能不會為您提供不同的實例。
最終,所有對象都通過new
實例化; 你可能在代碼中看不到它。
這里有幾種方法,其中System.console()
可能會實現(完全簡化,實際上並不喜歡它):
// (1) Returns new instance each time
class System {
static Console console() {
return new Console();
}
}
要么
// (2) Returns same instance each time
class System {
private static final Console CONSOLE = new Console();
static Console console() {
return CONSOLE;
}
}
(實現它的方法有很多種,這只是兩個例子。你可以通過查看源代碼看到它在OpenJDK中的實現方式 - 它與(2)類似,因為每次返回相同的實例,還有一些我不想在此描述的並發症)
在(1)中,如果您兩次調用System.console()
,您將返回兩個不同的Console
實例:
System.console() != System.console()
在(2)中,如果您兩次調用System.console()
,您將返回相同的Console
實例:
System.console() == System.console()
我在這里要問的問題是,如果我回到不同的實例或同一個實例,我是否需要關心? 如果API設計師做了一個合理的工作,答案可能不是 。
關於是否公開創建新Console
是由編寫類的人做出的。 每次調用該方法時,他/她可能不希望您創建不同的實例有很多原因,例如:
每次調用該方法時,他/她可能希望您創建單獨的實例有多種原因,例如:
您可能不希望用戶直接調用構造函數的原因有很多:
new Console()
完全創建了Console
的實例; 控制台之類的東西通常依賴於平台,因此您可能希望在Windows,MacOS等上運行時返回WindowsConsole
, MacConsole
等實例。如果WindowsConsole
和MacConsole
擴展了Console
,則可以從System.console()
返回其中任何一個System.console()
方法。 在Java 7中引入菱形運算符<>
之前,必須在new
語句中包含完整的泛型參數,例如ArrayList<HashMap<String, List<String>>> list = new ArrayList<HashMap<String, List<String>>>();
; 但是,泛型方法允許將其寫為ArrayList<HashMap<String, List<String>>> list = newList()
:
<T> List<T> newList() { return new ArrayList<T>(); }
(有時,您需要將大量參數傳遞給構造函數,並且使用Builder模式很方便。這與問題中的情況無關,但這是不直接調用構造函數的原因。)
問題是這些是內部實現細節,應該封裝 :作為Console
類的用戶,您不需要關心創建它的成本,或者是否存在共享狀態:您只需要一個Console
。
這種封裝是通過提供類似System.console()
的方法實現的:您不需要知道該方法是否像上面的(1)或(2)那樣實現(或任何其他方法)。
另外,如果類最初編寫為(1),並且證明存在問題,則可以將其實現更改為(2),而不需要您作為System
類的用戶更新代碼。
對初學者來說這可能有點太多細節,我可以嘗試幫助你理解更多; 它的長短是因為如果不直接創建實例,有時會更好。
System.console,console是靜態的,這就是我們直接使用類名調用它的原因,並且為了調用非靜態方法,我們通常使用objectname.methodname。
java.io.Console類在內部與系統控制台連接。系統類提供了一個靜態方法console()
,它返回Console類的唯一實例。這就是我們以前用來作為Console c = system.console()
。
有關更多詳細信息,請閱讀靜態類和非靜態類方法調用/實例創建。
靜態方法不需要實例,但非靜態方法可以。 System.console()
是靜態的,但new BufferedReader(...).read(...)
不是
當方法的結果永遠不會根據上下文改變時,通常使用靜態方法。 例如:
Math.abs(-3); //will always be 3, no matter what
不過考慮這個課程:
public class Person {
private String name;
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
/*
* In this world, no special characters are allowed in a person's name
*/
public static boolean isValidName(String name) {
if (name.contains("!#$%&(=?") {
return false;
}
return true;
}
}
Person mySister = new Person("Mary");
Person myBrother = new Person("David");
調用Person.getName()
沒有任何意義; 這就像問“一個人的名字是什么?” 沒有說明這個人是誰。 現在,如果你問我“你姐姐的名字是什么?”,那么我可以打電話給mySister.getName()
並給你一個明智的答案。
回復:你的評論“你怎么知道什么時候不用新”
如果您正在嘗試創建一個新的Person對象(想象您剛生了一個孩子),但您想知道您在互聯網上找到的這個神奇的名字是否會被當局接受:
boolean validName1 = Person.isValidName("LordVoldeMort!!!!!"); //returns false
boolean validName2 = Person.isValidName("HarryPotter2016"); //returns true
Person myLittleBabySon = new Person("HarryPotter2016"); //Accepted by authorities
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.