X



トップページ独身男性
660コメント436KB
System.out.println("またJavaの季節がやってきた!" + 2);
■ このスレッドは過去ログ倉庫に格納されています
0001おれさま ◆6CTEZS59O00a
垢版 |
2018/09/13(木) 10:42:14.49
去年の今頃Java学習開始するも挫折
しかし不屈の闘志をめらめらと燃やしながら
そびえ立つ岩壁にいどむため、再びこの地にやってきたのだ!

プログラミング歴は独学Cチョビッツ+独学VBA少々


きょうかしょ
https://www.amazon.co.jp/dp/484433638X
スッキリわかるJava入門 第2版 (スッキリシリーズ)
0184Mr.名無しさん
垢版 |
2018/10/20(土) 14:08:51.80
典型的な本読んだだけで理解したつもりになってるタイプだな
入門編読み終わったんならオブジェクト指向で簡単なアプリで作ったら?
DBの代わりにファイルに読み書きするToDoリストやクリックすると月が替わるGUIカレンダーとか
本当に理解してるならこのくらい簡単に作れるはず
それもできないのに正規表現やThreat知っても成長しないぞ
0186おれさま ◆6CTEZS59O00a
垢版 |
2018/10/20(土) 15:52:45.04
インプットとアウトプットは両方大事だね
これはどんな勉強にも言える

入門編読んでから
4つ作って常時起動してるPCでずっと動かしてる
もちろん入門テキストの知識だけでは作れないものなので
いろんなサイト巡って知識かき集めて作ってある

今やってるというか、つい最近までやっていた作業は
最後に作ったプログラムから自分が気に入った機能を実現するコードを抜き出して
雑だったものをもう少ししっかりしたものに組み直す
こんな風にしてお手本コードとしていくつか作っておく
そして、こいつらを何も見ずにざっと書けるようにする
書くたびに所々アレンジを加えていろいろ試して見る
ということをやってた
一つが大体300行程度のコードか

これは結構楽しい
ベースとなるコードは毎日同じなんだけど、理解が深まって悪くない

正規表現はずっと昔からいろんな所で使ってきたんだけど
もちろんプログラミング始める前の話ではある。
覚えようと思ってはいたんだけど、使う機会が年に数回であとはコピペでいけちゃって
なんとなくうやむやにしてて、しっかり頭に入れてなかった
なんというか、正規表現には思い入れがあって、是非自分のものにしたいなぁと。
ちょいちょい毎日のアレンジに組み込んで使っているのだ

数日前からはテキストを読み進めている
アウトプットは楽しいけど、インプットも進めないと知識の幅が広がらない
スカスカな知識でもいいから、こういう事ができるんだということをなんとなく覚えていると
アウトプットとしてソフトを作っているときに選択肢が広がる
0187Mr.名無しさん
垢版 |
2018/10/20(土) 16:11:20.02
具体的にどんなアプリ作ったんだ?
もしかして>>160みたいなの?
0188おれさま ◆6CTEZS59O00a
垢版 |
2018/10/20(土) 16:34:18.61
ちなみにカレンダーはそのうち作ろうと思っている
上のほうですでに書いたんだけど、今デスクトップ上で表示してるカレンダーが
日本の祝日や振替休日を正確に示していないので、代用品が欲しい。
その辺から拾ってこれば早いんだけどそれじゃなんだし。

ところで、プログラムを作ってて思うのは、自作のクラスの
インスタンスを何個も作って活用するという場面はなかなか出くわさないということ。
いや、正確にいうと、そういう場面に無理やり持っていくこともできるんだけど、
無理してる感がすごくて、不自然すぎる

毎日アレンジ練習でプロパティファイルReaderクラスを作って遊んでたりする
カプセル化を施すためにフィールドをprivateにしてsetter、getterを作って
setterにはフィルターかけたりなんかするわけだけど、今までつくったような小規模ソフトだと
ここまでやっても、おいおい無理スンナよ・・・という天の声が聞こえてくる
多様性の練習でabstractクラスやinterfaceをいくつも作るのは面白い
最後にforでまわして結果がでるとすっきりする
が、練習でしかない

その点、カレンダーは日付クラスを作ると大量にインスタンス生成できたりなんかして面白そうだ
月クラスや年クラスなんかも組み込んじゃって多重構造にしちゃったりとかいろいろ想像してる
祝日やらの情報は内閣府のcsvを自動で取り込んで組み込んでもいい
おそらく今の知識で足りるだろう

じゃ、なんで作ってないのかというと、実践編の知識を組み込みたいと思ったからだ
組み込んだほうがよりコード的に面白そうなのがつくれるのであれば、だけど。
今日はコレクションの章を読んだんだけど、この辺も使えそうなら使ってみるつもりだ
日付という集合はキッチリカッチリ仕様が固まっているものなので、
曖昧さが残るデータを取り扱うのに便利そうなコレクションの知識は使えないかもしれないが。

もう一点カレンダーを作るのを遅らせている理由
今の知識だとThreadクラスに定期実行の役割を担わせていくしかない
でもThreadクラスはいろいろと問題があるようだ
既にPCで動かしている4つのソフトはどれもThreadクラスを使っていて
これ以上そういうソフトを増やすことでPCを不安定リスクに晒したくないというのがある。

これについては問題があって、ざっと見る限り実践編では解決する手段が書かれていない
ネットを漁るか別のテキストに手を伸ばすか、という話になる
コピペして流用するのは簡単だ
でも使うならコピペではなく、ちゃんと理解した上で使いたい
代用となるクラスについては上の方でも何度か書いているが
イマイチ自分の理解が浅い部分がある
この辺の理解が深まった頃にカレンダーを作るかもしれない

そう急ぐものではない
0189Mr.名無しさん
垢版 |
2018/10/20(土) 17:54:53.93
俺も入門書読んでた頃、カレンダーアプリ作ったことある

俺はMVCモデルで、viewはSwingで年月変更するボタンと7×6個のJTextFieldを用意して、そこにmodelとなる二次元配列で作った日付をcontrollerではめ込んでいくって設計にした
でも、日付の始まりは月によって違うし祝日は年によって日付が変わるからそこら辺の調整が結構悩んだな
頭で理解するのと、実際にオリジナルのアプリを作るのでは全然違うことを知った

いきなりThreat使ったアプリなんて作れるわけないんだから、まずは簡単な設計でオブジェクト指向に則ったちゃんと機能するアプリを作ってはどうよ?
0190おれさま ◆6CTEZS59O00a
垢版 |
2018/10/20(土) 18:45:27.82
兄さん、それThreatじゃなくてThreadっすよ
何度も間違えてるところからして使ったことないんだろうけど・・・・
おれの作ったアプリは全てThreadクラス利用した定期実行プログラム

兄さん・・・・

おれVBAやってたんだけど
やり始めて数ヶ月後にカレンダーをクラスモジュールとform使って作った
クリックすれば月がどんどん変っていくやつ
日付をクリックすることでその日付が起点となってエクセルの表に入っていく
おれにとってカレンダーを作る事自体はそう難しくないんだよ
VBAみたいなオブジェクト指向でない言語でクラスモジュール使って書く方がよっぽど難しいんだ・・・

