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

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

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

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

Q&A

解決済

3回答

1786閲覧

親クラスの変数を子クラスで変更し、親クラスに返す

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

0グッド

0クリップ

投稿2021/08/26 05:25

編集2021/08/26 10:11

前提

Screen2.javaクラスで定めたメンバ変数を、他のクラスCode.javaで数値の変更を行いたい
継承について理解しきれていない部分がある

###実現したいこと
Screen2.javaの変数iを、Screen2.java内のボタンbtn_Cを押してCode.javaを実行するたびに変更したい
(Code.javaでは、音声の再生および変数iの変更を行いたい)

初歩的な質問で恐縮ですが、ご教授いただければと思います。
よろしくお願い致します。

発生している問題・エラーメッセージ

実行すること自体は可能なのですが、
コンソールにこのようなメッセージが出てしまい、アプリケーション画面を開くことができません。

Exception in thread "main" java.lang.StackOverflowError at java.desktop/sun.awt.CGraphicsDevice.nativeGetScreenInsets(Native Method) at java.desktop/sun.awt.CGraphicsDevice.getScreenInsets(CGraphicsDevice.java:127) at java.desktop/sun.lwawt.macosx.LWCToolkit.getScreenInsets(LWCToolkit.java:498) at java.desktop/java.awt.Window.init(Window.java:519) at java.desktop/java.awt.Window.<init>(Window.java:550) at java.desktop/java.awt.Frame.<init>(Frame.java:426) at java.desktop/java.awt.Frame.<init>(Frame.java:391) at java.desktop/javax.swing.JFrame.<init>(JFrame.java:180) at screen.Screen2.<init>(Screen2.java:27) at screen.Code.<init>(Code.java:16) at screen.Screen2.<init>(Screen2.java:32) at screen.Code.<init>(Code.java:16) at screen.Screen2.<init>(Screen2.java:32)

at screen.Code.<init>(Code.java:16)
at screen.Screen2.<init>(Screen2.java:32)
が無数に繰り返してしまいます。

該当のソースコード

Screen2.java

