プロフィール

けい

Author:けい
公開したWebサービス・アプリ一覧はこちら

※2014年12月、私が個人で開発したWebサービス・アプリへの
累計アクセス数は8億を超えました。
負荷対策頑張ります。日々精進していきます!!


■■■ 業務経歴 ■■■
社会人1年目:携帯電話開発。画面周りを1年間
2年目 :海外向け携帯電話ミドルウェア開発
     ブラウザとプロトコルスタック周り
2年目後半~:携帯電話の通信専用チップ開発
3年目:カーナビ。画面周りの開発
3年目後半~:BDビデオカメラ
     組み込みLinux カーネルと
     ドライバの開発。
4年目12月:プロジェクト途中で退社
~ここまではC、またはC++で開発~

~ここからJavaがメインの開発~
4年目1月:Web系の会社に転職
       ~4ヶ月間の研修
5年目5月:製造業向け生産管理システム開発
6年目9月:証券会社向けシステム開発
7年目10月~携帯電話向けコミックサイトの運用・開発
8年目12月:プロジェクト途中で退社

~ここからPHPがメインの開発~
8年目1月~仲介手数料が無料の不動産屋の社内SEに転職
交渉しほぼ完全に裁量労働が可能な立場になる。
業務内容はシステム全般ですが、
最近はSEO対策の作業が多いです。
現在14年目 まだ、しばらくはこの会社に居るつもりです。

あと、全ての記事がリンクフリーです。

最近の記事

過去ログ

全ての記事を表示する

全ての記事を表示する

カテゴリー

FC2カウンター

RSSフィード

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
--.--.--    [ Myカテゴリ:スポンサー広告 ]

Javaのお勉強

以下はC,C++プログラマーが「独習Java」を読んで新しく学習したことのメモである。自分用のメモなので、多分読んでも面白くない。飛ばすべし。
また、fc2では行頭のインデントが無効になっているため、ソースも見にくい。

★キーワード
バイトコード VMで動かせるようにコンパイルされたオブジェクトファイル
メソッド   Cでいう関数のこと
シグネチャ  メソッド名とパラメーターの型を合わせたもの。

Javaの型変換
Javaの型変換のため、以下のような処理が問題となってしまう。

public class testClass {
public static void main(String args[]) {
short s1 = 1;
short s2 = s1 + 1;
System.out.println(s2);
}
}

一見、C、C++プログラマには問題に見えないこのソースをコンパイルすると、
「型の不一致: int から short には変換できません。」
というエラーが表示される。
このエラーが表示される理由はJavaの型変換という機能である。
C,C++では違う型同士の演算が可能である。
ところがJavaではint 以下のビット数の変数を演算すると、結果は全てintになるという特性がある。
よって以下のような処理もやはりエラーとなる。(short と shortでintに変わってしまうため)

public class testClass {
public static void main(String args[]) {
short s1 = 1;
short s2 = 1;
short s3 = s1+s2;

System.out.println(s3);
}
}

型変換の優先順位でいうと double > float > long > int > それ以外となる。そのため
double と何かを演算すると 必ず結果はdoubleとなる。
変数同士のビット演算などがやりたい場合はどうなるのだろうか・・・ @ 疑問点1 誰か教えて。@


Javaの配列
配列はC,C++とJavaでは作り方が違っていて、以下のような配列の取り方はNG.

public class testClass {
public static void main(String args[]) {
int array[10];
System.out.println("");
}
}

エラーメッセージ
「トークン "10" に構文エラーがあります。このトークンを削除してください。」
なんで上記のやり方ではいけないのかが、理解に苦しむ。

正解は以下
public class testClass {
public static void main(String args[]) {
int array[];
array = new int[10];
int array2[] = {1,2,3};
int array3[] = new int[10];
int array4[] = array;


System.out.println("array = " + array.length);
System.out.println("array2 = " + array2.length);
System.out.println("array3 = " + array3.length);
System.out.println("array4 = " + array4.length);
}
}

array.length で配列の個数が取得できるので便利ではあるが、配列がクラスっぽい動作をしているのは不思議。

/* 多次元配列の作り方 */
public class testClass {
public static void main(String args[]) {
int varName[][] = new int[5][10];

System.out.println("varName = " + varName.length);
System.out.println("varName = " + varName[0].length);
System.out.println("varName = " + varName.length * varName[0].length);
}
}

出力結果
varName = 5
varName = 10
varName = 50


