みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

voidの性質や使い方、showメソッドについて

1ファイル1クラスの原則に反しますが、敢えて1ファイルに2クラスあるプログラムにおいて、voidの性質や使い方、showメソッド等について教えてほしいです。
ファイル名はStart.javaです。

---------------------------------
package sample;

class Cat {
String name;
int age;
void show(String name,int age) {
System.out.println("名前は" + name + "です");
System.out.println("年齢は" + age + "歳です");
}
}
public class Start {
public static void main(String[] args) {
Cat cat1 = new Cat();
cat1.name = "太郎";
cat1.age = 28;
cat1.show();
}
}
---------------------------------

「cat1.show();」のところでエラーが出ていますが、Eclipseでそのまま実行してみますと。

~~~~~~~~~~~~~~~~~~~
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
型 Cat のメソッド show(String, int) は引数 () に適用できません

at sample.Start.main(Start.java:16)
~~~~~~~~~~~~~~~~~~~

といったエラーが出てきます。しかし、Catクラスの「void show(String name,int age) 」の箇所を「void show() 」のように、Startクラスと同じく引数の中身を空にしますと。

||||||||
名前は太郎です
年齢は28歳です
||||||||

と、正しい結果が出力されたのです。

最初のプログラムは、Catクラスのshowメソッドには引数があり、Startメソッドのshowメソッドには引数が無い状態でした。
修正したプログラムでは、どちらのクラスのshowメソッドにも引数はありませんでした。

最初のプログラムでも、mainメソッドを実行して、nameとageに値を格納して、showメソッドでCatクラスの方で定義したshowメソッドを呼び出すといった流れで、正しい値は出るはずだと自分は考えたのですが。

なぜエラーになってしまったのか、どうして2つのクラスのshowメソッドの引数が空だとうまく結果が出力されたかにつきまして、お教えいただけないでしょうか。

よろしくお願い致します。

※OKWAVEより補足:「Webシステム開発」についての質問です。

投稿日時 - 2019-07-14 00:18:13

QNo.9635125

すぐに回答ほしいです

質問者が選んだベストアンサー

1歩ひいて考えたとして・・・

ローカル変数をクラス変数に移動するだけの関数。
void set_name(String name) {
this.name=name;
//なぜこんなことをするか?というと
//名前として適切か?をテストしてOKなら代入などの禁則処理ができるため
//いまは、テストでnameですが、例えば名前は漢字か?読みはカタカナか?などをテストできるようにしたいので。
}
void set_age(int age) {
this.age=age;
//なぜこんなことをするか?というと
//年齢として適切か?をテストしてOKなら代入などの禁則処理ができるため
//年齢なのにマイナスだったり、事実上あり得ない1000歳だとかをチェックできます。
}
void show() {
System.out.println("変数の名前は" + this.name + "です");
System.out.println("変数の年齢は" + this.age + "歳です");
}
だったら、OKですよ。

set_xxx系の返り値をBOOLにして、正しく反映できたか?を返し
if (hogehoge.set_xxx(para)!=true) {
/* 設定が不適切だった時の処理 */
}
って書いていけば、あとで、受け付ける文字が変わったり範囲があるものを作ったりしても、
根元で1発で処理できるので、便利ってな。(今回のはサンプルなので、あんまり意味ないけど)

cat1.age = 28;
これだと、どんな値でも入ってしまうのと、代入自体は適切なので、
エラーも出ませんし。値が理想とするものか?をだれもテストできない。
当然変な所でバグがでて、ハマる!ってな。

まだ、"private"や"public"などの属性がないので、
全部"public"ですが、
クラス内の変数と、クラス内の関数のどちらも、
外からアクセスできる/できないについて設定できますよ。

とりあえず、今回の件は、デバッガーがあるなら、
PRINT系命令で一度ブレイクポイントを付けて、
各変数がどこをさしているのか?を見ると、
すぐわかると思いますので。ファイトっす

投稿日時 - 2019-07-14 14:47:27

お礼

ありがとうございます。
はい、

void set_name(String name) {
this.name=name;
}

void set_age(int age) {
this.age=age;
}

