初心者のJavaプログラミング

プログラミングガチ初心者がIT業界を目指して頑張ります。

【Android】スピナー(Spinner)クラスのメモ

こんばんは。
スピナークラスの使い方ではまっていたというよりは、
Stringクラスに対して誤解が!w

null と 空文字って違うんですねw

String str1 = null;
String str2 = "";

この二つは違います。
Stringは参照型の変数なので、変数には実体ではなくてオブジェクトのある実体の番地が入っています。
str1は実体がないということなのでどこも参照していません。
それに対してstr2は空文字が入っています。一応実体があるのでnullじゃないってことです。

いい例えが浮かばないけど、
鉛筆がない = 鉛筆が0本ある
みたいな感じなのかなと。

昔々、どっかの数学者が何もないという状態を、0という数字があると表現したっていう話をふと思い出しました。
そんな感じなのかなーw


そんで、
変数に文字が入っているかどうかの判定とかすると思うんですが、

if(str2 == "ハローワールド")

ではなくて

if(str2.equals("ハローワールド"))

というようにequalsメソッドを使って判定しなくてはなりません。


これではまってましたw
スピナーで表示されている文字列の状態に応じて、処理を変えていこうと思っていて、
ずっとequalsメソッド使わないで == で判定してました。
Logだしても最後のelseにしか入ってこないなーと思って、
ぐぬぬー状態でした。

とりあえず解決したので、がんがん先に進もうと思います!

ではでは!

【第25回】初心者のJavaプログラミング【例外処理(try, catch)】

こんにちは。
最近鼻の調子が悪いです。
風邪か花粉か。イネ科のかもがや?っていう河原に生えているやつの花粉症なんですよね。だから、春と秋だと秋のほうがひどい傾向がるんですよねー。
あと、ほこりアレルギーっぽいので掃除すると具合悪くなりますw

ってことで今回は例外処理です。

例外とは

良く分からないので、とりあえず例外を出してみます。
0除算が手っ取り早いです。
整数を0で割ってしまってはだめなのです!

class ExceptionZeroJosan {
	public static void main(String[] args) {
		int a = 5;
		int b = 0;
		int c = a / b;
		System.out.println(c);
	}
}

文法的に正しいのでコンパイルは通りますが、
int c = a / b;
の行で実行時にエラーが出ます。

Exception in thread "main" java.lang.ArithmeticException: / by zero
といったエラーが表示されます。
ArithmeticExceptionクラスの例外オブジェクトが生成されていることを意味しています。

このように例外とは、プログラムの実行中に発生した問題を通知するために、実行時に生成されるオブジェクトのことです。

Javaではこの例外を、前もって準備しておいた処理ルーチンで処理することが出来ます。

例外処理の書き方

class ExceptionZeroJosan {
	public static void main(String[] args) {
		int a = 5;
		int b = 0;
		try { //< 例外が発生する恐れのある処理を書く
			int c = a / b;
			System.out.println(c);
		}
		catch(ArithmeticException ex) { //< 例外発生した時の処理
			System.out.println("0で割っちゃだめだよー");
		}
		finally { //< 必ず実行される
			System.out.println("終わり");
		}
	}
}

コンパイルして実行してみると、
"0で割っちゃだめだよー"
"終わり"
が表示されたと思います。

tryの中に例外が発生する恐れのあるコードを書いていきます。
0除算は例外が発生しそうというかします。
予定通り例外が発生して、ArithmeticExceptionクラスのオブジェクトが生成されました。
その例外がcatch(ArithmeticException ex)のexに引数として受け取っています。
その例外に対しての処理をcatchブロックの中に書いていきます。
catchは例外をキャッチ!って感じです。
そんで、finallyブロックですが、これは必ず実行されます。
tryで例外が発生しなかった場合でも、例外が発生した場合でも実行されるということです。
try文にretrunステートメントがあったとしても、すぐに関数を抜けずfinallyブロックの処理をします。ここがちょっと紛らわしいです。