また、Javaでは配列の要素が四角形の行列である必要がない。
よって、以下のような配列が作成可能
/* 多次元配列の作り方 */
public class testClass {
public static void main(String args[]) {
int myarray[][] = {
{22,31},
{33,44,55,4444},
{32,33,4444,5555}
};

System.out.println("myarray = " + myarray.length);
System.out.println("myarray = " + myarray[0].length);
System.out.println("myarray = " + myarray[1].length);
System.out.println("myarray = " + myarray[2].length);
}
}
出力結果
myarray = 3
myarray = 2
myarray = 4
myarray = 4


P48
★メソッドの例外指定
int func(int prm) throws exceptionList {
}

exceptionListは例外リストといえます。
この関数をコールしたときに起こりうるエラーをthrowsの後に書きます。

★静的メンバ、インスタンスメンバ、ローカルメンバ
静的メンバはわかりやすくいうと staticのメンバが静的メンバ。
ひとつのクラスで実体はひとつ

インスタンスメンバはクラスから生成されたオブジェクトの一つ一つに対して作成される、
クラス内でのグローバル変数みたいなもの。
ローカル変数はメソッド内部で宣言される、関数内変数のこと。
静的変数も静的メンバと同じ。クラスに結び付けられているので実体は一つしか存在しない。
インスタンスメンバとしてはインスタンス変数と、インスタンスメソッド
静的メンバは静的変数、静的メソッドという


★Javaプログラムにはmain() という静的メソッドが必ず存在する。
main()は一つのアプリで一つである。
このmain() にはCのように int main(int argc, char *argv[]) とはならず、
main(String args[]) となる。
この理由はJavaでは配列はメソッドを持つので、args.length とすれば引数の個数が取得できるからである。

引数の個数と、引数で受け取った文字列の出力
public class testClass {
public static void main(String args[]) {

System.out.println("args[0] = " + args[0] + " args[1] = " + args[1] + " args.length = " + args.length);
}
}

★オブジェクト指向においてクラス変数とは状態を表すらしい。
この考え方は面白い。
メソッドの動作は固定なので、変数が取りうるパターンだけ状態があると考えることができる。

★コンストラクタのオーバーロードとは複数のコンストラクタを使用可能なこと。
もっと正確な用語を使うとコンストラクタのシグネチャが異なる。
シグネチャとはコンストラクタ名とパラメーターの型を合わせたもの。

public class testClass {
public testClass(int i) {
}
public testClass(char b) {
}
public testClass(short c) {
}

public static void main(String args[]) {

System.out.println("args[0] = " + args[0] + " args[1] = " + args[1] + " args.length = " + args.length);
}
}

★コンストラクタは戻り値を返すことができない
ちなみにクラス内から、同じクラスのコンストラクタを呼ぶためにはthis を用いる。
呼び方としては
this(i);
this(b);
this(c);
これだけでよい。

★静的変数について P152
静的変数、インスタンス変数は初期化しなくても初期値が決まっている。
boolean の場合には偽、数値の場合には0が代入される。
変数の宣言時に値を代入することもできる。
C++と同様、静的処理と、非static処理は混ぜるな危険。
Javaでは自動的に初期化されないのはローカル変数のみである。

★ファイルスコープ
Cだと異なったファイルの関数、変数を参照するためにはincludeもしくはexternが必要になるが、
Javaの場合には同一ディレクトリのクラスを使用するために特別な処理を行う必要がない。
便利だが、ビルドに時間がかかったりはしないのだろうかと、不思議に思う。


★ローカル変数と静的変数、インスタンス変数を同名にすると
ローカル変数が優先される。普通こんなことやらないと思うが、一応。

★Javaでのポインタ渡し
Javaにはポインタが無いので、アドレス渡しができないものかと思っていたのだが、
参照渡しというテクニックがアドレス渡しと同様のようである。
ただし、参照渡しというのを明示的に行うわけではなくて、
配列やオブジェクトを引数として引き渡す場合に自動的に参照だけが渡される。


★継承
継承するためにはextends を用いる必要がある。
メソッドのオーバーライドによって実行時のポリモーフィズムが実現される。
スーパークラスのメソッドを呼び出すためにはsuperを用いる。

clsName2はclsName1から継承している。
clsName1はclsName2のスーパークラスである。↓

class clsName2 extends clsName1 {
}

clsName2 varName;

↑ これはオブジェクトを参照する変数を作成している。