てかね、そんな競争みたいのどうでもいいんだ
なんで言語やってると後ろから蹴り飛ばしながらお前のあれが悪いこれが悪いの
言う人多いんだろうか
楽しんでやろうよ?ね?
0191Mr.名無しさん
垢版 |
2018/10/20(土) 20:16:39.60
予測変換使ってたから間違い気づかんかったw

VBAってExcelのマクロを組んだってことでしょ?
そうじゃなくて一からアプリを作ったことあるのかってこと

雑学で本読んでるだけならどうでもいいけど、本気でプログラミングを学びたいなら方向が間違ってるってアドバイスしてるだけ
0193おれさま ◆6CTEZS59O00a
垢版 |
2018/10/21(日) 08:59:11.44
ArrayListのインスタンスが変更されると発生する例外
ConcurrentModificationException

いろいろと書いてみるとたまに出る
iteratorを使って回してると出た
iterator宣言文をちょい上の方に書いてしまうと出るようだ
whileの直前にしたら出ない

どうやらArrayListにaddする前にiteratorをArrayListを対象に宣言してしまうとでるみたいだ
addし終わってからwhileで回す直前にいれるようにしよう
0195おれさま ◆6CTEZS59O00a
垢版 |
2018/10/21(日) 15:19:05.05
実践編はなかなか重いな
重要なコードはそらで書けるようにしていこう
曖昧なままだと先に進んだところでつまずく
とかいいつつ、どれがほんまもんに大事なコードなのかは先に進まないと分からないのだが

一応ArrayListとHashMapの操作法は基本的な部分は頭にいれた
ジェネリスクについてより深くやっていくようなのでちょうどよかった
0198おれさま ◆6CTEZS59O00a
垢版 |
2018/10/22(月) 06:57:09.49
public static final String LS = System.lineSeparator();

改行 定数

今度からこれを使う事にする



旧版
public static final String LS = System.getProperty("line.separator");
0199おれさま ◆6CTEZS59O00a
垢版 |
2018/10/22(月) 10:09:45.11
継承関係
B a t t l e C r e a t u r e
↑            ↑
Character       Monster
↑    ↑       ↑
Hero Wizard     Slime

多様性の話
List<Character> alChar = new ArrayList<Character>();
Character c0 = new Hero("勇者あ");
Character c1 = new Hero("勇者い");
Character c2 = new Hero("勇者う");
Character c3 = new Hero("勇者え");
Character c4 = new Hero("勇者お");
Character c5 = new Wizard("魔法使いa");
Character c6 = new Wizard("魔法使いb");
Character c7 = new Wizard("魔法使いc");
alChar.add(c0);
alChar.add(c1);
alChar.add(c2);
alChar.add(c3);
alChar.add(c4);
alChar.add(c5);
alChar.add(c6);
alChar.add(c7);

List<Monster> alMons = new ArrayList<Monster>();
Monster m0 = new Slime('A');
Monster m1 = new Slime('B');
Monster m2 = new Slime('C');
alMons.add(m0);
alMons.add(m1);
alMons.add(m2);

List<BattleCreature> alBC = new ArrayList<BattleCreature>();
alBC.add(c0);
alBC.add(c1);
alBC.add(c2);
alBC.add(c3);
alBC.add(c4);
alBC.add(c5);
alBC.add(c6);
alBC.add(c7);
alBC.add(m0);
alBC.add(m1);
alBC.add(m2);

for (BattleCreature bc : alBC) {
 System.out.println(bc.getClass());
}

こうやってクラス名を取得したときにBattleCreatureではなく
中身のHero、Wizard、Slimeを表示出来ないかと思って試して見たんだけど成功
0200おれさま ◆6CTEZS59O00a
垢版 |
2018/10/22(月) 10:23:06.11
for (BattleCreature bc : alBC) {
 System.out.println(bc.getClass().isInstance(c0);
}

とすることでBattleCreatureの中身がCharacterかどうかをbooleanで戻す事ができる
c0としてあるが、これはCharacter変数であればなんでもいい
要は、Character変数に代入できるかどうかを判定してくれてる
0201おれさま ◆6CTEZS59O00a
垢版 |
2018/10/22(月) 10:24:50.00
と思ったが違うわ
c0の中身がHeroだから
Heroかどうかしか判定してくれてないな

ん〜失敗
0202おれさま ◆6CTEZS59O00a
垢版 |
2018/10/22(月) 12:36:38.25
どちらか全滅までの自動バトルプログラム完成

魔法使いカンの攻撃!
スライムAに14のダメージを与えた!(186)
スライムCの攻撃!
魔法使いトンは53のダメージをうけた!(0)
魔法使いトンは死んでしまった!
勇者ぽんの攻撃!
スライムBに0のダメージを与えた!(200)
スライムCの攻撃!
勇者ぽんは64のダメージをうけた!(36)
魔法使いコンの攻撃!
スライムBに42のダメージを与えた!(158)
魔法使いカンの攻撃!
スライムBに16のダメージを与えた!(142)
スライムCの攻撃!
魔法使いカンは127のダメージをうけた!(0)
魔法使いカンは死んでしまった!
勇者ぽんの攻撃!
スライムBに140のダメージを与えた!(2)
魔法使いコンの攻撃!
スライムBに22のダメージを与えた!(0)
スライムBを倒した!
スライムAの攻撃!
魔法使いコンは52のダメージをうけた!(0)
魔法使いコンは死んでしまった!
スライムCの攻撃!
勇者ぽんは21のダメージをうけた!(15)
勇者ぽんは逃げ出した!
勇者ぽんたちは、ぜんめつしてしまった!
0205おれさま ◆6CTEZS59O00a
垢版 |
2018/10/23(火) 13:12:01.82
WHSをずっとやってた
簡単なコードおぼえた
フォルダ作ったりファイルコピーしたり。
Javaと比べると簡単
0207おれさま ◆6CTEZS59O00a
垢版 |
2018/10/24(水) 15:52:11.45
今日は復習だけ

WSHのコード2つ
実践編のコード3つ

これだけ

実践編のジェネリクスと列挙型の練習問題、金庫にアイテム出し入れするやつ
最初見たとき一体これはなにやってんだと思ったけど、
いろいろやってたら理解できた

・自作のジェネリクス付きのクラスを使う事でいろんな型のインスタンスをを金庫に入れることができるようにする

・次に、金庫を守るためにカギとなる仕組みを作る
ここで列挙型を利用する
久しぶりのswitchがでてきて復習になった

switch (keytype) {
case LOCK :
 break;
case FINGER :
 break;
}

2つを分離して考えないといけない
0209おれさま ◆6CTEZS59O00a
垢版 |
2018/10/24(水) 16:07:34.72
実践編は各章の練習問題を解けるようにすることを目標とする
解けるというか、覚えて利用出来るようにしておく
これだけだと、テキストに書いてあることの一部しかカバーできない
でも、実践編では、最低限の重要な知識を抑えることに焦点を絞ることにする

toStringのオーバーライドとかクソつまらなさそうなのは切って捨てたいけどどうすっか
この辺は自分で使うイメージが全くわかない
コレクションのところで自然順序とかなんとかでこの辺のオーバーライドがされてないと
ダメだと説教されたんで、大事なんだろうけど

とにかく最後までなんとか読み切る
0210おれさま ◆6CTEZS59O00a
垢版 |
2018/10/24(水) 16:10:44.57
Javaでは型安全、型安全で列挙型やらやってるんだけど
WSHは変数宣言いらないわ全部Variantだわで適当もいいところだ
楽だけど
0211おれさま ◆6CTEZS59O00a
垢版 |
2018/10/27(土) 05:49:23.98
復習復習復習

Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_MONTH, get(Calendar.DAY_OF_MONTH) + 100);

