2012-05-09 1 views
7

私は昨日Javaで試験を受けました。私には本当にあいまいなものがあります。スタティックメソッドによる非静的コンストラクタへのアクセス?

ルールは単純です:

  1. staticメソッドは非静的メソッドを呼び出すことはできませんすることはできません。
  2. コンストラクタは戻り値のないメソッドのようなものです。

    public class Main { 
        public static void main(String[] args) { 
         Main p = new Main(); 
         k(); 
        } 
    
        protected Main() { 
         System.out.print("1234"); 
        } 
    
        protected void k() { 
        } 
    } 
    
    Main p = new Main() line prints 1234 
    k() line raises error 
    

、なぜこれが起こるのですか?上記のJavaのルールと矛盾していませんか?

+3

静的メソッドからコンストラクタを呼び出すことが不可能だった場合は、これまでどんなオブジェクトも構築できませんでした。 –

答えて

10

1 - 非静的メソッドを呼び出すことはできません。

もちろん可能ですが、にはのメソッドを呼び出すオブジェクトが必要です。

静的メソッドでは、foo()(これはthis.foo()に相当)は使用できません。thisの参照はありません。

2 - コンストラクタは戻り値のないメソッドのようなものです。

彼らはcompared to methodsする必要がある場合、私はコンストラクタは非静的メソッド(コンストラクタの内部this参照が実際に存在するため)に近いと言うでしょう。

このように考えると、なぜ静的メソッドがコンストラクタを問題なく呼び出すことができるのかは明らかです。


だから、それを合計します

Main p = new Main(); 

は大丈夫です、new Main()ので、既存のオブジェクトに依存しません。

k(); 

それはthis.k()に相当し、thisがあなたの(静的)mainメソッドでは利用できないので大丈夫ではないです。

+0

'new main()'は単純なコンストラクタ呼び出しではないということは、常に人を混乱させるものです。単項演算子 'new'のアプリケーションで、どのコンストラクタを呼び出すかを指定します**多くのより広い割り当て+初期化手順**。 –

+0

@MarkoTopolnik、JLSリファレンス? – aioobe

+0

それは明白なので、本当に必要ですか? 'new'を適用すると、ヒープからメモリが割り当てられます** - コンストラクタには書き込まれません。**すべてのインスタンスイニシャライザ** - あなたにはっきりと明白な別の事実も呼びます。これはコンストラクタコードのどこにも書かれていません。また、 'this'が突然定義されたコンストラクタを呼び出します - 呼び出し側ではなく暗黙のコードで定義されます。コンストラクタは実際にコールバックに過ぎません。 –

4

いいえ、この点でコンストラクタは普通の方法ではありません。コンストラクタの全体のポイントは、クラスの新しいインスタンスを作成することです。

したがって、静的スコープでも呼び出すことができます。それについて考えてみましょう。新しいインスタンスを作成するためにクラスの既存のインスタンスが必要だった場合は、それを今までにインスタンス化できないだけです。

いくつかの明確化:

staticメソッドは非静的メソッドを呼び出すことはできませんすることはできません。

かなりです。静的メソッド内から非静的メソッドを呼び出すことができます。ちょうどスコープにする必要があります。私。

p.k(); 

は、上記のコードサンプルで完全に機能します。

コール

k(); 

インスタンス(非static)メソッド内部微細であろう。そして、それは

this.k(); 

暗示thisクラスの現在のインスタンスを参照するに相当します。コンパイラーがk()のような非修飾呼び出しをインスタンスメソッド内で見ると、自動的にthis.でそれをスコープします。ただし、静的メソッドはクラスのインスタンスに関連付けられていないため、静的メソッド内のthisを参照することはできません(およびコンパイラ)。したがって、インスタンスメソッドを呼び出すために、クラスのインスタンスに明示的に名前を付ける必要があります。

5

ルールは単純です:
1 - 静的メソッドは非静的メソッドを呼び出すことはできません。

これは単に真実ではありません。静的メソッドは、単に「ターゲット」参照を介して非静的メソッドを呼び出すことができます。たとえば、これは静的メソッドで結構です。

Integer x = Integer.valueOf(10); 
int y = x.intValue(); // Instance method! 

本当ポイントは、「静的メソッド内にはthis参照がありません」です。

2 - コンストラクタは戻り値のないメソッドのようなものです。

これは正直言って本当に便利なモデルではありません。 more(呼び出し元の視点から)、宣言クラスと同じ戻り値の型を持つ静的メソッドとしてコンストラクタを考えることはできますが、それは完全なモデルではありません。

コンストラクタを別のメンバーとして考えることをお勧めします。コンストラクタとメソッドを隠すのではなく、コンストラクタとメソッドの違いを受け入れます。

+0

オブジェクトの初期化の一環として呼び出されるvoidを返すコールバックにコンストラクタを似せるとどう思いますか?その間接的なレベルは、私の心には、人々を逃れ、間違った前提を引き起こすものです。 –

+0

@MarkoTopolnik:それはあなたが*呼び出し元*の観点から考えているかどうかによって決まります(この場合、void戻りはナンセンスです)。それは意味をなさない)。私は方法に邪魔な類推をしようとするのではなく、それを自分のタイプのものと考えるほうが好きです。 –

+0

呼び出し元が単に 'new'を適用していて、関数を呼び出さないという事実を考慮すると、ナンセンスではありません。それは実際に私の主なポイントです - 誰かがそれを見ていない、 '新しい'を尊重する必要があります。その演算子の戻り値は参照値であり、コンストラクタは 'void 'を返すコールバックとみなすことができます。私は類推がこれまでにしか行かないことに同意しますが、何か新しいことを学ぶときにも助けになります。 –

関連する問題