質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

16562閲覧

コンストラクタを使わない方法

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2016/09/11 12:31

http://d.hatena.ne.jp/aufheben/20110129/1296328721

こちらのサイトを参考にしました。

Java

1public class Main { 2 3 public static void main(String[] args) { 4 Function0<Integer> c1 = newCounter(); 5 println(c1.apply()); 6 println(c1.apply()); 7 println(c1.apply()); 8 println(c1.apply()); 9 println(c1.apply()); 10 } 11 12 static Function0<Integer> newCounter() { 13 // 変更可能とするためオブジェクトでラップする。 14 final IntHolder i = new IntHolder(0); 15 // ↓これがクロージャ。 16 return new Function0<Integer>() { 17 public Integer apply() { 18 // 関数の外部の変数を参照/変更する。 19 return ++i.value; 20 } 21 }; 22 } 23 24 static void println(Object o) { 25 System.out.println(o); 26 } 27 28 interface Function0<R> { 29 R apply(); 30 } 31 32 class IntHolder { 33 public int value; 34 public IntHolder(int value) { 35 this.value = value; 36 } 37 } 38 39 40}

元の記事はクロージャーに関するものですが、質問はクロージャーについてではありません。
上のコードを実行しようとすると、
Error:(14, 29) java: staticでない変数 thisをstaticコンテキストから参照することはできません
と出ます。
おそらく

Java

1final IntHolder i = new IntHolder(0);

でインスタンスを生成しようとした時に、当然コンストラクタが呼ばれるわけですが、その際にコンストラクタ内で用いられるthisがstaticではないからエラーが出ているのだと思います。
そうすると、上のようにstaticメソッド内でフィールドの値を設定したインスタンスを生成しようとすると、どのようにしたらいいのでしょうか?
回答お願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

あなたの推察は全く関係ありません。
問題は、IntHolderがMainの非static内部クラスであることに求められます。
これが原因で、IntHolderインスタンスを生成するためには、以下のようにMainのインスタンスが必要になります。

java

1IntHolder i = new Main().new IntHolder(0);

上記コードではこのMainインスタンスが指定されていないので、自分自身(this)に対してIntHolderを生成するように解釈しますが、それはstaticメソッドでは無理だよ、と言っているわけです。わかりにくいですね。

ちなみにEclipseで同じコードを書くと、次のようなエラーメッセージになります。

アクセス可能な型 Main のエンクロージング・インスタンスがありません。型 Main のエンクロージング・インスタンスで割り振りを限定する必要があります (例えば x.new A() で、x は Main のインスタンス)。

解決策は上記に示したMainインスタンスを生成する他に、IntHolderクラスをstaticにすることが挙げられます。

投稿2016/09/11 12:46

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/11 13:30

なるほど、原因はわかりました。 エラーメッセージの意味がよく理解できないのですが、回答の >自分自身(this)に対してIntHolderを生成するように解釈しますが、それはstaticメソッドでは無理だよ ここでの自分自身とはMainクラスのことでしょうか? また、非staticインナークラスのインスタンスの生成ではアウタークラスのインスタンスが必要ですから、メソッドがstaticであろうと 非staticであろうと関係ないように思えるのですが。
swordone

2016/09/11 13:39

> ここでの自分自身とはMainクラスのことでしょうか? このメソッドを起動した対象になる、Mainクラスのインスタンスのことです。 メソッドが非staticなら、自分自身のインスタンスを使って処理します。非staticメソッドからはフィールド変数が参照できるのと同じ理屈です。
退会済みユーザー

退会済みユーザー

2016/09/11 13:52

いまいち理解できていないのですが、thisはMainクラスのインスタンスということですね。 そして、エラーメッセージのthisもMainクラスのインスタンスということですが、メソッドがstaticかどうかは関係ないように思えるのですが、関係あるのでしょうか? 実際、newCounter()がstaticでなくともエラーを吐き出しますよね?
退会済みユーザー

退会済みユーザー

2016/09/11 14:01

あー、すいません。 理解できたと思います。 非staticメソッドであれば、自分自身の参照を省略しても良いから、もしこのnewCounter()が非staticであれば、this.new IntHolder(0)となって、インスタンスを生成することができるというわけですね?
swordone

2016/09/11 14:05 編集

メソッドがstaticの場合、特定のインスタンスに対する操作ができません。「静的な」メソッドのため、「動的に」生成されるインスタンスにはさわれないのです。 非staticなメソッドから他の非staticメソッドを呼び出す場合は、そのメソッドの前に"this."が省略されている状態なのですが、インスタンスにさわれないstaticメソッドからはthisを使えないのでエラーになるのです。 newCounter()を非staticにした場合にエラーになるのは、今度はstaticなmainメソッドから非staticメソッドを呼びだそうとしたからで、原因となる場所が変わっただけです。
swordone

2016/09/11 14:02

被ってしまいましたが、そのとおりです。
退会済みユーザー

退会済みユーザー

2016/09/11 14:04

もちろんその場合は Function0<Integer> c1 = newCounter(); と単にするだけではエラーになってしまいますので、Mainクラスのインスタンスを生成してそのメソッドとして呼び出す必要があるわけですが。
退会済みユーザー

退会済みユーザー

2016/09/11 14:11 編集

なんどもすいません。 「さわる」というのはどういう意味で使われていますか? 単に非staticメソッドでは、thisが隠れていることがあるが、staticメソッドではthisが追加されることはないという意味でしょうか?
swordone

2016/09/11 14:11

アクセスする、という意味で使いました。紛らわしくて申し訳ない。
退会済みユーザー

退会済みユーザー

2016/09/11 14:15

回答ありがとうございました。
guest

0

class IntHolder の宣言位置がクラスの中になってるので、これはいわゆるインナークラスになります。
インナークラスの中から this を参照するとインナークラスの実体が必要になりますが、 インナークラスはアウタークラスのメンバー変数みたいなものですから、 static メソッドでアウタークラスの実体がない状況ではインナークラスの実体にアクセスできません。

上のようにstaticメソッド内でフィールドの値を設定したインスタンスを生成しようとすると、どのようにしたらいいのでしょうか?

IntHolder を別クラスとして定義すれば良いと思います。

投稿2016/09/11 12:56

mit0223

総合スコア3401

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/11 13:33

回答ありがとうございました。 原因については理解できました。 別質問での補足について色々調べている最中です。 情報がまとまり次第返答致しますので、お返事いただければ幸いです。 エラーメッセージのstaticではない変数thisは上のコードのインナークラスの参照を表すthisのことなのでしょうか?
mit0223

2016/09/11 13:41

> エラーメッセージのstaticではない変数thisは上のコードのインナークラスの参照を表すthisのことなのでしょうか? はい、IntHolder のコンストラクタに出てくる this だと思います。
swordone

2016/09/11 13:44

違いますよ。インナークラスの参照ではなく、new IntHolder()する対象となるMainインスタンスのことです。
mit0223

2016/09/11 13:56

swordone さん、ご指摘ありがとうございます。訂正します。new IntHolder() は this.new IntHolder() という意味になっており、この this がだめなんですね。いや、xxx.new なんて始めてみましたが、この内側インスタンスが外側インスタンスの管理下にあるので、 new も外側インスタンスのメソッド的扱いなんですね。
退会済みユーザー

退会済みユーザー

2016/09/11 14:15

回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問