のように書くと、c の日付は +100 される
これと比較したいのはLocalDateTimeクラスを使ったパターン↓

LocalDateTime ldt = LocalDateTime.now();
ldt.plusDays(100);

これだと ldt の日付は +100 されない
plusDays()をCalendarクラスのset()と同じような感覚で書くと間違える

plusDays()は戻り値がLocalDateTimeオブジェクト→オブジェクト変数に格納必要
set()は戻り値がvoid→変数への格納不要

正解は、2行目を
ldt = ldt.plusDays(100);
とすることで100日加算されたオブジェクトに置換える必要がある
0212おれさま ◆6CTEZS59O00a
垢版 |
2018/10/27(土) 05:55:24.37
同じような間違いとして

SimpleDateFormat sdf = new SimpleDateFormat("西暦yyyy年MM月dd日");
System.out.println(sdf.format(c.set(Calendar.DAY_OF_MONTH, get(Calendar.DAY_OF_MONTH) + 100).getTime()));

とするとエラー
原因は set() の戻り値をCalendarオブジェクトと勘違いしている点
もしそうであれば
c.set().getTime()
によってDateオブジェクトを取得できる
しかし
c.set()
はvoidである
よって、これにgetTime()をつなげることはそもそもできない
0213おれさま ◆6CTEZS59O00a
垢版 |
2018/10/27(土) 05:56:40.40
もう何度もやってるからわかってるわいと思ってアレンジして書くといろいろと問題が起きる
細かい部分が分かってないことがアレンジによって露呈する
0214おれさま ◆6CTEZS59O00a
垢版 |
2018/10/27(土) 06:01:38.39
そういえばすっきり入門の最初の方でこういうのを書いていた

String s = new java.util.Scanner(System.in).nextLine();

理屈はいいから覚えろみたいなことが書いてあったんだけど
覚え直した方が逆に楽になりそうだ

Scanner sc = new Scanner();
String s = sc.nextLine();

単純にScannerクラスのインスタンス生成して
nextLine()を呼び出しているだけ
importは別途必要だ
0215おれさま ◆6CTEZS59O00a
垢版 |
2018/10/27(土) 10:20:29.41
ディープクローンが難しかった
テキストと同じ形式なら理解できたんだけど
少し違った形にすると突然難しくなる

ディープクローンの必要性がある変数がprivateで
さらに、コンストラクタの引数になっているような場合

やっと練習用雛形作れたから何度も書いて理解していこうと思う

equalsやhashCodeその他のオーバーライドも組み込んだから
この辺の復習として使う
結局この辺はコレクション関連分野でもあるんで
コレクションの復習にもなる
0216おれさま ◆6CTEZS59O00a
垢版 |
2018/10/28(日) 03:59:48.27
>>183について

\n

\s

この2つはそもそも種類が違う
\n は改行で、\s は空白だから違うのは当たり前とかそういう意味じゃない
属しているグループが全然違う
\n は \t \r などと同じ「エスケープシーケンス」
\s は \w \d などと同じ「あらかじめ定義されている文字クラス」

\n

" " の中にそのまま書いただけで \n という文字そのものではなく、
「改行」として認識される

\s

" " の中に書いたときに 「 \s という文字列として認識」 された場合に
初めて特殊な意味、ここでは「空白」として認識される

もう少し詳しく書く

"\s" と書いてしまうと、\ を特殊な記号として認識してしまう
そのため、これはエスケープシーケンスの一種だな、と誤解してしまう
しかしエスケープシーケンスには \s は存在しないため、エラーとなる

「 \s という文字列として認識」 させるには \ がもつ特殊な機能を消し去って
\ そのままの文字列として認識させる必要がある
そこで、\ の前にもう一つエスケープのための \ をつける
こうすることで、 「 \s という文字列として認識」 してもらえる

つまり、あらかじめ定義された文字列を matches などで使う時は、総じて \\s \\d \\w
のような書き方をしなければならないということになる
0217おれさま ◆6CTEZS59O00a
垢版 |
2018/10/28(日) 04:01:51.70
>>216
修正

つまり、あらかじめ定義された文字列を matches などで使う時は、

つまり、あらかじめ定義された文字クラスを matches などで使う時は、
0218おれさま ◆6CTEZS59O00a
垢版 |
2018/10/28(日) 04:14:51.67
>>183の中に書いてあるURL
ここで質問している人は、おれと同じように、
\n のようなエスケープシーケンスと混同したのだと思う

回答にはエスケープシーケンスとの違いが説明しているものがない
質問した本人は分かったつもりでいるみたいだけど、
問題は解決できてないんじゃないかと思う

スッキリ実践編にもその辺を書いてくれるとよかったな
0219おれさま ◆6CTEZS59O00a
垢版 |
2018/10/28(日) 05:11:57.84
ここで疑問がもう一つ生まれる

\s が 「 \s という文字列として認識」 されたときに初めて 「空白」 と捉えてもらえる
それならば、
\s という文字列とマッチするかどうかを調べたいときはどうすんぢゃい と。

String s1 = "\\s";
System.out.println(s1);
if (s1.matches("\\s")) {
 System.out.println("s1 ok");
}

これではokはでない
s1 は \s と認識されているが
matches("\\s") の \\s は 「空白」 として認識されてしまうためマッチしない
\s と書くとエラーでるし。

今後の課題として残しておこう
0221おれさま ◆6CTEZS59O00a
垢版 |
2018/10/28(日) 05:32:20.22
>>219

String s1 = "\\s";
System.out.println(s1);
if (s1.equals("\\s")) {
 System.out.println("s1 ok");
}

これで一応おk
要は s1 で \s と認識できたわけだから
同じようなレベルで認識してもらえるようなメソッドを使えばよいだけ
そもそもmatchesでは不可能なのかもしれない

containsでもいけた
0222おれさま ◆6CTEZS59O00a
垢版 |
2018/10/28(日) 06:27:50.57
C#関連(本買っただけで何もやってないが)

ビルドの中にコンパイルがある。

コンパイル:
コンピュータが実行するのに適した形式に変えて、実行可能なファイルに変換する。

ビルド:
コンパイル+使っているライブラリに関連づける(リンク)

https://qiita.com/rico/items/9ab8aa110e757a13ef37


Visual Studio が無い Windows 環境で c# コードをコンパイルする
https://qiita.com/asterisk9101/items/4f0e8da6d1e2e9df8e14
0223おれさま ◆6CTEZS59O00a
垢版 |
2018/10/28(日) 06:34:16.89
スクリプト

簡易的なプログラムのこと。スクリプトを記述するための言語をスクリプト言語といい
、機械語への翻訳を必要とせずに実行できる。スクリプト言語は、
アプリケーション開発用の本格的なプログラミング言語に比べ、
用途を限定することで、覚えやすいように簡単な構造になっている。
代表的なスクリプト言語としては、JavaScript、PHP、Perlなどがあり、
特定のアプリケーションの動作の記述、マクロやバッチファイルの作成、
CGIなどの簡単なプログラムに用いられる。
https://kotobank.jp/word/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88-4871


