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

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

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

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

Q&A

解決済

7回答

9096閲覧

ループ中の関数で1週目に一度だけ行う処理

koiju

総合スコア11

Java

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

0グッド

1クリップ

投稿2017/09/05 04:22

編集2017/09/05 06:23

###実現したいこと
java勉強中の初心者です
ループの一週目のみ関数で特定の処理(セットアップ)をさせたいです
関数中の変数のみで実現させたいです
どうかよろしくお願いします
###実現させたい動き

java

1//メンバ変数の例 2//実行結果 3//一度きり 4//関数稼働中 5//関数稼働中 6//関数稼働中 7//...(以下略 8 9package test; 10 11public class Test{ 12 static boolean flag = false; 13 14 public static void main(String[] args) { 15 while(true){ 16 method(); 17 } 18 } 19 20 static void method(){ 21 if(flag ==false){ 22 System.out.println("一度きり"); 23 flag=true; 24 } 25 System.out.println("関数稼働中"); 26 } 27}

###該当のソースコード
(下記のコードはループのたびに初期化されるため,狙った動きができてません

java

1//関数内の変数のみで上のコードと同じ結果を出したい 2//実行結果 3//一回だけ 4//関数稼働中 5//一回だけ 6//関数稼働中 7//一回だけ 8//...(以下略 9 10package javaapplication43; 11 12public class JavaApplication43{ 13 14 public static void main(String[] args) { 15 while(true){ 16 makeMenu(); 17 makeButton(); 18 } 19 } 20 21 static void makeMenu(){ 22 boolean flag = true; 23 if(flag == true){ 24 //具体例,最初の一週目のみメニューを作りaddする 25 //変数の宣言 26 //ループ外でまとめて宣言は避けたいです 27 //セットアップ処理 28 System.out.println("一度きり"); 29 flag = false; 30 } 31 System.out.println("関数稼働中"); 32 //具体例,二週目以降は描画の更新のみ 33 } 34 35 static void makeButton(){ 36 //具体例,最初の一週目のみボタンとなる画像をロード、ボタンを作る 37 //具体例,二週目以降は描画の更新のみ 38 } 39}

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

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

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

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

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

m.ts10806

2017/09/05 04:27

1度しか実行しないのであればループは不要では・・?
m.ts10806

2017/09/05 04:28

というか最初にご提示のコードも無限ループしそうですけど。
fuzzball

2017/09/05 05:02

なぜグローバル変数(という表現は間違っているような気がしますが)を使いたくないのでしょうか?
koiju

2017/09/05 05:34

それぞれ初期セットが必要な関数を用意してループさせた時、関数の数だけグローバル変数を用意したくないからです
koiju

2017/09/05 05:35

mts10806さんの仰る通り質問に不備がありました申し訳ありません。直させてもらいます。
fuzzball

2017/09/05 05:39

状況を把握しきれていませんが、一つのフラグを共用できないのでしょうか?
退会済みユーザー

退会済みユーザー

2017/09/05 23:34

フラグが複数になって困るなら、mapに入れればいいだけ。 ※containerを利用
guest

回答7

0

ベストアンサー

C言語でのstaticなローカル変数みたいなのが欲しいと言うことでしょうか?

C

1#include <stdio.h> 2#include <stdbool.h> 3void method(void) 4{ 5 static bool flag = false; 6 if (flag == false) { 7 printf("一度きり\n"); 8 flag=true; 9 } 10 printf("関数稼働中\n"); 11} 12int main(void) { 13 for (int i = 0; i < 5; i++) { 14 method(); 15 } 16}

上と同じような事をJavaでもしたい。ただしflagmethod内で定義して、methodと共に管理され、method以外からは見えないようにしたい。そんな感じでしょうか。

結論から言うと、全く同じようにJavaで書くことは無理です。Javaにはstaticなローカル変数というものが無いため、関数内の全てのローカル変数は関数の終了と共に全て破棄されます(オブジェクトが破棄されるでは無い事に注意してください)。

条件を緩めて、とりあえずフラグの部分がそれぞれの関数で独立し、かつ、まとまって表記されていればいいと考えると二つの方法が考えられます。

  1. 関数型インターフェースのオブジェクト等を返すメソッドにする。
  2. staticなネストクラスとしてまとめる。

最初の1.のmomon-gaさんが書いている方法です。momon-gaさんはラムダ式を使って関数型インターフェースのオブジェクトを返していますが、Java7以前でも局所クラスや匿名クラスのオブジェクトを返す事で実現は可能です。ひとつ欠点を言えば、final(または実質firnal)な変数しかラムダ式や局所クラス・匿名クラスの内部で使えないため、プリミティブ型であるbooleanをそのまま使えないことです。momon-gaさんのコードのように真偽値を管理するなんらかのラッパーを用意する必要があります。

次の2.は下記のような感じです。

public class Test { public static void main(String[] args) { for (int i = 0; i < 5; i++) { Method.method(); } } static class Method { static boolean flag = false; static void method() { if (flag ==false) { System.out.println("一度きり"); flag = true; } System.out.println("関数稼働中"); } } }

やっていることはもともとのstaticフィールドを使っていることと変わりありません。違いは、ネストクラスの中でまとまって書いてあるかどうかぐらいです。ネストクラス名が違っていればそれぞれのフィールドは独立していますので、同じフィールド名やメソッド名を使うことができます。この方法はTestクラスのstaticフィールドの名前空間を汚さないぐらいしかメリットがありません。あまりにも複雑になる場合は、それぞれ完全に独立したクラスにすることを検討した方が良いかもしれません。

投稿2017/09/05 22:23

raccy

総合スコア21733

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

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

koiju

2017/09/06 06:50

ありがとうございます とても参考になりました
guest

0

たぶん、javaでクロージャーみたいなことをやりたいのだと理解しました。

ということで、擬似コードを書いてみました。
とはいえ、ぶっちゃけ、Java1.8あまりさわってないので、小汚いです。
むりくり感がはんぱないので、どなたかキレイにしてもらえれば。

java.util.functionもろくに調べずに使ってます・・・

java

1import java.util.function.Supplier; 2 3public class HogeClo { 4 public static void main(String[] args) { 5 // while だと無限ループなので、5回にしてます 6 Supplier<String> makeMenu = makeMenu(); 7 Supplier<String> makeButton = makeButton(); 8 for (int i = 0; i < 5; i++) { 9 makeMenu.get(); 10 makeButton.get(); 11 } 12 } 13 14 15 private static Supplier<String> makeMenu() { 16 final MyBool b = new MyBool(); 17 return () -> { 18 if(b.getBool()) { 19 b.setBool(false); 20 System.out.println("一度きり:menu"); 21 } else { 22 System.out.println("関数稼働中:menu"); 23 } 24 return null; 25 }; 26 } 27 28 private static Supplier<String> makeButton() { 29 final MyBool b = new MyBool(); 30 return () -> { 31 if(b.getBool()) { 32 b.setBool(false); 33 System.out.println("一度きり:Button"); 34 } else { 35 System.out.println("関数稼働中:Button"); 36 } 37 return null; 38 }; 39 } 40 41 // boolean を 変更可能にするためラップする 42 static class MyBool { 43 boolean b = true; 44 public void setBool(boolean b) { 45 this.b = b; 46 } 47 public boolean getBool() { 48 return b; 49 } 50 } 51}

実行結果

Java

1一度きり:menu 2一度きり:Button 3関数稼働中:menu 4関数稼働中:Button 5関数稼働中:menu 6関数稼働中:Button 7関数稼働中:menu 8関数稼働中:Button 9関数稼働中:menu 10関数稼働中:Button

投稿2017/09/05 11:54

momon-ga

総合スコア4820

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

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

koiju

2017/09/05 13:14

回答ありがとうございます 仰る通り、状態を保持し続けることができる関数を実現したいです
退会済みユーザー

退会済みユーザー

2017/09/05 23:51 編集

ThreadLocal クラスみたいなことをやりたい?
guest

0

引数で指定すのは駄目でしょうか?

java

1 public static void main(String[] args) { 2 boolean flag = false; 3 while(true){ 4 method(flag); 5 flag = true 6 } 7 } 8 9 static void method(boolean flag){ 10 if(flag==false){ 11 System.out.println("一度きり"); 12 } 13 }

投稿2017/09/05 04:31

編集2017/09/05 04:33
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

momon-ga

2017/09/05 12:04

これで十分な気がします。
guest

0

「ループ」について具体的に要件を定めないと多分答えが出ません。

###2017.9.6大修正

java

1while(条件){ 2 反復処理 3}

というループについてならば最初の一回限りの処理を追加するならば↓のようになります。

java

1一回限りの処理 2while(条件){ 3 反復処理 4}

投稿2017/09/05 14:49

編集2017/09/06 13:50
HogeAnimalLover

総合スコア4830

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

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

raccy

2017/09/05 22:30

Javaにはstaticローカル変数はありません。 static bool f = true; のような書き方をメソッド内で書くことはできません。
HogeAnimalLover

2017/09/06 13:48

おっと、失礼しました。訂正しておきます。
guest

0

BA出ているけど、私だったらどうするかのアイデア。
薦められる方法でもないので、読み流して下さい。

汚い書き方ですが、名前やコメントでガチガチに固めればまず変な変更をする人はいないかなと思います。

java

1 // makeMenuが実行されたか管理する。 2 // 他の関数からの代入は禁止(必要な時はmakeMenuクラスを作り再設計) 3 static boolean makeMenuIsFirstExecute = true; 4 5 static void makeMenu(){ 6 if(makeMenuIsFirstExecute){ 7 System.out.println("一度きり"); 8 makeMenuIsFirstExecute = false; 9 } 10 System.out.println("関数稼働中"); 11 }

なんでもかんでも言語の機能で実現させなくてはいけないという訳でもないと思います。(言語の機能があるならそちらの方が意図がわかりやすくて良い方法だとは思います。)

影響範囲が局所的であるうちは例外的な書き方をしても、良いような気がします。もちろん、それに値する効果がある場合に限られますが・・・

投稿2017/09/09 01:17

iwamoto_takaaki

総合スコア2883

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

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

0

後半のコードで言うと、makeMenu()makeButton()を別クラスに切り出して、フラグをクラス変数で持つ。

投稿2017/09/05 06:40

fuzzball

総合スコア16731

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

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

koiju

2017/09/05 06:52 編集

回答ありがとうございます 同じ動きは実現できますが、関数中の変数のみで解決したいです。
fuzzball

2017/09/05 06:52

それはなぜですか?
guest

0

flagがfalgになっているからとかそういうオチでしょうか?
でもそれだとコンパイル通らないでしょうし。
そもそもコンパイルが通らないという質問でしょうか?
考え方は関数内のstatic変数で良いと思います。
もしくは、一度だけ実行したい処理がループ内先頭にあるなら、ループ前に処理してしまってもいいと思います。

Java

1 public static void main(String[] args) { 2 System.out.println("一度きり"); 3 while(true){ 4 method(); 5 } 6 } 7 static void method(){ 8 } 9

投稿2017/09/05 04:29

編集2017/09/05 05:42
ttyp03

総合スコア16996

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

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

ttyp03

2017/09/05 05:23

なぜマイナス。意味わからん。
koiju

2017/09/05 12:22

マイナスとはどういうことでしょうか?
ttyp03

2017/09/05 23:23

いや、マイナス評価がついていたのでなんでだろう?ということです。
ttyp03

2017/09/05 23:25

raccyさんの回答で理由がわかりました。 Javaだとstaticローカル変数は定義できないのですね。 失礼しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問