例外オブジェクトに対応するcatchブロックがなかった場合

例外にも色々種類があって、

  • 0で除算した時等に発生する例外
  • 配列の範囲外を参照してしまった場合の例外

等です。
もし上の例で、配列の範囲外を参照してしまった場合の例外のオブジェクトをキャッチするようなコードを書いていた場合、せっかく例外をキャッチしようとしてもできません。

catch(ArithmeticException ex)となっている部分を
catch(ArrayIndexOutOfBoundsException ex) に変更してみて下さい。
例外はキャッチされずに、finallyブロックだけが実行されて終わります。

まあ、気をつけましょうってことです!w

(キャッチできなかった場合、呼び出し元のメソッド内のtryブロックのcatchブロックに検索しにいきます。見つかった段階で検索を終了して処理をします。)
ちょっとややこしいですが例文を一つ。

class ExceptionZeroJosan {
	public static void testA() {
		try {
			testB(); //< 2
		}
		catch(ArithmeticException ex) { //< 7 呼び出し元まで探しにくる。
			System.out.println("testAメソッド内でキャッチしたよ!"); //< 8 例外キャッチ
		}
		finally { //< 9 必ず実行されます。呼び出し元に戻る。
			System.out.println("ふはは!");
		}
	}

	public static void testB() { //< 3
		int x = 5;
		int y = 0;
		try {
			int z = x / y; //< 4 (例外発生!)
			System.out.println("あああ");
		}
		catch(ArrayIndexOutOfBoundsException ex) { //< 5 (クラスが違うのでキャッチできず)
			System.out.println("testBメソッド内でキャッチしたよ");
		}
		finally { //< 6 必ず実行されます。呼び出し元に戻ります。	
			System.out.println("ぐぬぬ...");
		}
	}

	public static void main(String[] args) {
		try {
			testA(); //< 1
		}
		catch(NumberFormatException ex) {
			System.out.println("0で割っちゃだめだよー");
		}
		finally { //< 10 必ず実行されます
			System.out.println("終わり");
		}
	}
}

処理される順番を書いておいたので追ってみて下さい。


ちなみにですが、全ての例外のスーパークラスであるExceptionクラスとして例外オブジェクトを引数で受け取れば例外のキャッチが出来ます。
catch(Exception ex)としてみて下さい。
catch(ArithmeticException ex)としたときと同じ実行結果になるはずです。




次はthrowステートメントについて書こうとおもったのですが、
あまり良く分かっていないことにたった今気付き、絶望していますw
もうちょっと勉強して出直してからきますw

それでは今日はコレくらいで。
皆さん、暑くなったり涼しくなったりしているので体調崩さないように。
ではでは。

【第24回】初心者のJavaプログラミング【パッケージ】

2連続投稿です。
今回はパッケージについてです。
package
import
等のキーワードが出てきます。
ターミナルやコマンドプロンプト上でのコンパイルと実行の仕方が通常と違うので、そこのあたりも説明していきます。
そんなに難しくないはずです。

パッケージとは

パッケージとは、辞書的な説明をすると、クラスやインターフェイスの集まりのこと、となっています。
意味を持たせた集まりというイメージでしょうか。
Javaのパッケージ = ディレクトリ(フォルダ)
だとイメージすれば良いのではないかと思います。

パッケージの割り当て方

1つのソースファイルに含まれるクラスとインターフェイスを特定のパッケージに割り当てる方法があります。
めちゃくちゃ簡単で、

package パッケージ名;

を、一番最初の行に書きます。

また、複数のパッケージを階層的にすることも出来ます。
この場合はピリオドで区切ります。


余談ですが、会社で使うときにはパッケージ名としてドメイン名を使用するのが一般的とのことです。
ドメインが、
matoowo.co.jp
の場合、パッケージ名は、
jp.co.matoowo.~
みたいに逆から書いていくそうです。
その後ろにアプリ名、機能名を書いていくみたいです。
jp.co.matoowo.aprication1.dao
って言う感じです。
働いたことがないので詳しいことは良く分かりませんw

機能名ですが、

  • dao(データベースアクセス用)
  • dto(画面表示用)
  • entity(データ)
  • logic(処理)
  • controller(仲介)
  • property(設定)

らへんが使われることが多いみたいです。

また、今まで上げたソースではパッケージの指定なんて1回もしたことはなかったと思います。
パッケージの指定をしなかった場合は、デフォルトパッケージ(名前無し、無名)のパッケージに割り当てられることになります。

やや脱線しましたが、パッケージの割り当て方としてはこんな感じですね。

具体的なやり方

例を見てもらった方が分かりやすいと思うので、まず例を。

package p;

class PackageSample {
	public static void main(String[] args) {
		A a = new A();
		B b = new B();
		C c = new C();

		a.a1();
		b.b1();
		c.c1();
	}
}
package p;

class A {
	void a1() {
		System.out.println("A");
	}
}
package p;

class B {
	void b1() {
		System.out.println("B");
	}
}
package p;

class C {
	void c1() {
		System.out.println("C");
	}
}

こんな感じで、4つのソースファイルを用意します。
こいつらを全部1つのパッケージに指定するので、pというパッケージに割り当てます。
それぞれのソースファイルの最初の行ですね。

ここまではいいと思うんですが、コレをコンパイルする方法が今までと違います。
私の場合は、
Documents/Java/p
の中にこれらのソースファイルを置きました。
そうしたらまずパッケージの親ディレクトリをカレントディレクトリにします。
私の場合だと、
Documents/Java
です。
移動したらコンパイルするために、ここで次のようなコマンドを打ちます。
javac p/*.java
windowsでは
/ ではなくて¥を打ちます。
このp/*.javaの意味ですが、
/はディレクトリを指定する意味ですよね。*は全部って言う意味があるらしいです。
なので「pのディレクトリの中にある、拡張子が.javaのファイル全部に対してコンパイルします」という命令です。

このコマンドを実行するといつも通り、.classファイルがpディレクトリの中に出来上がると思います。

次に実行の方法ですが、
java p.PackageSample
という風に打ちます。
JVMの引数として、クラス名を完全修飾クラス名で指定しなければなりません。
完全修飾クラス名とはパッケージ名とクラス名を合わせたものです。
ですので、
java PackageSample
ではなく、完全修飾クラス名で
java p.PackageSample
とうようにしてやる必要があります。

無事実行されるはずです。

import

別のパッケージ内のクラスやインターフェイスを使いたい場合に使用する方法です。
例えば、java.utilパッケージのクラスやインターフェイスを使いたい場合等に利用します。

import java.util.*;

というように書きます。
*なので、java.utilパッケージの中の全てのクラスやインターフェイスを指定していることになります。

Javaのリファレンスを見るとこのようなパッケージがうるとらたくさんあります。
車輪の再発明とならないように、調べていいのがあったら積極的に使っていくのがいいぜ!


パッケージはコレで終了です。
次回は例外処理です。

【第23回】初心者のJavaプログラミング【インターフェイスの継承•instanceof演算子】

こんばんは。
最近は基本情報の勉強に重きを置いているので、なかなか更新する機会が少なくなっています。
申し訳ないです。
試験日が10月19日なので、そろそろ過去問をがっつりやらなきゃだめだと思うので、日々過去問を解いています。

今日はインターフェイスの継承についてです。

インターフェイスの継承(書き方)

方法は通常のクラスの継承(拡張)と同じで、extendsキーワードを使用します。
前回も説明しましたが、Javaでは多重継承を許していません。ですがインターフェイスの場合は多重継承が出来ます。
その方法も前回書いたので省略します。

じゃあそもそも、なんでJavaでは多重継承を許してないのでしょうか。

Javaが多重継承を許していない訳

複数のスーパーインターフェイス内で同じ名前の変数やメソッドが宣言されていると、サブクラスからするとどっちを参照すればいいのか分からないですよね。
結果コンパイルエラーが発生します。
ここら辺がちょっとややこしいので多重継承は許していないみたいです。

instanceof演算子

オブジェクトのクラスやオブジェクトに実装されているインターフェイスを確認するための演算子です。

変数名 instanceof クラス名(またはインターフェイス名)

このように書きます。
そして変数がinstanceofの後に書いてあるクラス名であれば"true"が返されます。違っている場合は"false"が返されます。

インターフェイスはこのくらいです。
あまり真新しいことはないです。

次回はパッケージについてです。

【第22回】初心者のJavaプログラミング【インターフェイス】

こんばんは。
ここ2、3日寒いですね。朝方とか羽毛布団にくるまっていましたw

今日はインターフェイスです。

インターフェイスとは

インターフェイスとは、定数とメソッド宣言を1つにまとめたものです。
というように教科書に記載してありますが、よくわかりません。
クラスと何が違うのというところですが、まだ私自身違いが良く分かっていません。
抽象クラスをさらに押し進めたもの、っていうように考えてもらってかまわない、と先生はおっしゃっていたのできっとそうなんでしょうw そういうことにしましょう。

じゃあ抽象クラスと何が違うの?となる訳ですが、
大きな違いは、多重継承ができることだと思います。
どこかで書いたと思いますが、Javaは多重継承を許していません(C++は許しているみたいです)
ですが、インターフェイスの場合は、複数インターフェイスを1つのクラスに実装することが出来ます。

ここで注意点なのですが、宣言と実装は別ということです。
はじめに定数とメソッドの宣言をひとつにまとめたものと書きました。メソッドをまとめたものではないです。メソッドの宣言をまとめたものになります。

メソッドの宣言でメソッドの機能を書きます。メソッドの中身がない状態です。
メソッドの実装でメソッドの中身を書きます。どのような動作をするかということです。
例えばリモコンで言うと、
メソッドの宣言は、
「音量上げるボタンを押す」
「音量下げるボタンを押す」
といったものです。
それに対して、メソッドの実装は、宣言された「音量を上げるボタンを押す」「音量を下げるボタンを押す」メソッドの中身のことです。
音量を上げるボタンを1回押したら音量を1上げる。2回押したら2上げる。音量がMAXまでいったらそれ以上上がらないようにする。ある一定の音量まで上げると、聴力を失う危険性があります、等といった警告を出す。
というような実際の動きの部分を実装と言います。

Javaでのインターフェイス宣言の仕方

一般的には次のように書きます。

interface インターフェイス名 {
  // 定数
  定数1;
  定数2 = 2;
  
  // メソッドの宣言
  void upSounds(); //< 宣言だけ。実装しちゃだめ。
  void downSounds() {
    // こんな風に実装はしちゃだめ。できない。
  }
}

普通のクラスの宣言の仕方と同じ要領です。
ただ、メソッドの中身を書いちゃだめってとこだけが重要です。
インターフェイスは動作の中身ではなく、どんな機能を持っているかがユーザーや他のクラスが分かればいいのです。メソッドの中身をわざわざ他クラスに見せる必要はないということです。カプセル化の話にもつながってきますね(たぶん...)

宣言したので、実装もしなきゃですよね。そうでなければ意味がありません。
メソッドを宣言しときながら実装を書かないと、なんじゃこりゃーってことになるので(音量上げるボタン押しても何も起こらないze!)、宣言したメソッドの中身は必ず実装します。
次は実装の仕方です。

Javaでのインターフェイス実装の仕方

class クラス名 implements 実装するインターフェイス名 {
  public void upSounds() {
    // 中身を書いていく
  }
  public void downSounds() {
    // 中身を書いていく
  }
}

上記のようになります。
継承のextendsみたいな要領で書いていきます。

また、1つのクラスに複数インターフェイスを実装できるので、

class クラス名 implements インターフェイス1, インターフェイス2 {}

というようなことも出来ます。
この時ももちろん全てのメソッドの中身を書かなければなりません。

継承ではこんな風にはかけませんでしたよね。


インターフェイス自体も継承が出来ます。
そこらへんと、それ周りの説明は次回にします。

よだーん
インターフェイス = 取り扱い説明書みたいなイメージなのですが、合っているのでしょうかw
リモコンそのものがインターフェイスみたいなイメージです。
少し不安です。

【第21回】初心者のJavaプログラミング【継承と変数•オーバーライド•コンストラクタ】

継承において、スーパークラスの属性やメソッドはサブクラスが相続します。
つまり、サブクラスではスーパークラスの属性やメソッドが使えます。
前々回あたりにやりました。

継承と変数

スーパークラスと同じ名前の変数をサブクラスで作った場合はどうなるでしょうか。
この場合は、サブクラスで作った変数がスーパークラスの変数を隠してしまいます。
となると、スーパークラスの変数はサブクラスから参照することができない!
と思いきや、やっぱりちゃんとサブクラスから参照できる機能がJavaにはあるんですね。
superというキーワードを使うと出来ます。
super.変数名
というようにサブクラス内で使用すれば、スーパークラスの同じ名前の変数を参照することが出来ます。
注意点ですが、2つ上のスーパークラスの変数にはアクセスできません。
super.super.変数名
といった使い方は出来ないということです。

そんじゃいつもの通り例を。

class Goku {
	// 悟空の身長と体重
	double height = 180.;
	double weight = 70.;
}

class Gohan extends Goku{
	// ご飯の身長と体重
	double height = 170.;
	double weight = 60.;
	// 悟空の身長を参照
	double getGokuHeight() {
		return super.height;
	}
}

class GokuGohan {
	public static void main(String[] args) {
		Gohan gohan = new Gohan();
		
		System.out.println(gohan.height);
		// サブクラスの悟飯から悟空の身長を呼び出す。
		System.out.println(gohan.getGokuHeight());
	}
}

メソッドのオーバーライド

同じシグネチャを持つメソッドスーパークラスにもある場合、スーパークラスメソッドが実行されずに、サブクラスのメソッドが実行されます。
シグネチャとは前もやりましたが、
メソッド名、引数の数、引数の型の組み合わせのことです。注意点ですが、戻り値の型はシグネチャに含まれません!
このことを知らなくて、なんかの問題ができませんでしたw

これは具体的な例を見た方が分かりやすいので、例を出します。

class Goku {
	void kamehameha() {
		System.out.println("おら悟空。カメハメ波!!");
	}
}

class Gohan extends Goku{
	void kamehameha() {
		System.out.println("ひゃっほーおら悟飯。カメハメ波!!");
	}
}

class GokuGohan {
	public static void main(String[] args) {
		Goku goku = new Goku();
		goku.kamehameha();

		Gohan gohan = new Gohan();
		gohan.kamehameha(); //< オーバーライド

		// 要注意!!
		Goku test = new Gohan();
		test.kamehameha(); //< オーバーライド
	}
}

mainメソッド内の、
Gohan gohan = new Gohan();
というところがオーバーライドです。
スーパークラスのkamehameha()メソッド
サブクラスのkamehameha()メソッド
シグネチャが同じですよね。
なので、スーパークラスのkamehameha()ではなく、
サブクラスのkamehameha()が呼ばれます。

問題は一番したのやつです。
Goku test = new Gohan();
です。
変数の型はスーパークラスであるGokuですね。
ですがオブジェクトそのものの型はGohanですよね。
どのkamehameha()メソッドを実行するのかを決定するのは、
変数の型ではなく、オブジェクトそのものの型です。
なのでこの場合はGokuではなく、Gohanのkamehameha()が呼ばれることになります。

new コンストラクタ()でオブジェクトの参照が渡されることを思い出せば普通に理解できますが、
勘違いしやすいところです。
気をつけましょう!!

ちなみに、メソッドも変数と同じく、
super.メソッド名();
というかたちで、スーパークラスメソッドを使用できます。

継承とコンストラクタ

クラスの属性とメソッドはそのクラスだけではなく、スーパークラスにも定義されています。
なので、そのクラスだけコンストラクタを実行して初期化するだけだと、適切な初期化が出来ません。
また、スーパークラスで定義された属性とメソッドはサブクラスのコンストラクタを実行する前に、適切に初期化されてなければなりません。
つまり、スーパークラスコンストラクタがサブクラスのコンストラクタより先に実行されることになります。

ここは、そうなんだーと思って検証してみるくらいでいいのかなって思います。


以上でクラス関係の所は終了です。
あとは、クラスの修飾子(publicとかprivateとか)は時間があるときに確認する感じでいいと思います。
余裕があれば書いていきますが、最近余裕がなくなってきたので厳しいかもですw


次からはインターフェイスに入ります。

【第20回】初心者のJavaプログラミング【特化としての継承】

こんばんは。今回は前回の続きです。
前回は汎化の継承というものをやりました。
物事の抽象的な部分に注目し、概念の階層を構築していくのが汎化という作業です。
例えばですと、消しゴム、ボールペン、鉛筆に共通の文房具という抽象的な概念を切り出して、それを基底クラスにします。

今回は特化の継承というものをやります。
考え方は同じです。

「汎化としての継承」と「特化としての継承」

汎化としての継承は、前回説明したとおりで、基底クラスを探し出して作ることです。
それに対して、特化としての継承はその名の通りですが、派生クラスを作りだすことです。
文房具クラスから鉛筆クラス、消しゴムクラス、ボールペンクラスを作りだすのが特化です。
元のクラスがどちらかということが違うだけです。やっていることは2つとも変わりません。
ですが、どっちかというと汎化のほうが難しいなと感じます。
やっぱり文房具と鉛筆を比べると、どっちが具体的かというと、鉛筆のほうが遥かに具体的だと思います。なので、文房具クラスを基底クラスにするという風に考えることの方が難しい気がします。

Javaにおける継承

ここからは書き方の説明です。
スーパークラスとサブクラスの関係について書きます。

スーパークラスはそのクラスのオブジェクト、またはサブクラスのオブジェクトを参照できます。
よーするに、intとdoubleみたいな関係じゃないすかね?(多分違うかもw)
スーパークラスの方が大きいのでサブクラスの参照を代入してもおっけーみたいな。
これ結構重要な機能らしいです。

以下例です。

// 文房具クラス(スーパークラス)
class Bunbobu {}
// 文房具のサブクラス
class Pencil extends Bunbobu{}
class Eraser extends Bunbobu{}
class BallPointPen extends Bunbobu{}

class InheritanceSample {
	public static void main(String[] args) {
		// 文房具クラスの変数を準備する。
		Bunbobu item;

		// サブクラスのオブジェクトの参照を入れる
		item = new Pencil();
		System.out.println("Pencilオブジェクトの参照");

		item = new Eraser();
		System.out.println("Eraserオブジェクトの参照");

		item = new BallPointPen();
		System.out.println("BallPointPenオブジェクトの参照");

		// 試しにサブクラスの変数にスーパークラスの参照を入れてみるが、
		// コンパイルエラーが出ます
		// サブクラスからは親のオブジェクトを参照できないということになります。
		Eraser items = new Bunbobu();
	}
}

親は子のアドレスを持つことができるということですね。


今日はこのくらいで。
次回は継承と変数の関係、メソッドのオーバーライド、継承におけるコンストラクタあたりを書いていこうと思います。

ではでは。