最近使ってるVBSもスクリプト言語
0225おれさま ◆6CTEZS59O00a
垢版 |
2018/10/28(日) 08:30:31.85
public class Book {
 public boolean equals(Object o) {
  if (o == this) return true;
  if (o == null) return false;
  if (!(o instanceof this)) return false;//←ここダメ
 }
}

A instanceof B

「参照型変数a が bクラス/インターフェース/配列のインスタンスかどうか」
を調べるものなので
Bにインスタンスを持ってきてはダメ

Bに来るのはこの場合だとクラス名のBook

if (!(o instanceof Book)) return false;

が正解
0227Mr.名無しさん
垢版 |
2018/10/29(月) 02:05:19.26
>>219
正規表現で\sという文字列を表すにはエスケープして\\sとなる
だがこれをそのまま引数に渡すとJVMが最初の\を文字エスケープと認識して\sという文字列に変換し、結果的に正規表現の空白文字にマッチするか検証することになる
\\sという文字列を正規表現として渡すには文字エスケープが2つ付けて、\\\\sとする必要がある
0228おれさま ◆6CTEZS59O00a
垢版 |
2018/10/29(月) 11:11:41.30
>>227
なるほどねぇ
言われてみればそうだな

String s = "\\s";
System.out.println(s);

if (s.matches("\\\\s")) {
System.out.println("ok");
}


ちなみにだけど、>>227の前半部分の説明を \n についてすると?
0229おれさま ◆6CTEZS59O00a
垢版 |
2018/10/29(月) 11:13:40.08
ラムダ式とかの6章クリア
練習問題とstream()の基本的な使い方ぐらいだけど、まぁいいか

ぐぐるとラムダ式使ってるコードってたまに出てくるから
参考にしたいときに使える知識かなとは思う
0230おれさま ◆6CTEZS59O00a
垢版 |
2018/10/29(月) 15:29:01.06
ProcessBuilder pb = new ProcessBuilder(
    "c:\\windows\\system32\\notepad.exe", "calcreport.txt");

ProcessBuilder pb = new ProcessBuilder("java", clazz.getName() );

こいつら、上が第7章198ページ、下が同じく第7章217ページ練習問題の答

上が本文内で出てきたときは、まぁこんな感じで外部のexe起動できるんだな
ああそうですか、で終わった

練習問題で下のが出てきて???????????????ですわ
一応練習問題はできるようにするという目標を立てているので、しゃーないから調べてみた

意外と簡単だった

つまりだ、
●CMDでなんかプログラムを起動するときに
>xxx yy zz
みたいに打ちこんでEnterパーン!てやるとする
ちなみにxxxはexeだったりいろいろ

●これをJavaから同じように起動したいと思うなら
ProcessBuilder pb = new ProcessBuilder("xxx", "yy", "zz");
pb.start();

具体的に書くと
●CMD
>notepad /W test.txt
●Java
ProcessBuilder pb = new ProcessBuilder("notepad", "/W", "test.txt");
pb.start();

CMDでnotepadのかわりにnotepad.exeとしてもいいのだが
これはJavaのほうでも同じで "notepad" のかわりに "notepad.exe" としてもよい
ちなみにメモ帳はパスが通ってるからCMDにおけるカレントフォルダがどこであっても
notepad.exeへの完全なパスなしで起動できる

ProcessBuilderの第一引数においても同様に絶対パスを書く必要はない
とにかくCMDでどう書くのかを参考にして書けばいいだけ

よって上に書いた1個目のProcessBuilderの宣言で
ProcessBuilder pb = new ProcessBuilder("notepad.exe", "calcreport.txt");
と書いてもいける

ただし、違いが一つある
CMDだとcalcreport.txtがカレントフォルダになければ新しく作りますか?
とのウィンドウがでる
Javaではcalcreport.txtが存在しないとエラーが生じる

2つ目の
ProcessBuilder pb = new ProcessBuilder("java", clazz.getName() );
も同様
CMDでFQCNを使ってclassファイルを実行する場合に
>java jp.co.aaa.Calc
としてEnterパーン!とするなら
Javaでは
ProcessBuilder pb = new ProcessBuilder("java", "jp.co.aaa.Calc");
pb.start();
と書く
第二引数が clazz.getName() となっているのはFQCNを取得するためだ 👀
Rock54: Caution(BBR-MD5:1341adc37120578f18dba9451e6c8c3b)
0231おれさま ◆6CTEZS59O00a
垢版 |
2018/10/29(月) 16:30:53.48
>>230の2つ目を考えるにあたって注意しなければならないこと

あくまでも ProcessBuilder は「外部」プログラムの実行に使われる
よって、
Javaのクラスファイルを実行するといっても、
外部に存在しているコンパイル済のクラスファイルの実行に使うであって
今現在組んでいるソースコードに存在する他のクラスを指定してもダメ

コードが正常に動くか実験したい時に勘違いしないようにする
0232おれさま ◆6CTEZS59O00a
垢版 |
2018/10/29(月) 16:44:08.02
Eclipseで楽してたらコマンドラインから実行する方法忘れてしまった

例:
Main.class
-----------------------
package aaa;

public class Main {
 public static void main(String[] args) {
  System.out.println("test");
 }
}
-----------------------

(パスを通さないことを前提に説明・カレントフォルダ名はtestとする)
これをコマンドラインから起動するときは
フォルダtestの中にフォルダaaaを作る
その中にMain.classを入れておく
propertiesファイルとか使うなら
フォルダtestに入れておく
CMDでフォルダtestに移ってから
>java aaa.Main
で起動

eclipseのワークスペースからクラスファイルを拾ってくる時は
binフォルダの中をみればいい
ただ、この中にMain.classとは異なる見慣れないものが入ってたりする
Main$1.class
Main$2.class
Main$3.class

eclipseがバックアップ用に用意したものかと思ってフォルダaaaにコピペしなかったらエラー
表示をみるとどうやらこいつらも必要なようだ
この3つもaaaに放り込んだらうまく起動した
0234おれさま ◆6CTEZS59O00a
垢版 |
2018/10/29(月) 16:51:03.00
ここつまんねぇなぁ
覚えても意味なさそうだぁ
とか思っててもいざ練習問題ちゃんと出来るようにしようとすると
派生的にいろんな所の復習することになる
この 「いろんな所」 が結構大事な分野だったりするんで
結局がんばってやったほうがいいんだろうな
0235おれさま ◆6CTEZS59O00a
垢版 |
2018/10/30(火) 10:33:26.15
よし、ProcessBuilderによるclassファイル実行でけた

eclipseの今扱っているプロジェクトのプロジェクトフォルダの直下に
フォルダaaaをおいてこの中にMain.classを入れる

ProcessBuilder pb = new ProcessBuilder("java", "aaa.Main");
pb.start();

で起動確認済
0236おれさま ◆6CTEZS59O00a
垢版 |
2018/10/30(火) 11:14:46.84
>>235の状況下で

Class<?> c = Class.forName("aaa.Main");
System.out.println(c.getName());

はできなかった
ProcessBuilderではいけるのになぜだ

