- PR -

エラーについて

1
投稿者投稿内容
うじ
会議室デビュー日: 2006/01/23
投稿数: 4
投稿日時: 2006-01-23 10:52
jbuilderで別のクラスをインポートして、そのクラスのメソッドを使おうとしています。ですが、インポートはできるのですがメソッドを使おうとすると「static でない メソッド setText() を static コンテキストから参照することはできません。」というエラーが出ます。インポートする側はstaticという記述はしていないのですが、どうしてでしょうか?」教えて下さい。よろしくお願いします。
tnk
会議室デビュー日: 2005/06/10
投稿数: 11
投稿日時: 2006-01-23 11:08
インポートしたクラスのメソッドを
使おうとしているメソッドがstaticだから
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2006-01-23 11:11
まず最初に二つ申し上げておきます。

(1) スレッドの件名
「エラーについて」ではどのようなエラーかわかりません。
何も説明していない「教えてください」よりはマシですが、「エラー:『static でない メソッド setText() を static コンテキストから参照することはできません』について」と書くと、もう少し内容が絞れ、どのようなトラブルに遭遇しているのかがわかりやすくなります。

(2) エラー内容の具体的明示
うじさんの投稿ではエラーメッセージがきちんと引用されています。
これも「何だかエラーが出ていてわかりません」よりはマシですが、どのようなプログラムを書いたところ、どの行で、どういう種類のエラー(コンパイルエラーか実行時エラーか、およびエラーメッセージ全文)が出たかを明示すると、読む人にとって状況がわかりやすくなり、可能であればですが、再現性を検証することもできるやもしれません。

さて本題です。
エラーの意味は読んで字のごとく、main() 等の static メソッドから、static でないメソッドを対象オブジェクト(呼び出し先で this となるオブジェクト)を指定せずに呼び出すとこのエラーが発生します。

例を示します。
コード:
public class StaticInvocationTest {
  public static void main(String[] args) {
    callee(); // main は static だが callee は static でない; エラー

    StaticInvocationTest obj = new StaticInvocationTest();
    obj.callee(); // 同じクラス内のメソッドだが、対象オブジェクト(obj)を指定すると大丈夫
  }

  public void callee() { // 非 static メソッド
  }
}



より詳しい説明をお望みであれば、お手元のソースをコピー&ペーストして書き込んでください。
うじ
会議室デビュー日: 2006/01/23
投稿数: 4
投稿日時: 2006-01-23 11:25
詳しく記述しなくてすみません。自分としては、クラス間を相互にデータを受け渡すようにしたいのです。しかし、クラス同士をお互いにインスタンス化することもできませんでした。その理由としてお互いにインスタンス化してしまうと、再帰呼び出しが何回も起こり「java.lang.StackOverflowErrorなので
うじ
会議室デビュー日: 2006/01/23
投稿数: 4
投稿日時: 2006-01-23 11:36
詳しく記述しなくてすみません。自分としては、クラス間を相互にデータを受け渡すようにしたいのです。しかし、クラス同士をお互いにインスタンス化することもできませんでした。その理由としてお互いにインスタンス化してしまうと、再帰呼び出しが何回も起こり「java.lang.StackOverflowError]というエラーが出てしまいます。
ソースを記述するのでよろしくお願いします。
MakeSongFrameからCodeFrameをインポートして,
CodeFrameのメソッドを使おうとすると、エラーがでてしまいます。
念のため関係ないと思われるApplication1.javaも貼り付けておきます。
お手数ですがよろしくお願いします。

【Application1.java】
package fingerhelp;

import java.awt.Toolkit;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.Dimension;

public class Application1 {
boolean packFrame = false;

public Application1() {
MakeSongFrame frame = new MakeSongFrame();
// validate() はサイズを調整する
// pack() は有効なサイズ情報をレイアウトなどから取得する
if (packFrame) {
frame.pack();
} else {
frame.validate();
}

// ウィンドウを中央に配置
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.
getSystemLookAndFeelClassName());
} catch (Exception exception) {
exception.printStackTrace();
}

new Application1();
}
});
}
}

【CodeFrame.java】

package fingerhelp;

import java.awt.Toolkit;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.Dimension;

public class Application1 {
boolean packFrame = false;

public Application1() {
MakeSongFrame frame = new MakeSongFrame();
if (packFrame) {
frame.pack();
} else {
frame.validate();
}

// ウィンドウを中央に配置
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.
getSystemLookAndFeelClassName());
} catch (Exception exception) {
exception.printStackTrace();
}

new Application1();
}
});
}
}

【MakeSongFrame.java】

package fingerhelp;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JButton;
import fingerhelp.CodeFrame;


public MakeSongFrame() {
try {
setDefaultCloseOperation(EXIT_ON_CLOSE);
jbInit();
challenge();

} catch (Exception exception) {
exception.printStackTrace();
}
}

public void challenge(){
CodeFrame.setText();
}
}








うじ
会議室デビュー日: 2006/01/23
投稿数: 4
投稿日時: 2006-01-23 11:38
二重書き込み、長文ですみません…
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2006-01-23 13:12
気づいた点を何点。

(1) Application1.java が関係ないとうじさんが考えた理由が説明されていません。
(2) CodeFrame.java はコンパイルできません。
なぜならば、public と宣言されたクラス名 Application1 が、ファイル名から拡張子を除いた CodeFrame と一致しないからです。
(3) MakeSongFrame.java はコンパイルできません。
なぜならば、クラス定義がなくいきなりコンストラクタ定義から始まっているからです。
(中括弧の数もあっていないので、コピー&ペースト誤りと思われますが)

(4) 最後に根本的な考え方ですが、互いにインスタンス化すると再帰によりスタックオーバーフローとなるため static にしたというのが最も大きな誤りです。
インスタンス化しようが static にしようが、再帰が止まらなければいずれスタックを食いつぶしてスタックオーバーフローで止まります。(インスタンス化すると少し食いつぶしが早くなりますが)

以下、ソースがまともでないので検証できず、憶測による回答であることをお断りしておきます。

MakeSongFrame が CodeFrame オブジェクトを覚えておくためのフィールド(とアクセッサメソッド setCodeFrame)を新設し、CodeFrame#main の最初で MakeSongFrame#setCodeFrame を呼び出して CodeFrame 自身を覚えさせます。
(この、自分自身というのは this というキーワードで参照できます。)

あとは MakeSongFrame が CodeFrame#setText したい場合、static メソッドではなくその覚えておいた CodeFrame オブジェクトに対して setText すれば再帰が発生せずに済みます。

以上、基本的な考え方でした。
(もう少し高度でスマートな方法もありますが、このスレッドで書くには時期尚早と考えましたので割愛します。)
1

スキルアップ/キャリアアップ(JOB@IT)