★動的メソッドディスパッチ
適切なオーバーライドメソッドを動的に選択する機能。
ソースを見ると違和感を覚えるが、ポリモーフィズムには必要らしい。

class Thing {

Thing() {
}

void hello(){
System.out.println("Thing");
}
}

class X extends Thing{
public X() {
}

void hello(){
System.out.println("X");
}
}

public class testClass{
public static void main(String args[]) {
Thing var = new X(); //★ ここがキモ
var.hello();
}
}

出力結果
X

なんと親クラスが子クラスからnewされている。
ここで Thing var って何でもいいのではないかと思ってしまうので
何でもいいのかなーと思って試してみると
X var = new Y();
このXとYの部分は
X var = new Thing(); NG
Thing var = new X();  OK
Thing var = new Thing(); OK
Thing var = new Y();  NG(Yはhello()というメソッドを持つ、varとの継承関係に無いオブジェクト)

よって子クラスが親クラスのオブジェクトをnewすることは不可能だが
親クラスのオブジェクトが子クラスのオブジェクトをnewすることは可能である。
子は親のメソッドを呼べる。
親は全ての子を参照できる。
なんか面白い。

★継承したクラスのコンストラクタはどのように呼び出されるか
親クラス、子クラス、孫クラスがあって孫クラスのオブジェクトを作成すると、
コンストラクタは親クラス、子クラス、孫クラスの順番で呼ばれる。

★クラス修飾子(abstract, final, public)
final オーバーライドできないクラス
abstract 抽象クラス。インスタンス化できないクラス。オブジェクト指向プログラミングで重要。
public 他の全てのクラスから参照できるクラス。
無し    同じパッケージ内(ディレクトリ)からしかアクセスできない

P190 抽象クラスとはクラスの機能さえ定義すれば、
その機能をどのように実現するまで定義しなくていいという利点がある。
サブクラスでは同じ目的を達成するために複数の実装を使うことができる。
ようはIFのみが定義されているファイル。

finalは拡張できないクラス。クラスで実装したメソッドをオーバーライドできないようにする。
abstract とfinal を同時に指定することはできない。

有形クラス(concreteクラス)
abstractの反対でインスタンス化できるクラスのことを有形クラスという

★変数の修飾子
final 定数として使える変数。Cのconst と同じと考えていい
private 同じクラスのコードからしかアクセスできない変数
protected サブクラス、または同じパッケージ内のコードからしかアクセスできない変数
public 他のクラスからもアクセスできる変数
static インスタンス変数ではない変数(危険)
■transient クラスの永続的な状態の一部ではない変数??
■volatile 不意に値が変更されることがある変数。

下二つについては実プロジェクトではほとんど使わないらしい。
ちなみにvolatile は組み込みとはぜんぜん意味合いが違っている。
組み込みの場合にはvolatileは最適化しないという意味合いで使う。


void main() {
int i = 1;

while(i) {
xxx();
}
}

コンパイラが上記処理を最適化すると
void main() {
while(1) {
xxx();
}
}

となる。ところが組み込みの場合はiの取りうる領域をハードウェア的に直接書き換えることが可能なので
iという領域自体が無くなってしまうのは問題となる。
そういう場合にvolatileを使用する。volatileを使用するとコンパイラが最適化しない。


★コンストラクタの修飾子
private 同じクラスのコードからしかアクセスできないコンストラクタ
protected サブクラスまたは同じパッケージ内のコードからしかアクセスできないコンストラクタ
public 他のクラスからアクセスできるコンストラクタ

★メソッドの修飾子
■abstract このクラスでは実装しないメソッド (virtualのことみたい)
final オーバーライドできないメソッド
■native Javaのバイトコードではなく、ホストCPUで使われるマシン語で実装されるメソッド
private 省略
protected 省略
public 省略
static インスタンスメソッドではないメソッド
■synchronized 実行を開始するときにロックを取得するメソッド

abstractが宣言されているメソッドを含むクラスは、クラス自体もabstractにする必要がある。
synchronizedはマルチスレッドで用いる。
nativeってどうやってコンパイルするんだろ。コンパイラはなんだろ。

★singleton を用いると、オブジェクトの生成されているかとか
起動順序などを考慮しなくてよくなる。
例えば、通常ならばinitプロセスが起動するなどのルールがあるが、
この辺を考える必要が無くなる。

