簡體   English   中英

有些類需要初始化,有些則不需要

[英]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等上運行時返回WindowsConsoleMacConsole等實例。如果WindowsConsoleMacConsole擴展了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM