7

私はJavaが初めてです。私を混乱させることの 1 つは、一部のクラスをインスタンス化する必要newがある理由と、他の一部のクラスをインスタンス化する必要がない理由newです。

たとえば、私は log4j を見ていますが、必要ありませんnew

// get a logger instance named "com.foo"
Logger  logger = Logger.getLogger("com.foo");
logger.setLevel(Level.INFO);

他のいくつかのクラスが new を必要とするのはなぜですか? たとえば、従業員クラス:

Employee X = new Employee (John);
X.getwork();

などなど

なぜ言わなかったのLogger logger = new Logger(...);ですか?newまた、 、 likelogger.setLevel()などがなくても使用できたのはなぜですか。

4

8 に答える 8

8

Javaで新しいオブジェクトを作成する唯一の方法は、new[1]を使用することです。ただし、一部のクラスではnew、自分で言うことが許可されていないため、ファクトリメソッドを呼び出す必要があります。ファクトリメソッドは、(ロガーの例のように)静的である場合とそうでない場合があります。クラスの作成者は、コンストラクターに。以外のアクセス権を持たせることによってこれを設定しますpublic

また、例には新しいオブジェクトがまったく含まれていない可能性があることにも注意してください。そのLogger関数は、新しいオブジェクトではなく、古いオブジェクトを返している可能性があります。

オグデンナッシュによる次の詩はかすかに関連しているようです:

This morning I went to the zoo 
In order to look at the gnu. 
But the old gnu was dead,
and the new gnu, they said, 
Was too new a new gnu to view.

[1]低レベルの反射に関与したり、使用したりしない限りObject.clone()

于 2012-09-03T22:14:41.770 に答える
3

この場合、コメントで述べたように、ファクトリ メソッドを扱っています。

関連する API 仕様を参照してください。Logger

name パラメータの値に従って名前が付けられたロガーを取得します。指定されたロガーがすでに存在する場合は、既存のインスタンスが返されます。それ以外の場合は、新しいインスタンスが作成されます。

デフォルトでは、ロガーにはレベルが設定されていませんが、レベルが設定された直近の祖先から継承されます。これは、log4j の中心的な機能の 1 つです。

ファクトリ メソッド パターンは創造的な設計パターンであり、ウィキペディアによると、次のような状況で役立つことがよくあります。

factory パターンは、次の場合に使用できます。

  • オブジェクトを作成すると、コードを大幅に複製することなく再利用できなくなります。
  • オブジェクトの作成には、構成クラス内に含まれてはならない情報またはリソースへのアクセスが必要です。
  • 生成されたオブジェクトの有効期間管理は、アプリケーション内で一貫した動作を確保するために集中化する必要があります。

これら 3 つすべてがここで適用できます...正しいロガーを見つけるためにどのような作業が行われるかを誰が知っていますか? ロガーを使用するたびに新しいロガーを作成することにはあまり関心がありません... 代わりに、主にそれを使用することに重点を置いています。

Creative Commons Wiki にも関連記事があります。

ファクトリ メソッドは、いくつかの理由のいずれかで、コンストラクターの代わりに使用されることがあります。

  • 一部の言語 (Java など) では、コンストラクターに有用な名前を付けることができません。
  • 一部の言語 (Java など) では、コンストラクターに異なる名前を付けることができません (これは、2 つのコンストラクターに同じメソッド シグネチャを使用する場合に必要になる場合があります)。
  • 必要なたびに再作成するのではなく、同じインスタンスを再利用できるようにする ( FlyweightPatternを参照)

ここではおそらく 3 番目のオプションが最も適切だと思います。新しい を手動で作成すると、Loggerそれらを適切に共有できません。ファサードを使用getLoggerすると、これを透過的に行うことができます。

全体として、ファクトリ メソッドの使用は通常、必ずしも気にしない作業を公開することなく、よりクリーンで単純なコードを有効にすることです。

于 2012-09-03T22:19:19.487 に答える
2