★ObjectクラスはJavaクラス階層の頂点に位置するオブジェクトである。
全てのオブジェクトはユーザーが作成したオブジェクトも含めて例外なく、Objectクラスの系列下にある。
Objectクラスが持つメソッドとしては以下がある。

clone() このオブジェクトのコピーを作成して返します。
equals(Object obj) このオブジェクトとほかのオブジェクトが等しいかどうかを示します。
finalize() このオブジェクトへの参照はもうないとガベージコレクションによって判断されたときに、ガベージコレクタによって呼び出されます。
getClass() オブジェクトの実行時クラスを返します。
hashCode() オブジェクトのハッシュコード値を返します。
notify() このオブジェクトのモニターで待機中のスレッドを1つ再開します。
notifyAll() このオブジェクトのモニターで待機中のすべてのスレッドを再開します。
toString() オブジェクトの文字列表現を返します。
wait() ほかのスレッドがこのオブジェクトの notify() メソッドまたは notifyAll() メソッドを呼び出すまで、現在のスレッドを待機させます。
wait(long timeout) 別のスレッドがこのオブジェクトの notify() メソッドまたは notifyAll() メソッドを呼び出すか、指定された時間が経過するまで、現在のスレッドを待機させます。
wait(long timeout, int nanos) ほかのスレッドがこのオブジェクトの notify() メソッドまたは notifyAll() メソッドを呼び出すか、ほかのスレッドが現在のスレッドに割り込みをかけたり、指定された量の実時間が経過するまで、現在のスレッドを待機させます。

パターン的にはObjectクラスはオブジェクト操作とスレッド関連のメソッドを持っているようだ。

★Classクラス とは実行中のプログラム内のクラスやインターフェイスに関する情報がカプセル化されます。
配列や、特定のデータ型、基本データ型と、voidのそれぞれにClassオブジェクトが存在するため、
配列でlengthとかが使えるようになる。


★インターフェイス
インタフェースとは定数とメソッド宣言をひとつにまとめたもの。
インターフェイスを変数の型に使用することもできる。
インターフェイスに別のインターフェイスを拡張することも可能。
instanceof を使用するとオブジェクトが特定のクラスであるか、
または特定のインターフェイスを実装しているかを調べることができる。
パッケージとはクラスとインターフェイスをひとまとめにしたものです。
パッケージを使って名前空間を体系化することが可能です。
CLASSPATH環境変数はJava2 SDKツールがパッケージを検索する場所を示します。
■クラスにインターフェースを実装する場合、そのインターフェイスで宣言されているメソッドを全て実装しなければならない。
インターフェイスは同名の変数、メソッドをもつとコンパイルエラーが発生する。

★クラスからインターフェイスを使用するにはimplements キーワードを用いる
public class clsName extends superName implements intfList {
}

★インターフェイスをimplementsでいっぱい書くのは手間がかかるので以下のように記載できる。
public interface interface0 extends interface1, interface2, interface3{
//インターフェイスの本体
}

上記インターフェイスを使用するとき
public class clsName extends superName implements interface0 {
}


★thisキーワードの勘違い
thisというキーワードはそのクラス内という意味合いだと思っていたが、
以下のようなコードで実行したところ、対象の変数が存在しない場合には
親クラスの変数がthis.変数 として使用されることがわかった。


abstract class MaterialObject {
String materials;
}

class Ball extends MaterialObject {
Ball() {
this.materials = "test2";
// materials = "test";  結局この3行は全て同じ変数にアクセスしている。
// super.materials = "test3";

System.out.println(materials);
System.out.println(this.materials);
System.out.println(super.materials);
}
}

public class testClass{
public static void main(String args[]) {
Ball ball = new Ball();
}
}

★抽象クラスの勘違い
抽象クラスでは変数を作成してはいけないものだと思っていた。
なぜならば抽象クラスをインスタンス化するとエラーが起きるからである。
しかし上記のように継承したクラスのインスタンスを生成することにより、
抽象クラスの変数も同時に作成されるような使い方をすることがわかった。


★★★★★抽象クラスとインターフェイスの違い★★★★★
抽象クラスとインターフェイスの違いがよくわからなかった。
インターフェイスは変数がpublic static final となり、
メソッドはpublic abstractとなる。
これらは抽象クラスでも実装できる。
それではなぜインターフェースを用いるのかというと、
Javaは複雑になるという理由で多重継承をサポートしていない。
そのため、制限をつけた継承をするといういみでインターフェースを用いる。
インターフェースならばいくらでも記述することができる。