もしかしてと思いながらbinフォルダの中にaaaフォルダをぶちこんだら行けてしまった
手法がどうであれ、ClassクラスもProcessBuilderと同様に外部のクラスファイルに
アクセスできるようだ
0237おれさま ◆6CTEZS59O00a
垢版 |
2018/10/30(火) 12:48:17.63
eclipseでコマンドライン引数を渡して実行する方法

実行の構成→「引数」タブ→プログラムの引数

ここにコマンドライン引数を並べればいいだけ
0238おれさま ◆6CTEZS59O00a
垢版 |
2018/10/30(火) 12:59:51.70
>>236はちと違う感じがする
クラスファイルへのアクセスってのは内部も外部もないのでは。
この辺は学習が進めばハッキリしてくるだろう
0239おれさま ◆6CTEZS59O00a
垢版 |
2018/10/30(火) 13:38:32.43
7章の練習問題は解答が間違えてるようだ
https://teratail.com/questions/153338

問題の指示によると、
文字列配列を引数とするmainメソッドの存在を確認しなければならない
存在する場合のみ、第二引数による条件分岐に入る

にもかかわらず、
@条件分岐に入ってから存在確認処理をしているのが第二引数が I のケース
Aそもそも存在確認を行ってさえいないのが第二引数が E のケース

@の存在確認とは、
getMethod()によって 文字列配列が引数であるmainメソッドを指定している
この条件に当てはまるメソッドがない場合に例外が投げられるようになってる
(throws Exception)
例外はメソッドを呼び出したmainメソッドで処理される
という部分を指している
0240おれさま ◆6CTEZS59O00a
垢版 |
2018/10/30(火) 15:06:42.90
>>239の間違いを正したコードを書いてた

これでいいだろと思って実行してみるんだけど
ProcessBuilder による起動がうまくいかない
起動するクラスのmainメソッドには

System.out.println("eating memory.......");

と書いてあるのだが、これが表示されない
ProcessBuilderによるクラス実行は実験済で間違いないはずなのだが
いろいろやっても上コメントが表示されない

まさかな、と思ってこれを実行するクラスのmainメソッドに追加

JFrame jf = new JFrame();
jf.setSize(100, 100);
jf.setVisible(true);

そしたらなんとフレームが出現するじゃないか
ProcessBuilderによる実行は、「外部プログラム」の実行なので、printlnがあっても
内部的な処理結果を表示するコンソール画面には出ないということか

ちなみに実行するクラスファイルはbinフォルダに置いたままではだめ
プロジェクトのフォルダ直下に置く
ProcessBuilderによる実行は、やはり「外部のプログラム」を動かすものなので
eclipse上、カレントフォルダはプロジェクトのフォルダ直下(この辺は不確実)
0242おれさま ◆6CTEZS59O00a
垢版 |
2018/10/30(火) 15:12:25.80
ちなみにリフレクションによる実行では
ちゃんとコンソールにprintlnの内容が表示される
これが
External Launch と
Internal Launch の違いってことかな
0243おれさま ◆6CTEZS59O00a
垢版 |
2018/10/30(火) 15:46:01.03
>>238の続きなんだけど、リフレクションによる実行は「内部」だね
>>236で、binフォルダにaaaをぶち込むと実行できたのは
まさにbinフォルダが内部的なものだからだ
普通にクラスのソースコードを書いて実行するとbinフォルダにクラスファイルが生成される
つまり、binフォルダにクラスファイルを置くということは、
ソースコードに書いたのと結果的に同じ
外部のクラスファイルを持ってきたという考えはしない方がいい
0244おれさま ◆6CTEZS59O00a
垢版 |
2018/10/31(水) 13:56:32.92
>>239の問題をクリア

@で使っている例外を利用してmainメソッドの存在確認をする方法は
秀逸だと思うので、これはちゃんと利用する
ただし、
launchInternalメソッドの中に書くのではなく
mainメソッドに書く

---------------------------------------------
try {
 m = c.getDeclaredMethod("main", String[].class);
} catch (NoSuchMethodException e) {
 System.out.println("指定されたメソッドが存在しません。");
 System.exit(1);
}
-----------------------------------------------
m は static なクラス変数として宣言したMethodクラスのインスタンス変数
クラス変数としたのは launchInternalメソッドにおいて invoke するのに流用するため

あと、launchExternal メソッドで起動した場合に起動確認のためJFrameを表示させたい
そこでMemoryEaterクラスの main メソッドの中にJFrame表示のコードを入れた
さらにフレームタイトルに launchInternal、 launchExternal どちらから起動されたか
わかるように I か E の文字をいれることにする
そのため、これらのメソッドを起動する際に、I か E の引数を渡すことにする
内部起動か外部起動かによって引数の渡し方が違ってくるところがポイント
-------------------------------------------------------------
public static void launchExternal(Class<?> clazz) throws Exception {
 ProcessBuilder pb = new ProcessBuilder("java", clazz.getName(), "E");
 Process proc = pb.start();
 proc.waitFor();
}
public static void launchInternal(Class<?> clazz) throws Exception {
 String[] args = {"I"};
 m.invoke(null, (Object)args);
}
--------------------------------------------------------------
0245おれさま ◆6CTEZS59O00a
垢版 |
2018/10/31(水) 15:24:10.35
この問題は例外処理の復習になる

●例外インスタンスを自分で投げるケース
throw new IllegalArgumentException("起動方法の指定が不正です");

IllegalArgumentExceptionはメソッドの引数が不正

●例外を伝播させる
public static void launchExternal(Class<?> c) throws Exception { }

throws と複数になってるところがポイント

●例外処理中の e.getMessage() とは
これは e.printStackTrace() を使った場合に表示されるメッセージが冗長なため、
これらのメッセージのうち一部分だけを表示させたいときに使うようだ
具体的には、今取り組んでるコードにおいて、実行対象となるクラスにmainメソッドがない場合