たとえば、クラスによっては、アプリケーションで複数のオブジェクトを作成できない場合があります。その場合、クラスをインスタンス化するために Logger.getLogger() などのメソッドを呼び出す必要があります。getLogger() には、次のようなコードが含まれる場合があります。

if(uniqueInstance == null) {
    uniqueInstance = new Logger();
}

return uniqueInstance;

uniqueInstance は Logger のインスタンスです。これはSingletonと呼ばれるデザインパターンです。このパターンでは、コンストラクターがプライベートであるため、クラスをインスタンス化できません。

クラスをインスタンス化できない他の方法は、クラスが静的として定義されている場合です。

パブリック コンストラクターを持ち、静的ではないクラスは、new キーワードでインスタンス化する必要があります。

于 2012-09-03T22:17:02.793 に答える
1

オブジェクトLogger.getLogger()を返すためです。コンストラクターを呼び出します。コンストラクターも。を返します。クラス内はおそらく次のようなものであるため、これも一種の使用法です。Loggernew Logger()LoggernewLogger

public class Logger {
     public static Logger getLogger() {
        return new Logger("foo", "bar");
    }
}
于 2012-09-03T22:14:36.260 に答える
1

あなたが求めているのは、デザインパターンにもっと関連しています。Logger クラスはシングルトン パターンに従っています。

アプリケーション全体でクラスのインスタンスを 1 つだけ作成したい場合は、コンストラクターを非公開にし、最初に呼び出されたときにクラスのオブジェクトを作成して保存する静的メソッドを提供できます。

public class SingletonPattern{

    private static SingletonPattern instance;

    private SingletonPattern(){} 

    public static synchronized SingletonPattern getInstance(){
        if (instance == null){
            instance = new SingletonPattern();
        }
        return instance;
    }
}

このようにして、クラスを 1 回だけインスタンス化するように制限できます。

于 2012-09-03T22:41:42.923 に答える
0

あなたの例では、さまざまなユースケースが必要です。オブジェクトを返す静的メソッドと実際のコンストラクター呼び出しです。

静的メソッドは、オブジェクトを呼び出す必要のないメソッドです。ここでは、内部メカニズムがオブジェクトをインスタンス化し、将来の使用のために返すことができます。このメソッドでは、「new」の呼び出しがありますが、オブジェクトが構成されている可能性があります。 、または返される前にキャッシュから取得されます。これはこの種の呼び出しです

Logger  logger = Logger.getLogger("com.foo");

実際のコンストラクター呼び出し(newを使用)は、新しいオブジェクトを作成する通常の方法です。

于 2012-09-03T22:14:21.047 に答える
0

技術的にはLoggerクラスを使用していませんでしたが、メソッドを使用していました。Loggerクラスを技術的にインスタンス化することも、のように直接参照を保持することもありませんでしたLogger logger = new Logger()。代わりに、あなたがしているのは、返されたインスタンスを取り戻すためのメソッドにアクセスすることです。クラスの定義を見るといいでしょう。ただし、おそらくあなたが持っているのはクラス内の静的メソッドです。そして、クラスはおそらくプライベートコンストラクターで定義されています。これにより、クラスをインスタンス化せずにメソッドにアクセスできます。あなたはこれとJavaの静的な説明をここで見ることができます:https ://stackoverflow.com/a/1844388/1026459

于 2012-09-03T22:14:36.593 に答える
0

一部のクラスは、それ自体の外部でインスタンス化できません (たとえば、Mathクラス、これらのクラスには非パブリック コンストラクターがあります)。これらのクラスのうち、クラスのインスタンスを返すメソッドを提供するものがあります (InetAddressクラスなど)。これらはファクトリーメソッドと呼ばれます。これらは、それらがstatic属するクラスのインスタンスを返すメソッドであるため、newキーワードを使用する必要はありません (代わりに、ファクトリ メソッド内で使用されます)。例えば:

public class A {
   private A() {}
   public A createAnA() { return new A(); }
}

これがファクトリcreateAnA()メソッドです。

于 2012-09-03T22:17:27.930 に答える