package screen; import java.awt.Color; import java.awt.Font; import java.math.BigDecimal; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class Screen2 extends JFrame{ int i = 1; public static void main(String args[]) { Screen2 frame = new Screen2(); frame.setVisible(true); } public Screen2() { setTitle("タイトル"); setSize(1450,900); setDefaultCloseOperation(EXIT_ON_CLOSE); JPanel p = new JPanel(); add(p); p.setLayout(null); //C JButton btn_C = new JButton("C"); btn_C.addActionListener(new Code()); btn_C.setBounds(300, 600, 100, 150); p.add(btn_C); } }

Code.java

package screen; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException;; public class Code extends Screen2 implements ActionListener{ Screen2 s = new Code(); public void actionPerformed(ActionEvent e){ Clip clip = null; AudioInputStream audioInputStream; try{ //音を鳴らす String cmdName = e.getActionCommand(); File soundFile = new File("/*音声ファイル*/"); audioInputStream = AudioSystem.getAudioInputStream(soundFile); AudioFormat audioFormat = audioInputStream.getFormat(); DataLine.Info info = new DataLine.Info(Clip.class, audioFormat); clip = (Clip)AudioSystem.getLine(info); clip.open(audioInputStream); clip.start(); //変数iの変更 s.i++; } catch (UnsupportedAudioFileException e1) { e1.printStackTrace(); } catch (LineUnavailableException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } }

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

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

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

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

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

jimbe

2021/08/26 07:11 編集

Sc というクラスが見当たりません。
jimbe

2021/08/26 07:20

Code クラスの actionPerformed メソッドの前に書かれている「//回答箇所」というのは、どういう意味でしょう。 このコードは何かの課題の穴埋め問題の回答なのでしょうか。
退会済みユーザー

退会済みユーザー

2021/08/26 09:00

ひとつのボタンにいくつかのボタンイベントを実装したアプリケーションを作ろうとしており、Code.javaをそのボタンイベントの中の一つとして抜粋しております。 「Sc」や「回答箇所」というのは他のボタンイベントで用いる物でして、質問する際に消去し忘れてしまった物です。 修正させていただきました、失礼しました。
jimbe

2021/08/26 09:16

> ひとつのボタンにいくつかのボタンイベントを実装 なるほど、それで String cmdName = e.getActionCommand(); があるのですね。
xebme

2021/08/26 09:31

継承することで、コンストラクターが循環(Code->Screen2->Code)しています。継承をやめて教科書どおりインナークラスで解決してください。関数型インターフェイスが登場してから、ActionListener のインスタンス代わりに、ラムダ式も使えるようになりました。
guest

回答3

0

ベストアンサー

Screen2.javaクラスで定めたメンバ変数を、他のクラスSc.javaで数値の変更を行いたい

これの理由が

ひとつのボタンにいくつかのボタンイベントを実装したアプリケーションを作ろうとしており、Code.javaをそのボタンイベントの中の一つとして抜粋しております。

のため、「class Screen2 extends JFrame implements ActionListenerとはできない」ということなんでしょうかね?

そういった場合javaでは内部クラス(インナークラス)や匿名クラス(無名クラス)・ラムダ式で済ますことが多いですが、別ファイルに分けたいということでしょうか?

単純にやるならScreen2のインスタンスをCodeに渡せばいいです(button3

めんどくさいので音の再生は省略

java

1import java.awt.event.ActionEvent; 2import java.awt.event.ActionListener; 3import javax.swing.JButton; 4import javax.swing.JFrame; 5import javax.swing.JPanel; 6 7 8public class Sample extends JFrame implements ActionListener { 9 public static void main(String[] args) { 10 new Sample().setVisible(true); 11 } 12 13 int i = 1; 14 15 public Sample() { 16 setSize(300, 300); 17 setLocationRelativeTo(null); 18 setDefaultCloseOperation(EXIT_ON_CLOSE); 19 20 JPanel panel = new JPanel(); 21 add(panel); 22 23 JButton button1 = new JButton("self"); 24 // 自身のactionPerformedを使用 25 button1.addActionListener(this); 26 panel.add(button1); 27 28 JButton button2 = new JButton("inside"); 29 button2.addActionListener(new Inside()); // 内部クラス 30 panel.add(button2); 31 32 JButton button3 = new JButton("outside"); 33 // 内部クラスでないなら、どうにかしてSampleのインスタンスを渡す 34 button3.addActionListener(new Outside(this)); 35 panel.add(button3); 36 37 JButton button4 = new JButton("anonymous"); 38 // 匿名クラス insideと同じ意味だがその場で継承とnewしている 39 button4.addActionListener(new ActionListener() { 40 @Override public void actionPerformed(ActionEvent e) { 41 System.out.println(++i); 42 } 43 }); 44 panel.add(button4); 45 46 JButton button5 = new JButton("lambda"); 47 // ラムダ式 insideと同じ意味だがanonymousをさらに短くした表記 48 button5.addActionListener(e -> System.out.println(++i)); 49 panel.add(button5); 50 51 JButton button6 = new JButton("add twice"); 52 button6.addActionListener(e -> System.out.println(++i)); 53 button6.addActionListener(e -> System.out.println(++i)); 54 panel.add(button6); 55 } 56 57 @Override public void actionPerformed(ActionEvent e) { 58 System.out.println(++i); 59 } 60 61 62 class Inside implements ActionListener { 63 public void actionPerformed(ActionEvent e) { 64 // 内部クラスからは外側(Sample)の変数が見える 65 System.out.println(++i); 66 } 67 } 68} 69 70 71class Outside implements ActionListener { 72 private Sample sample; 73 74 public Outside(Sample sample) { 75 this.sample = sample; 76 } 77 78 public void actionPerformed(ActionEvent e) { 79 System.out.println(++sample.i); 80 } 81}

投稿2021/08/26 09:45

TN8001

総合スコア9801

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

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

xebme

2021/08/26 10:21

インナークラスを定義すると、同じことをコンパイラがやります。インナークラスのバイトコードをみれば分かりますが、インナークラスのコンストラクターの引数は外側のクラスのインスタンスです。つまり、インナークラスが外側のクラスのインスタンスを所有して、処理を委譲 (?)するパターンとなります。継承によらない問題解決ですね。
guest

0

Screen2 と Code が使う/使われる関係であれば、継承は不要です。

java

1package screen; 2 3import java.awt.event.ActionEvent; 4import java.awt.event.ActionListener; 5import java.io.File; 6import java.io.IOException; 7 8import javax.sound.sampled.AudioFormat; 9import javax.sound.sampled.AudioInputStream; 10import javax.sound.sampled.AudioSystem; 11import javax.sound.sampled.Clip; 12import javax.sound.sampled.DataLine; 13import javax.sound.sampled.LineUnavailableException; 14import javax.sound.sampled.UnsupportedAudioFileException; 15import javax.swing.JButton; 16import javax.swing.JFrame; 17import javax.swing.JPanel; 18 19public class Screen2 extends JFrame { 20 int i = 1; 21 22 public static void main(String args[]) { 23 Screen2 frame = new Screen2(); 24 frame.setVisible(true); 25 } 26 27 public Screen2() { 28 setTitle("タイトル"); 29 setSize(1450, 900); 30 setDefaultCloseOperation(EXIT_ON_CLOSE); 31 32 JPanel p = new JPanel(); 33 add(p); 34 p.setLayout(null); 35 36 //C 37 JButton btn_C = new JButton("C"); 38 btn_C.addActionListener(new Code(new Code.Callback() { 39 @Override 40 public void started() { 41 i ++; //変数iの変更 42 } 43 })); 44 btn_C.setBounds(300, 600, 100, 150); 45 p.add(btn_C); 46 } 47} 48 49class Code implements ActionListener { 50 interface Callback { 51 void started(); 52 } 53 private Callback callback; 54 Code(Callback callback) { 55 this.callback = callback; 56 } 57 58 //回答箇所 59 public void actionPerformed(ActionEvent ae) { 60 try { 61 //音を鳴らす 62 File soundFile = new File("/*音声ファイル*/"); 63 AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile); 64 AudioFormat audioFormat = audioInputStream.getFormat(); 65 DataLine.Info info = new DataLine.Info(Clip.class, audioFormat); 66 Clip clip = (Clip) AudioSystem.getLine(info); 67 clip.open(audioInputStream); 68 clip.start(); 69 if(callback != null) callback.started(); 70 } catch (UnsupportedAudioFileException | LineUnavailableException | IOException e) { 71 e.printStackTrace(); 72 } 73 } 74}

投稿2021/08/26 07:32

jimbe

総合スコア13168

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

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

退会済みユーザー

退会済みユーザー

2021/08/26 09:01

ご回答ありがとうございます、参考になります。 また、質問のご指摘もありがとうございました。
guest

0

  1. new Screen2() を実行
  2. コンストラクタ内で new Code() を実行
  3. Code extends Screen2 なので、 Code のコンストラクタ内でまた new Code() を実行

という無限ループになって StackOverflowError になってます。

投稿2021/08/26 05:31

mather

総合スコア6759

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

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

退会済みユーザー

退会済みユーザー

2021/08/26 06:36

ご回答ありがとうございます。 Screen2()の変数をCode()に継承するには、 Code.java内にメソッドを作成し、そのメソッドの中で継承を行う必要がある ということでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問