もし e.printStackTrace() なら
-----------------------------
java.lang.NoSuchMethodException: MemoryEater.main([Ljava.lang.String;)
 at java.lang.Class.getMethod(Class.java:1786)
 at Main.main(Main.java:19)
------------------------------

もし System.out.println(e.getMessage()); なら
------------------------------
MemoryEater.main([Ljava.lang.String;)
------------------------------

調べた結果このようになったのだが、疑問に感じたのは実践編7章解答で
catchの中にこのような記述がある

System.out.println(e.getMessage());
e.printStackTrace();

包含関係にあるこの2つを並べることに何の意味があるのか分からない
今のところは自分が調べた結果を信じることにしておこう
e.getMessage()はエラーメッセージを簡潔に書きたいときに使うもの、とする
0246おれさま ◆6CTEZS59O00a
垢版 |
2018/10/31(水) 16:06:25.26
あとこれ

Method m = clazz.getMethod("main", String[].class);

getMethodメソッドの第二引数 String[].class
この class は何なんだ!
調べまくって何となく分かったんだけど、要はこの class は実践編209ページの
Class インスタンスの基本的な取得方法の一つ

Class<?> cinfo = クラス名.class

の class と同じものだということ。
String[].class は文字列型配列に関するClassクラスのインスタンスである

リフレクションと呼ばれる分野について学習してるわけなんだけど
特徴的なのはあるクラスを対象とするとき、
そのクラスを対象とするClass クラスのインスタンスを生成する点

この先はざっくりとした説明になる。

場合によるのだろうが、この分野において、
メソッドに渡す引数の(クラス)型を指定するときも
同様の配慮をしなければならないようだ
つまり、メソッドの仮引数が
int i となっていたら、実引数は
int.class のように表現する場合があるということ

getMethod のレファランスを見てみると

public Method getMethod(String name,
Class<?>... parameterTypes)

Class<?> はまさにClassクラスのインスタンスをここにもってこいという事
0247おれさま ◆6CTEZS59O00a
垢版 |
2018/10/31(水) 16:18:48.94
clazz の宣言文を補足する
例えばこんな風になる

Class<?> clazz = MemoryEater.class;
Method m = clazz.getMethod("main", String[].class);

これは、下のように書いてもよいということになる

Class<?> clazz = MemoryEater.class;
Class<?> stClazz = String[].class;
Method m = clazz.getMethod("main", stClazz);

分析の対象となるクラス(MemoryEater)もClassクラスのインスタンスを生成し
分析の対象となるクラスで使われる引数のクラス型(String[])についても
Classクラスのインスタンスを生成して使いなさい!ということらしい
0248おれさま ◆6CTEZS59O00a
垢版 |
2018/10/31(水) 16:33:22.21
クラス名.class


クラスリテラルとかなんとか
タイプリテラルとか
リテラル記法とか

なにやらかなり特殊な書き方のようだ

今日はこれで終わり
0249おれさま ◆6CTEZS59O00a
垢版 |
2018/11/02(金) 16:05:26.41
自作Classに含まれるメソッドリスト

main
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

これまで間違えてコードを書いてたみたいで
main以外表示されてなかったんだけど、さっき間違いに気づいて修正
こんなにでてきた
Objectクラスから引き継いだものも表示されるのな
複数のwaitはオーバーロードか
0250Mr.名無しさん
垢版 |
2018/11/03(土) 09:49:29.26
コマンドライン引数によって受けとったclassファイルを
ProcessBuilderによって起動するテストをeclipse上でやろうとすると失敗することが多い
というかclassファイルのソースコードを修正しては起動するみたいなことをしていると起動しなくなったりする
eclipse上ではなくてちゃんとコマンドラインから起動すれば正常に動くので
eclipseの問題なのか
まぁこれ以上ここに時間を費やすのもどうかと思うから追究するのはやめるか
0251おれさま ◆6CTEZS59O00a
垢版 |
2018/11/03(土) 16:42:46.49
今日はずっと前にやってたところの復習してた
せっかく覚えたのに忘れるのもったいないからたまにやらないとね
0252おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 08:00:49.41
9章269ページあたりを読んでるんだけど
System.out.println() とは結局何なのだろうかと。

System はクラス名で
out はそのフィールドで、型は PrintStream

つまり System クラスでは
PrintStream out;
みたいな宣言があるわけだ
(実際には public final static PrintStream out = null;)

んで、PrintStream クラスのメソッドの一つに
println() がある

out はクラス型をフィールドに用いたもの
すっきり入門340ページの Hero クラスのフィールドとして宣言されている
Sword sword;
と同じようなものか

341ページの下に
hsword.name
というのがあるが、もし Sword クラスの name フィールドが private で
getter が置かれているとしたら
@ h.sword.getName()
となっていたはず

これと
A System.out.println()
は結構似てると考えていいのか

違いは、@では Hero クラスの中で宣言されている sword は static ではないため
アクセスするには Hero クラスのインスタンス h を生成したが
Aでは、System クラスの中で宣言されている out が static 宣言されているため
インスタンス生成が不要だった点
0253おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 08:04:52.55
こういった構造を、フェイクを使いながら書くと、こんな感じになるのか
これでいいのかな
警告はでてるけど実行可

public class Main {
public static void main(String[] args) {
Systemm.outt.printlnn("aaa");
}
}
class Systemm {
static PrintStreamm outt;
}

class PrintStreamm {
public static void printlnn(String st) {
System.out.println(st);
}
}
0254おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 08:14:14.18
>>253の PrintStreamm#Printlnn から static を抜いたら警告が消えた
理由はあとで考えることにする

public class Main {
 public static void main(String[] args) {
  Systemm.outt.printlnn("aaa");
 }
}
class Systemm {
 public static PrintStreamm outt;
}

class PrintStreamm {
 public void printlnn(String st) {
  System.out.println(st);
 }
}
0255おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 09:22:15.30
例えばこのスレを 「2ch.txt」 に全コピペして保存

(例外は投げるとする)
FileReader fr = new FileReader("2ch.txt");
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while (line != null) {
 System.out.println(line);
 br.readLine();
}

これだと文字化けしてしまう
そこで文字コードを指定したい

実践編260ページの記述によると、
FileReaderのコンストラクタで文字コード指定ができるかのように思われるが
実際はできない。いや出来るのかもしれないが調べた限りでは分からなかった ぞ

文字コードの指定には
FileInputStream
InputStreamReader
を使う
(この辺はHTML取得の時に使ったコードに似てる
URL、InputStream、InputStreamReader を使った)

FileInputStream fis = new FileInputStream("2ch.txt");
InputStreamReader isr = new InputStreamReader(fis, "SJIS");
BufferedReader br = new BufferedReader(isr);
String line = br.readLine();
while (line != null) {
 System.out.println(line);
 br.readLine();
}

これで文字化け回避できた
SJIS はググってでてきたものを適当にいれたらいけたってだけ
0256おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 09:34:16.09
TeraPad というテキストエディタを昔から使っているのだが、
下の方に文字コードが表示される
試しにこのスレやgoogleの検索結果のページやらをコピペしてみたり
パソコン内にあるいろんなファイルをTeraPadで開いてみたりしたが
全て SJIS と表示されていた

というか SJIS と指定して開いているからそう表示されるのかもしれないが
少なくとも、TeraPad でみたときに文字化けしていない状態で、SJIS と表示されているなら
SJIS がこの場合の正しい文字コードなんだなと

ちなみにeclipse上で、デフォルト文字コードを取得するこれ
System.out.println(System.getProperty("file.encoding"));
を確認してみると UTF-8 と表示される

この違いが文字化けの原因だ
0257おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 15:53:55.10
この辺はstream関連のクラスがたくさん出てきて何がなんだか分からなくなる

整理する

-------------------------------基本用語
●文字ストリーム系
Writer、Reader がクラス名に入る
●バイトストリーム系
OutputStream、InputStream がクラス名に入る
--------------------------------

・基本用語の頭に File がつくと
ストリームの終端がファイルであるクラスになる

・基本用語の頭に Buffered がつくと
バッファリングされた出力または入力ストリームをつくるクラスになる

・特殊なものとしてバイトストリームと文字ストリームの橋渡しをするクラス
OutputStreamWriter : 文字をバイトにエンコード
InputStreamReader : バイトを文字にエンコード
どちらも指定された文字セットを用いて変換することになるが
指定がなければシステムのデフォルトの文字セットを用いることになる
この文字セット指定がまさしく >>255でやった "SJIS" である
ここでは文字セットとは文字コードと同義か
0258おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 16:02:55.25
>>255を再考

FileInputStream fis = new FileInputStream("2ch.txt");//@
InputStreamReader isr = new InputStreamReader(fis, "SJIS");//A
BufferedReader br = new BufferedReader(isr);//B
String line = br.readLine();
while (line != null) {
 System.out.println(line);
 br.readLine();
}

>>257の「基本用語」に注目しながら分析

@一旦バイトストリームによってファイルを読み込んでいく (バイトだからInputStream)
A吸い上げたバイトを文字にエンコードするが、その際文字セットを SJIS に指定 (橋渡し役)
B変換された文字をバッファリングする (文字だからReader)
0259おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 16:08:17.01
InputStreamReaderのせいで頭が混乱してた
常に文字セットを指定してれば橋渡し変換役だってことが理解できてたんだけど
文字セット指定がないデフォルトでこれまで使ってたんで
役割が頭ん中で明確になってなかった
0260おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 16:30:14.54
public class Main {
 public static void main(String[] args) {
  FileInputStream fis = null;
  FileOutputStream fos = null;
  BufferedOutputStream bos = null;
  GZIPOutputStream gos = null;
  try {
   fis = new FileInputStream("test.txt");
   fos = new FileOutputStream("test.txt.gz");
   bos = new BufferedOutputStream(fos);
   gos = new GZIPOutputStream(bos);
   int i = fis.read();
   while (i != -1) {
    gos.write(i);
    i = fis.read();
   }
  } catch(IOException e) {
   e.printStackTrace();
  } finally {
   try {
    if (fis != null) fis.close();
    if (gos != null) gos.close();
   } catch(IOException e) {
    
   }
  }
 }
}

実践編9章の練習問題
コマンドライン引数はテストが面倒なので内部指定した
test.txt を読み込んで、同じ内容を test.txt.gz にかき込むんだけど、
書込みの際のフィルタリングとして
バッファリング+圧縮
が指示されている

文字ストリームは一切使わず
バイトストリームのみで処理するため
Reader、Writer がついたクラスは出てきていないのがポイント
0261おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 16:37:31.85
FileOutputStream

BufferedOutputStream

GZIPOutputStream

の順でフィルタにかけてるんだけど

FileOutputStream

GZIPOutputStream

BufferedOutputStream

でやったらどうなるかテストしてみた
作成されるgzファイルが壊れてた
GZIPOutputStream が最後じゃないとだめみたいだ
0262おれさま ◆6CTEZS59O00a
垢版 |
2018/11/04(日) 16:40:45.04
>>260修正

gos.flush();

を忘れてた
while ブロックの直後に挿入するとする
ふらぁぁぁぁぁぁぁっしゅ!
0263わがはい ◆0BMoNHqNlM
垢版 |
2018/11/04(日) 18:45:21.35
>>261
逆でもいけるやろ
どっちもOutputStreamのサブクラスなんやから
gzip形式で圧縮してるんだから直で開いても見えへんで
解凍するかGZIPInputStream使わんと

public class Main {
public static void main(String[] args) {
try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream("test.txt"));
   BufferedOutputStream gos = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream("test.txt.gz")));) {
int i;
while ((i = fis.read()) != -1) {
gos.write(i);
}

} catch (IOException e) {
e.printStackTrace();
}