のようなコードを読んだことがありまして、なぜこういったことを行うのかが疑問でした。
チェック機能があったんですね(^^;
privateやpublicは確かに、意識して書いてないですね…それも意識できるようになれたら、と思います。

if (hogehoge.set_xxx(para)!=true) {
/* 設定が不適切だった時の処理 */
}

は、自分の実力では活用法がまだ想像できないですね…また質問するかもしれませんので、その際はすみませんがよろしくお願いします<m(__)m>
デバックモードでも追ってみます。

投稿日時 - 2019-07-17 19:42:00

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.4

No.2です

重要なところで誤解があるようですので・・。

次郎25歳が出てきたのはフィールドが書き換えられたからではありません。
フィールドは太郎28歳のままです。
フィールドとメソッドの仮引数に同じ変数名を付けることはできますが、別物なのです。メソッド内で 「 age 」とだけ書くと仮引数の事になります。

もう一つ、この会話で「インスタンス」という語が出てこなかったので、
「クラス」と「インスタンス」の違いについては理解されていますか?「クラス」は定義「インスタンス」は実体です。
this は 同じクラスではなく、同じインスタンスの自身を指します。
Cat cat1= new Cat();
Cat cat2= new Cat();
Cat cat3= new Cat();


それぞれ別のインスタンスが生成されます、フィールドも別々なので、それぞれ別の値を保持することができます。また、this は それぞれの自身を指します。
これも実際に動かしていろいろやってみてください。

質問内容から離れすぎましたのでこれにて終了です。
失礼いたしました。

投稿日時 - 2019-07-14 11:56:20

お礼

はい、クラスとインスタンスについては、大丈夫です。
が、thisは同じクラスではなく同じインスタンス自身だったのは認識不足でした、ありがとうございます。
仮引数nameやageは、フィールドとメソッドで異なるのですね。
確かに今回はメソッドで「太郎」「28」と値を入れているので、メソッドの方は実引数ですね。
また復習してみます。

投稿日時 - 2019-07-17 19:40:18

ANo.3

>Exception in thread "main" java.lang.Error: Unresolved compilation problem:
>型 Cat のメソッド show(String, int) は引数 () に適用できません
>
>at sample.Start.main(Start.java:16)

エラーメッセージをきちんと読まれたらわかると思うのですけど。
Catのメソッドshow(String, int)は、1番目にString型の引数が、2番目にint型の引数が必要なのに、
show()と引数なしで呼んでるからエラーになってるんです。

>なぜエラーになってしまったのか、どうして2つのクラスのshowメソッドの引数が空だとうまく結果が出力されたかにつきまして、お教えいただけないでしょうか。

CatクラスのshowメソッドのString型の第1引数とint型の第2引数が必要という仕様と、使い方が異なってたからです。
それをCatクラスのshowメソッドを引数なしという仕様に変える事で使い方の方に合わせたことで解決したという事です。

投稿日時 - 2019-07-14 03:11:13

お礼

そうなんですね。
Catクラスのshowメソッドは引数ありの仕様なのに、それをStartクラス内で引数無しで利用しようとしたのが原因なんですね。
何となく頭がスッキリしました、ありがとうございます!

投稿日時 - 2019-07-14 09:50:06

ANo.2

void show(String name,int age) { ~ }
と引数が2つ定義されているのに
cat1.show();
では引数がありませんね。コンパイラはカンカンになって怒ります。
void show() { ~ }
を定義すれば許してもらえます。

void の性質については、返り値を持たない、ですが、本件のエラーには関係ありません。

回答はここまでですが、むしろ最初のプログラムで、やってみてほしいのですが、

class Cat {
String name;
int age;
void show(String name,int age) {
System.out.println("名前は" + this.name + "です");
System.out.println("年齢は" + this.age + "歳です");
System.out.println("名前は" + name + "です");
System.out.println("年齢は" + age + "歳です");
}
}

ここで、
cat1.name = "太郎";
cat1.age = 28;
cat1.show(”次郎”,25);
を実行するとどうなるでしょうか?

投稿日時 - 2019-07-14 02:06:43

お礼

ありがとうございます、ubkuさんのコード、試してみました。
thisは確か、同じクラス内に限り値を呼び出せる…的な使い方だったと思います。

だからStartクラスの「cat1.name = "太郎";」「cat1.age = 28;」で、Catクラスのフィールドを参照して値を代入し。
Catクラスの変数nameが"太郎"、変数ageが28という値になりまして。

同時に「this.」が付いていたので、たとえStartクラスのshowメソッド内で引数に「”次郎”,25」が指定され、変数nameとageの値が変わったとしても。

―――――――
名前は太郎です
年齢は28歳です
―――――――

と、Catクラスの中でのnameとageの値が、出てきました。

―――――――
名前は次郎です
年齢は25歳です
―――――――

が出てきたのは、Catクラスのshowメソッドを呼び出した後に、引数を指定してnameとageの値を変えたから、Catクラス内の値は出てこなかった…。


こういった認識で正しいでしょうか?
もし誤りがありましたら、お手数ですが再度ご指摘いただけますと幸いです<m(__)m>

投稿日時 - 2019-07-14 09:53:16

あら。
最初のケースは
cat1.name = "太郎";
cat1.age = 28;
cat1.show();
ではなく
cat1.show("太郎",28);
で、コンパイルが通ります。
理由は、これ
void show(String name,int age) {
2個のパラメーターを必要とする宣言があったためで、
cat1.show();
と、省略したことで、必要なものがない!というエラー

逆に、
void show()
の時に、エラーが出なかった理由は、
cat1.name = "太郎";
cat1.age = 28;
の代入が優先されたため。

ローカルスコープとクラス内のスコープの違いです。

void show(String name,int age) {
System.out.println("名前は" + name + "です");
この時の"name"は、cat1.nameではなく、
void show(String name,int age) {←ここの"name"を参照している。

省略した場合は、関数の外である、
class Cat {
String name; ←ここ
を見ていたので、表示がされたという具合ですね。

もし、
void show(String name,int age) {
System.out.println("名前は" + this.name + "です");
System.out.println("年齢は" + this.age + "歳です");
と書いていた場合は、パラメーターとして、name,ageに
何が与えられても、this(つまりCATそのもの)の変数を見ます。
なので、これを省略したため、コンパイラが自動判断した結果による
違いですね。
void show(String name,int age) {
System.out.println("変数の名前は" + this.name + "です");
System.out.println("変数の年齢は" + this.age + "歳です");
System.out.println("パラメタの名前は" + name + "です");
System.out.println("パラメタの年齢は" + age + "歳です");
}
と書いて、呼び出し元を
Cat cat1 = new Cat();
cat1.name = "太郎";
cat1.age = 28;
cat1.show("花子",14);
とでもすれば、理解できるかと思います。

投稿日時 - 2019-07-14 01:41:13

お礼

ありがとうございます、変数nameがどのように処理されているか、よくわかりました!
this.を使えば引数に何の値が入ろうとも、フィールドで定義したnameやageを参照してくれるんですね。

「(一方のクラスで)2個のパラーメーターが必要な宣言をしていたのに、(別のクラスで)省略してしまって『必要なものがない!』というエラー」も、覚えておきます。

投稿日時 - 2019-07-14 09:57:14

あなたにオススメの質問