★instanceof 演算子
演算子ということに注目
0xFFFF & 0x3333とかと同様、
オブジェクト instanceof オブジェクトのように使用するのだ。
変数を使用すると

if (He instanceof myfather) {
}

のように微妙な英文っぽいのを作成できる。
いやな感じだなこれ。
使い道としてはオブジェクトのクラスや、オブジェクトに実装されている
インターフェイスを確認することができる。
AとBが継承、またはインタフェースとして、関連付けられているのならばTRUEとなる。
よってinstanceof の後に来るものは、クラス名またはインターフェース名となる。

★パッケージとはクラスやインターフェイスの集まりのこと P221
使用方法は

package packageName;

のようにして用いる。
ひとつのファイルで用いることができるpackage文は一つのみ。
階層構造は.で区切る。

package folder1.folder2.signals;

ようは自分のファイルがあるディレクトリのことである。
普通にディレクトリを見ればわかるから, packageなんて書く必要ないのではないか?
と思えるが、書くらしい。
デフォルトパッケージを使っているとエラーが出ないので気がつかなかった。

★クラスパス
CLASSPATHは、.classファイルの検索先を指示するための環境変数。

★import とはCでいうインクルードと同じ
だが、*が使えるので、ディレクトリ以下を一度にインクルードすることもできる。

★P237 例外
Javaにはtry, catch, finallyという例外処理を行う手順が用意されている。
これは便利な機能だが、catchの数が多くなるとやはり見にくくなる気がする。
finallyは必ず実行される処理である。
switch文のdefaultとは違い、必ず実行される点に注意。
tryブロック内にreturn があったとしても、必ずfinallyが実行されてからreturnされる。
リソースを開放する目的で用いると便利。

★例外についての質問
例外がいっぱいあるようだが、catch節には全てのexceptionを網羅しなければならないのか?
->Exceptionを含めて例外は継承関係になっていて、
catch (Exception e) {
処理
}

と記載してあれば全ての例外を取得できる。ただし、Exceptionはほぼ最上位のエラーなので、
細かな処理を行いたいときには、

catch (例外 1) {
処理
}
catch (例外 2) {
処理
}
catch (例外 3) {
処理
}
catch (Exception e) {
処理
}

のように最後に記述する必要がある。
ただし、Javaコンパイラがcatchブロックの順序を判定してくれるので
意識しなくても大丈夫。
また、tryブロックで生成されない例外クラスに対応するcatch ブロックがある場合には
同じくコンパイラが発見してくれる
また、exceptionには検査例外とRuntiome Exceptionの2つがあるが、
Runtime Exceptionは0による除算や、不適当なキャストなどがあり、
検査例外は主にAPIのエラーである。
検査例外(API)はコンパイル時にチェックされ、なんらかの処置が必要である。


★throw ステートメント P246
前述の例ではJVMによって例外が生成されておりましたが、自分で作成するためには
throw ステートメントを使用する。

catch (ExceptionType param) {
throw param;
}

throw (スルー) を行うと、エラーをそこで消さないので、
以下のような処理を行うこともできる。

public static void c() {
try {
System.out.println("Before d");
d();
System.out.println("After d"); //1、この行は実行されない。
}
catch (ArithmeticException e) {
System.out.println("c: " + e);
throw e;
}
finally {
System.out.println("c: finally");
}
}

public static void d() {
try {
ゼロ割;
}
catch (ArithmeticException e) {
System.out.println("d: " + e);
throw e;
}
finally {
System.out.println("d: finally");
}
}

このようにエラー処理をd()で行い、さらにc()で行うこともできる。
また、注目してほしいのでは、1で1の行は実行されないのである。
JavaではCのようにネストを深くするのを避けるためにtry, catch, finallyをこのようにもちいる。


また、以下のように記載することで例外を生成することもできる。
class testClass {

public static void main(String args[]) {
try {
System.out.println("Before a");
a();
System.out.println("After a");
}
catch (Exception e) { //例外はすでに処理済なのでここの中には入らない。
System.out.println("main: " + e);
}
finally {
System.out.println("main: finally");
}
}

public static void a() {
try {
System.out.println("Before throw statement");
throw new ArithmeticException(); //例外生成
}
catch (Exception e) {
System.out.println("a: " + e); //ここで例外を処理している
}
finally {
System.out.println("a: finally");
}
}
}