try (BufferedReader gis = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream("test.txt.gz"))));) {
String str;
while ((str = gis.readLine()) != null) {
System.out.print(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
0264おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 04:19:58.31
>>263
ほんとだ
たぶんコードをどこかで間違えてたな

しかしわかりにくいので勝手に改変
GZIP→Buffer (test_gos-bos.txt.gz)
Buffer→GZIP (test_bos-gos.txt.gz)
フィルタ順を変えた2つ圧縮ファイルが作られるがどちらも正常

public class Main {
 public static void main(String[] args) {
  try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream("test.txt"));
    BufferedOutputStream bos = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream("test_gos-bos.txt.gz")));) {
   int i;
   while ((i = fis.read()) != -1) {
   bos.write(i);
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
  
  
  try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream("test.txt"));
    GZIPOutputStream gos = new GZIPOutputStream(new BufferedOutputStream(new FileOutputStream("test_bos-gos.txt.gz")));) {
   int i;
   while ((i = fis.read()) != -1) {
   gos.write(i);
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}
0265おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 04:22:22.69
自分のコードでも成功

public class Main {
 public static void main(String[] args) {
  FileInputStream fis = null;
  FileOutputStream fos = null;
  BufferedOutputStream bos = null;
  GZIPOutputStream gos = null;
  
  //bos→gosの順
  try {
   fis = new FileInputStream("test.txt");
   fos = new FileOutputStream("test_bos-gos.txt.gz");
   bos = new BufferedOutputStream(fos);
   gos = new GZIPOutputStream(bos);
   int i = fis.read();
   while (i != -1) {
    gos.write(i);
    i = fis.read();
   }
  } catch(IOException e) {
   e.printStackTrace();
  } finally {
   try {
    if (fis != null) fis.close();
    if (gos != null) gos.close();
   } catch(IOException e) {}
  }
  
  //gos→bosの順でもOK
  try {
   fis = new FileInputStream("test.txt");
   fos = new FileOutputStream("test_gos-bos.txt.gz");
   gos = new GZIPOutputStream(fos);
   bos = new BufferedOutputStream(gos);
   
   int i = fis.read();
   while (i != -1) {
    bos.write(i);
    i = fis.read();
   }
  } catch(IOException e) {
   e.printStackTrace();
  } finally {
   try {
    if (fis != null) fis.close();
    if (bos != null) bos.close();
   } catch(IOException e) {}
  }
 }
}
0266おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 04:28:03.98
fos = new FileOutputStream("test_bos-gos.txt.gz");

fos = new FileOutputStream("test.txt_bos-gos.gz");
と指定すると
中身のファイルが、拡張子なしの
test.txt_bos-gos
になるという事に気づいた
こういう仕様なのか

ちなみに作成された圧縮ファイルが正常化どうかのチェックは
WinRARを使って適当にやってる
0267おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 04:34:40.49
そして flush() がまた抜けているという件
ふらぁぁぁぁっぁぁぁぁぁっしゅ!!!
0268おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 04:42:11.26
finally使わないでいい書き方だけど
try () のカッコの中に複数文書いてもいいんだな
おれはこういう風に書きたい

public class Main {
 public static void main(String[] args) {
  try (
   BufferedInputStream fis = new BufferedInputStream(new FileInputStream("test.txt"));
   BufferedOutputStream bos = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream("test_gos-bos.txt.gz")));
  ) {
   int i;
   while ((i = fis.read()) != -1) {
   bos.write(i);
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}
0269おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 07:18:55.78
12章のデータベースアクセスを読んでいるのだけど
実践編の次の位置にあるテキストとして
スッキリわかるSQL入門がある
これはJavaのテキストかと思っていたのだが
そういうわけではなさそうだ

「スッキリわかるサーブレット&JSP入門」 はJavaのテキスト

この2冊に踏み込むべきか、迷うところだ
0270おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 08:08:19.43
ん〜いろいろぐぐってみたがSQL入門は買っておいたほうがよさそうだな
どうせだからサーブレットの方も買うか?
0271おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 08:26:18.37
それはともあれ、データベースは実践編12章で触ることになるため
DBMSの導入が必要となる

ここでは実践編が勧める HS Database を導入することにする
インストールまでは簡単だ
適当にぐぐれば出てくる
次に・・

実践編335ページ
>以後、この章のプログラムの実行時には、このJARファイルにクラスパス
>(eclipseの場合はビルドパス)を通して実行する必要があります。

eclipseを使っているのでビルドパスとやらを通さなければならない
調べた結果

ビルドパスはプロジェクトごとに通していくことになる
ここでいうJARファイルとは、バージョンごとにファイル名は違うだろうが
おそらくH2 Databaseをインストールしたフォルダにあるこれ
H2\bin\h2-1.4.197.jar
であろうと推測できる

このjarファイルを外部のライブラリとして追加していくことを意味するのだろう

まずプロジェクトのプロパティーを開く
方法はいろいろあるが、パスを通したいプロジェクトをパッケージエクスプローラで選択した状態で
プロジェクト→プロパティー
次に
→「ライブラリー」タブ→外部JARの追加
ここで上記のjarファイルを選択する

こうすることで、パッケージエクスプローラ上で、当該プロジェクトを開いた場合に
「参照ライブラリー」 が追加されており、この中に h2-1.4.197.jar が配置されることになる

不正確なら以後修正していく
0272おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 08:50:42.49
public class Main {
 public static void main(String[] args) {
  try {
   Class.forName("org.h2.Driver");
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
  Connection con = null;
  try {
   con = DriverManager.getConnection("jdbc:h2:G:\\DB\\H2_Database\\test01");
  } catch(SQLException e) {
   e.printStackTrace();
  } finally {
   if (con != null) {
    try {
     con.close();
    } catch(SQLException e) {
     e.printStackTrace();
    }
   }
  }
 }
}


ファイルが作成されたので、これでとりあえずいいのか

Class.forName("org.h2.Driver");
の org.h2 については、パッケージエクスプローラから h2-1.4.197.jar を開くと
直下に同じ名前のパッケージがあるので、これだろう
0273おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 09:44:33.60
ん〜ん〜
実践編361ページのコード
これおかしくないか?
いろいろとまだ知識が固まってないので自信あるわけではないが

con.close();

の位置
finally ブロックに書かれているのは、どんなときでも必ず実行されなければならないから。
(もちろん if 文で示す通り null の時は除くけど)

しかしだ、この finally ブロックが置かれている位置、catch ブロックの「中」だぞ?
ということは例外が catch されなければ実行されないんじゃないのか?

おかしいのであれば誰かネット上で指摘してるはずだと思って
ぐぐってみたけどヒットしない
おれがおかしいのですか〜
0274おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 09:49:38.56
public class Main {
 public static void main(String[] args) {
  //finallyが※の内側のケース
  try {
   Class.forName("org.h2.Driver");
  } catch (ClassNotFoundException e) {//※
   System.out.println("@");
   try {
    Class.forName("org.h2.Driver");
   } catch(ClassNotFoundException ee) {
    System.out.println("A");
   } finally {
    System.out.println("finally内側");
   }
  }
  
  //finallyが※の外側のケース
  try {
   Class.forName("org.h2.Driver");
  } catch (ClassNotFoundException e) {//※
   System.out.println("A");
   try {
    Class.forName("org.h2.Driver");
   } catch(ClassNotFoundException ee) {
    System.out.println("B");
   }
  } finally {
   System.out.println("finally外側");
  }
 }
}


結果は 「finally外側」

「finally内側」 が表示されるのは、一つ目の※で存在しないクラスを指定した時
この時例外をキャッチして catch ブロックに入る
そこで初めて finally は実行される

ん〜おかしいよね?
0275おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 09:56:03.51
いや、話はもう少し複雑なのか?

con が catch 文の中でも使われているから内側、外側両方で finally がいるということか?
つまり上の例で言えば

public class Main {
 public static void main(String[] args) {

  try {
   Class.forName("org.h2.Driver");
  } catch (ClassNotFoundException e) {//※
   System.out.println("@");
   try {
    Class.forName("org.h2.Driver");
   } catch(ClassNotFoundException ee) {
    System.out.println("A");
   } finally {
    System.out.println("finally内側");
   }
  } finally {
   System.out.println("finally外側");
  }
 }
}
0276おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 10:06:50.64
いやいや、やっぱり違う

内側で使った con は結局、外側の finally で close されるからいいんだ
やっぱ内側の finally は必要ないはずだ

にも関わらず実践編361ページでは内側のみに finally があるのでおかしいなぁ
というのが疑問点
0277おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 10:11:57.82
ま、とりあえず12章まで読むだけ読んだ
ちょい飛ばしたから、今週は先へは進まずに復習のみでもおkか
0278おれさま ◆6CTEZS59O00a
垢版 |
2018/11/05(月) 15:23:34.40
とか言いながら、斜め読みしながら先へ進むおれ

「リファクタリング」

これな
以前VBAの10,000行ぐらいのプログラム書いたんだけど
おれが組んだもので一番でかいやつ
今も他人によって使われてて、自分でいうのもなんだけど役に立っている

しかし中のコードはひどいもので
その原因の一つは、VBAを一から勉強しながら書いていたから、
勉強初期の頃のコードと、それなりに理解できてきた頃のコードが絡まり合って、それはもう。
もう一つは、計画性がなく気ままに機能を追加してきた結果、ネストの階層がとんでもなく深い

滅多に表層にでないバグを潰したりして、最終的に完成するまでに2年はかかっている

たぶんもう一度組み直せばすっきりとして実行速度もあがると思うのだが
あの苦労をもう一度・・・と思うと。

コードをいじらないでも設定を柔軟に変えられるよう、
各種設定値をワークシート上に記述できるようになってはいるのだが
実は全て正常に動くかは全部チェックしてない
この辺も組み直す過程でチェックできるだろう

今はおれが触れる場所にいるのでなんとかなるのだが
いずれ離れる予定なので、それまでにはなんとかしないといけないのだが。

めんどい
0279わがはい ◆0BMoNHqNlM
垢版 |
2018/11/05(月) 16:54:41.40
初心者あるあるやね
ワイも昔は一つのクラスの中にズラーっと書いて保守性も拡張性も考えとらんかった
といってもプログラミング始めてまだ半年の素人やけども
最近は機能別にクラス分けするようにしとるけど、今度はどう設計するか考えんといかんからこれはこれで大変

>>272
finallyでcloseするとネストが深くなって可読性が落ちるし、し忘れることもあるからauto_closeにしたほうがええで
0280おれさま ◆6CTEZS59O00a
垢版 |
2018/11/06(火) 08:04:51.09
try {
} catch() {
} finally {
 if () {
  try {
  } catch() {
  }
 }
}

これはもうルーチンワークだわ
closeまで書いてから対象となるインスタンス生成してるぐらいだ
try(){} をベースにしようか迷ったけど
めんどくさい方を先に覚えて間違えずに書けるようにしたほうがいい
簡略化が導入されるまでみんな書いてたものだしね
0281おれさま ◆6CTEZS59O00a
垢版 |
2018/11/06(火) 11:08:00.61
スッキリわかるSQL入門 第2版 ドリル222問付き! (スッキリシリーズ)2018/11/30
中山清喬、 飯田理恵子


新しい版がでるそうなのであと3週間ほど待つ事にしよう
0282おれさま ◆6CTEZS59O00a
垢版 |
2018/11/07(水) 10:40:17.29
実践編どくはああああああああああああああああ

寄り道したくなってきたぞ
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況