★P252 catch節には必ずThrowable型のパラメータが必要です。
Throwable型のクラスには以下のよく使われるメソッドがあります。
getMessage() //コンストラクタから提供された文字列を返す
printStackTrace() //問題が発生した時点でのスタック情報を表示する。

Errorクラスは発生する可能性が低いので、考慮する必要はほとんど無し。
ExceptionクラスはThrowableクラスとは継承関係にあり、Throwableクラスを拡張します。
Exceptionクラスの主なサブクラスとしては、

ClassNotFoundException クラスが見つからなかった
IllegalAccessException クラスに不正にアクセスしようとした
メソッドが見つからなかった、スレッド割り込みが入った
などがある。


★P256 throwsステートメント
呼び出し元に対して例外を投げる可能性があるメソッドを書いた場合は、
他のプログラマにわかるようにどの例外が投げられるのかを明示しておくこと。
これはやらなければいけないことである。
試してみると、非常に便利なことがわかった。

class testClass {
public static void main(String args[]) {
a();
}

public static void a() {
try {
b();
}
catch (ClassNotFoundException e) { //?
System.out.println("test1 ");
e.printStackTrace();
}
}

public static void b() throws ClassNotFoundException { //?
c();
}

public static void c() throws ClassNotFoundException { //?
Class cls = Class.forName("こんな名前は無いよ");
System.out.println("test1 "+ cls.getName());
System.out.println("test2 "+ cls.isInterface());
}
}

例えば?の箇所の記載を
public static void c() throws ArithmeticException {
上記のように変更すると、処理されない例外の型 ClassNotFoundException というメッセージが出る。
よって、throws に記載できるものは起こりうるエラーしかかけないことがわかる。
そのため、この書き方では前頁のようにエラーメッセージを変更することはできない。

また?を以下のように変更すると
public static void b() {

「ClassNotFoundException の到達不可能な catch ブロック。
処理されない例外の型 ClassNotFoundException」
上記のようなエラーが出る。
かなりコンパイラが賢いようだ。

以下のように記載することにより、例外を作成することもできる。
static void c() throws ExceptionA, ExceptionB { //複数の例外が起きる可能性がある場合
Random random = new Random();
int i = random.nextInt();
if (i % 2 == 0) {
throw new ExceptionA("We have a problem"); //例外生成
}
else {
throw new ExceptionB("We have a big problem"); //例外生成
}
}


★マルチスレッドプログラミング
デッドロックの発生に注意する必要がある。
プロセスよりもコンテキストの切り替えにかかる時間が短い。
スレッドには優先順位が付けられる。
同じ優先順位のスレッドは時分割で実行される。
スレッドを使用するためにはThreadクラスを継承すればよい。

class sureddo extends Thread {
public void run() { //スレッドの処理はrun() という固定の名前を用いる
//スレッドの処理
}
}

スレッドの起動には次の構文を用いる。
sureddo tx = new sureddo();
tx.start();

スレッドを作成する方法はもう一つあって、
Runnableインターフェイスを実装したクラスを宣言する方法がある。

class testclass implements Runnable {
public void run() {
//スレッドの処理
}
}

上記文のスレッドの起動は次のとおり
testclass ry = new testclass();
Thread zy = new Thread(ry);
zy.start();

継承は一つしかできないので、制約があるときには便利かもしれませんね。
スレッドの優先度は実は3つしかない。
Threadクラスが持っている、静的メソッドには以下がある。
スレッドへの参照を返す。
スレッドをmsec秒間停止させる。
現在のスレッドから他のスレッドに制御を明け渡す。

Threadクラスに定義されている主なインスタンスメソッドには以下がある。
なぜインスタンスメソッドなのかというと、おそらくスレッドごとに変数を持っているから。
名前を返す
優先順位を返す。
スレッドが生きているか?
スレッドのrun()
スレッドの名前変更
スレッドを開始する
スレッドの優先順位を変更する


★データの同期
 マルチスレッドプログラミングではデータの同期が必要な場合がある。
その場合、synchronizedというキーワードを用いることにより、メソッドを同期させることが可能である。
読んでみたのだが、staticな変数と、synchronizedの処理、staticな関数などの使い分けが
よくわからない。P276
とりあえずsynchronizedの処理をはずして以下のコードとしてみたところ、
private int balance = 0;

/* synchronized */ void deposit(int amount) {
balance += amount;
System.out.println("amaunt = " + balance);
}

なんと結果は70程ずれが出てしまった。
単位は10単位で行っているので、実質7ずれがあることになる。
それではbalance に対してstatic な変数としてみる。

private static int balance = 0;

/* synchronized */ void deposit(int amount) {
balance += amount;
System.out.println("amaunt = " + balance);
}

すると、今度は、140(実質14)もずれた。
へーこんなにずれてしまうものなのかと、不思議に思う。
じゃあ、volatileはどうか?volatileの説明では「不意に値が変更されることがある変数。」と
記載されているので、今回の条件にぴったりだろうと思い以下のコードで試してみた。

class Account {
private volatile int balance = 0;

void deposit(int amount) {
balance += amount;

// 口座の残高を表示する
System.out.println("balance = " + balance );
}

int getBalance() {
return balance;
}
}

結果
驚くべきことに2380(実質238回)のずれが生じた。
・・・volatileのJavaの使い道がまったく持ってわからん・・・


スレッドを使用するプログラミングでは同期が必ず必要なようだ。

★デッドロック P277
スレッドが3以上の場合に起こる、三すくみ状態のこと。
AはBの開放を待ち、BはCの開放を待ち、CはAの開放を待つ状態。
A->B->C->A

これを回避するために全てのオブジェクトに優先順位を与えるとよい。
また、wait() メソッドを用いることにより、スレッドを待機させることができる。
notify()メソッドはロック開放を待機しているスレッドに対して通知を送ることができる


★クラスライブラリの説明 P290
Randomランダムクラス
Dateクラス
Calendarクラス
などがある。

★Vectorクラス、Enumerationインターフェイス
ベクトル、イナムレーションと読む

ベクトルとは動的配列のことである。
動的配列の個数はデフォルトでは10個である。
イナムレーションはオブジェクトに対して一定の処理を繰り返すために用いる。

サンプルコード
package testpackage;
import java.util.*;

class testClass {

public static void main(String args[]) {

// ベクトルとその要素を作成する
Vector vector = new Vector();
vector.addElement(new Integer(5));
vector.addElement(new Float(-14.14f));
vector.addElement(new String("Hello"));
vector.addElement(new String("konnichiwa"));
vector.addElement(new Long(120000000));
vector.addElement(new Double(-23.45e-11));

// ベクトルの全ての要素を表示する
System.out.println(vector);

// ベクトルに要素を挿入する
String s = new String("String to be inserted");
vector.insertElementAt(s, 1); //sを1番目のオブジェクトに対して上書きする。
System.out.println(vector);

// ベクトルから要素を削除する
vector.removeElementAt(3);  //3番目の要素を削除する。
System.out.println(vector);
}
}

結果
[5, -14.14, Hello, konnichiwa, 120000000, -2.345E-10]
[5, String to be inserted, -14.14, Hello, konnichiwa, 120000000, -2.345E-10]
[5, String to be inserted, -14.14, konnichiwa, 120000000, -2.345E-10]


import java.util.*;

class testClass {

public static void main(String args[]) {

// ベクトルとその要素を作成する
Vector vector = new Vector();
vector.addElement(new Integer(5));
vector.addElement(new Float(-14.14f));
vector.addElement(new String("Hello"));
vector.addElement(new Long(120000000));
vector.addElement(new Double(-23.45e-11));

// ベクトルの要素を表示する
Enumeration e = vector.elements(); //要素の列挙を返す
while(e.hasMoreElements()) { //次に要素があるか?
Object obj = e.nextElement(); //要素がある場合には次の要素を取得して出力
System.out.println(obj);
}
}
}

結果
5
-14.14
Hello
120000000
-2.345E-10

★Stackクラス P302
使わないみたいです。

★Hashtableクラス P303
ハッシュ表はオブジェクトの保存と取得で用いられるクラスです。
ハッシュ名と値に分離することができる。

★StringToknizerクラス P305
文字列をトークンに分解するために用いる。

この辺から、Cのライブラリにあるものとあまり変わらなくなってきたので、
いいペースで進む。

★入出力 P311 この辺もMFCとかで使っていたクラスと似たようなクラスばかりなので
飛ばせる。
とりあえず、バイナリデータの送信に用いるバイトストリームと
文字データの送信に用いる文字ストリームがあることがわかった。
★P340 ランダムアクセスファイル。
これまでの例ではファイルに読み書きはできても、
特定の文字の変更、置き換えなどはできなかった。
(例えば、一行読み書きなど)
しかし、ランダムアクセスファイルを使用すれば、ファイルのどの位置にもシークすることが可能である。
RandomAccessFileクラスを用いる。

★12章 ネットワーキング 面白そうなので最後に取っておく。
最後までとっておいたのに、ページ数は少ないし、目新しいことなし。



★13章 アプレット
特徴
ブラウザ環境で実行される"アプリ"である。
ローカルディスクにはアクセスできない。(サンドボックスの中でしか動けない)
Java以外の言語は実行できない。
ダウンロード先にホストにソケットを開くことはできるが、それ以外のホストには接続できない。
現在では信頼できる入手先からダウンロードされたアプレットのみ、他のホストに接続できます。
実行する環境はブラウザの環境で実行されるか、もしくはアプレットビューアーでも実行できます。
ですが、基本的にはブラウザで実行するものみたいです。
なお、アプレット内に記載されているHTMLはアプレットでもなく、アプレットビューアでのみ使用する。

画面の処理では、表示しながら処理を行うため、描画更新処理は必須となる。
ちらつき防止の方法として、ダブルバッファリングという手法を用いる。
イベントトリブン・・イベントが起きたときのみ、イベントハンドラからのイベントが通知されること。
これの逆で、定期的にちゃんと表示されているかなーとか確認したりすることをポーリング(定期調査)といいます。
ポーリングはCPUを非常に消費するので、通常イベントトリブンで処理が行われます。



★14章
代行イベントモデル 一つのソースから一つ以上のリスナに効率よく送信できるようにしたもの
イベントを生成するものをソース(ハンドラみたいなものか?)という。
ソースの責任は主に3つあり
1、 イベントに関する登録通知、登録解除
2、 イベント生成
3、 登録されている全てのリスナにイベントを送信すること。

送信する際にはユニキャストやマルチキャストの設定が可能。


アダプタクラス:マウスイベントを取得したいときなどに、クリック、押下、離したときなどさまざまなパターンがあるが、
インターフェースを用いた場合、これら全てを実装しなければならない(空関数でもいいので実装しなければならない)。
いちいち全てを実装するのはめんどくさい場合に、アダプタクラスを使用することができる。
アダプタクラスを使用すると、オーバーライドしたいメソッドのみを実装すればよくなるので、非常に便利である。

アダプタクラスには
KeyAdapter キー押下、
MouseAdapter マウスのボタン押下
MouseMotionAdapter マウスの移動
他、などが用意されている。
場所的にはjava.awt.event の下である。

★インナクラス
クラスの中にクラスがあるつくりである。
このクラスの使い道としてはアダプタクラスの作成が簡単になるということです。


public class testClass extends Applet {
public void init() {
setBackground(Color.green);
addMouseListener(new MyMouseAdapter());
}

class MyMouseAdapter extends MouseAdapter {

public void mousePressed(MouseEvent me) { //オーバーライドしたメソッド。アクションが起きるとコールされる
setBackground(Color.red); //継承なしにAppletクラスの親クラスが持つメソッドを利用している。
repaint();
}

public void mouseReleased(MouseEvent me) { //オーバーライドしたメソッド。アクションが起きるとコールされる
setBackground(Color.green); //継承なしにAppletクラスの親クラスが持つメソッドを利用している。
repaint();
}
}
}

★無名インナクラス
これはちょっと衝撃的なソースである。
やっていることは、一つ上のコードと同じこと。
クラスの中身を引数として箇所に書くと、名前を決めなくてもよい

package testpackage;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
/*


*/

public class testClass extends Applet {

public void init() {
setBackground(Color.green);

addMouseListener(
new MouseAdapter() { //ここにインスタンスを生成してしまうのは上記と変わらないが、クラスの中身まで書いてしまっている。

public void mousePressed(MouseEvent me) { //オーバーライドしたメソッド。アクションが起きるとコールされる
setBackground(Color.red);
repaint();
}

public void mouseReleased(MouseEvent me) { //オーバーライドしたメソッド。アクションが起きるとコールされる
setBackground(Color.green);
repaint();
}
});
}
}



★15章 AWT
画面関連なので、ここは流し気味で・・・


と言う研修を7日程度でやりました。
あれだけ読むのに苦労したJavaでも、仕事として学習を行うと結構あっという間に読めてしまうものですね。
スポンサーサイト
コメント(0)   2007.01.04    [ Myカテゴリ:時事・駄文 ]

コメントの投稿













管理者にだけ表示を許可する

Template Designed By
ぐらいんだぁ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。