System.out.println("またJavaの季節がやってきた!" + 2);
■ このスレッドは過去ログ倉庫に格納されています
去年の今頃Java学習開始するも挫折
しかし不屈の闘志をめらめらと燃やしながら
そびえ立つ岩壁にいどむため、再びこの地にやってきたのだ!
プログラミング歴は独学Cチョビッツ+独学VBA少々
きょうかしょ
https://www.amazon.co.jp/dp/484433638X
スッキリわかるJava入門 第2版 (スッキリシリーズ) まぁまぁ落ち着いて。
基礎的な動きを確認しながらプログラミング練習してる段階なんでね
これはこうしなければならないみたいなものより
これはこうしても動くし、こうやっても動くみたいな知識が面白いんだよ
javaでGUIってwなんていうけど
メーヴェを作って空を飛ぼうとしてるひとに向かって
空飛ぶならヘリコプターかセスナ使えよ!って言ってるのと同じだよ
ゴールに到達するまでの時間を競うつもりもないし。
プログラミングを仕事にしたらそういう世界になっていくんだろうけど
それってつまんないだろうなと思うんだ
せっかく面白い道具があるのに使い方を縛られるなんてね
>>156
どういうレベルから助言をくれてるのかわからないからどう答えるべきなのか迷うんだけど
まず問題なく動いているということが大事で
今作ったものを土台にいろいろ考えていけるといいなと思ってるよ
https://www.javadrive.jp/tutorial/jframe/index5.html
extends JFrame にかんしてはこれ
>ただし、上記のようにした場合、mainメソッドが含まれるSampleクラスは
>単にmainメソッドが存在するだけのクラスとなってしまいます。その為、
>通常はmainメソッドが含まれるクラスそのものをJFrameクラスの
>サブクラスにする方法が取られます。
このサイトではクラス名はSampleだけど、おれのだとMainのままになってるだけ。
おれはね、これ読んだ瞬間に面白いなぁって思ったんだけど。
自分とこのクラスにextendsして自分とこのmainメソッドで自分のインスタンス生成するとかさ
Swingではこれ普通なの?面白いじゃん
じゃ俺もこれ使おうと思ったんだけどね。
基礎レベルのおれには継承やら実装やらの感覚掴むのに悪くないなって思ってる
ちなみにイベント系のインターフェースも全部Mainに実装させたらMainの行があほみたいに長くなったね
今は匿名クラス使ってるけどね
Runnableも同じようなもんだよ
で、あとsleepか
そもそも起きた問題と何をしたら解決したのかがちゃんとそっちに伝わってるかわからないし
何を問題と捉えて助言をくれているのかもわからないからちょっと難しいよ
もし助言くれるなら、なぜthrd.sleep()だと注意マークがでてThread.sleep()だと出ないのかに
焦点を絞ったもので。引数がどうのこうのの話はそもそもそこが問題の原因ではないだろうと
目星を付けて適当に書いただけで。
問題にしているのはsleepの引数ではなくて、
sleepメソッドがインスタンスから呼び出される場合と
クラスから呼び出される場合の違いなんだ
だれかに何かを伝えるためにここに書いているというよりも
自分が見直した時に参考になる程度にしか書いてないから
いろいろ誤解を与えてるようですまんね
このときはこういう風に考えてたけど、間違ってたなとか、
逆に大事な事忘れてたなとか、あとで見たら面白そうじゃん
>>153
( ^ー゚)b ツールチップで次回取得予定の時刻表示させようとしたけど
右クリメニューとかち合うみたいなんでやめやめ
右クリメニューに表示させるかな
いずれにしてもRun()メソッドがらみなんでちょいめんどくさそう
こんなことやる前に、これまでまとめ上げた内容でもう一度作り直してスッキリさせたほうがいいかもしれん
右クリメニュー関連のコードが迷走してるし あとあれだなぁ
ScheduledExecutorServiceを習得したいね
めんどくさそうだったから、一番簡単な処理方法に逃げてきたんで お天気取得ソフトのエラーがたまに起きるので修正
0時回って5分後に取得しようとすると明日の日付がhtml上にまだ表示されてないようだ
このへん適当にコード書いたんで
日付がないときの分岐処理がなかった
String.containsみたいな処理書くときは忘れないようにしないとな
分岐させないと常にエラーがでるようなものだとすぐに気づくんだけど
たまにしかエラーがでないものだと忘れ去ってしまう
表示されたエラーの内容は半分忘れてしまったんだけど
Stringの配列要素番号として -1 が返されてた
明日の日付が見当たらないと -1 を返してくるようだ いやいや違う
>>160修正
containsは分岐処理でかくものだ
エラーの原因はindexOf()で起きてる
indexOfに渡す引数が見当たらない時にエラーだ ウィンドウのD&D移動で、
MouseListenerの
public void mousePressed(MouseEvent e)での処理なんだけど
いつも間違えるのは、コンポーネントの中での相対座標を取得するコード
JFrameを継承するクラス内だからComponentのメソッドで「も」ある
getX()やgetY()を前置きなしにそのまま使えるんだけど
ComponentのメソッドとしてのgetX()、getY()は相対座標取得のメソッドではない
getX()
コンポーネントの原点の現在のx座標を返します。
なんとなく掴みづらい表現なのだがコンポーネントの左上端の絶対座標を意味してる(と思う)
x = getX(); はダメ。ウィンドウ左上端の絶対座標をとってきてしまう
x = e.getX(); が正解。eを生んだコンポーネントであるJFrameの左上端を原点としたマウスプレス点の座標を取得できる
>>120では、この辺の処理は
pt = e.getPoint();
をつかっており、x と y をばらばらに取得していない
ばらばらに取得するならここで書いたように e.getX()、 e.getY() を使うことになる package privateのクラスをよく使うんだけど
スッキリ入門のどこに書いてあったか探し出せなかったんだけど
やっとみつかったわ
カプセル化のところだ タイトルなしのウィンドウを作り
D&D移動・右クリから閉じる・前回開いた場所で開き直す
こんだけはそらで書けるようにした
いろんな要素が含まれてるから基本覚えるには役に立つ
特にイベント処理は
ActionListener
MouseListener
MouseMotionListener
WindowListener
ComponentListener
が含まれていて練習としては悪くない
Propertyファイルの取り扱いも基礎レベルでしかないけど
しっかり覚えたんで今後に使えそう
またテキストに戻るか Main.class-----------------
public static void Main
class Aaa
class Bbb
---------------------------
これはOK
Xxx.class-------------------
class Aaa
class Bbb
----------------------------
これもOK
クラスはpublicとpackage privateしかない
デフォルトはpackage private >>166修正
public static void Main
↓
public class Main iPhoneアプリ作っても実機にいれようとすると年間1万ぐらい払わないといけないと聞いて
作るならandroidアプリだなと思っていたんだけど
よくよく調べてみるとすでに数年前から自分のiPhoneに入れるだけなら無料でいけるようだ
いずれにしてももう少し先の話だ
2. プログラミング言語
アプリを開発する上で最も重要なプログラミング言語。
Androidアプリで主に利用されるのはJavaとC++ですが、
2017年にはオフィシャル言語としてKotlinも追加されました。
iOSアプリは主にobjective-Cが使われますが、
より多くの人がiOSアプリを作れるようにと2014年にSwiftが
オフィシャル言語に追加されています。 いいでしょ
Xamarin(「ザマリン」と読みます)は、C#を用いてiOSとAndroidのアプリケーションを
開発するためのライブラリおよび開発環境です。
XamarinはMicrosoftよりVisual Studioの一部として提供されています ●iOSアプリ
プログラミング言語 Objective-C Swift
開発環境 Xcode
開発に使用するOS Mac
●Androidアプリ
プログラミング言語 Java
開発環境 Android Studio Eclipse
開発に使用するOS Windows Mac
↓
Xamarin
プログラミング言語 C#
開発環境 Visual Studio(Windows)もしくは Xamarin Studio(Mac)
開発に使用するOS Windows Mac
Windows上では、Visual Studioという非常に優れた開発環境を
利用してiOS/Androidアプリを開発することができます
(注: 詳しくは後述しますがiOSアプリをビルドするには別途Macが必要になります)。
って結局Macいるってことかいな
さすがに無理ですわ abstractクラスを継承したときに、
abstractなメソッドをオーバーライドして確定することを
「実装する」と表現する
これが「実装」という言葉の基本
インターフェースを実装するというのは
インターフェースに含まれるabstractなメソッドをオーバーライドして確定するからこそ
こういう表現が使われる eclipseでかき込んだメソッドやクラスにカーソルを合わせてから
F3を押すとそのメソッドやクラスの宣言が表示される 中身をみられる
F4を押すと階層構造をみることができる むむむ・・・クラウド上でiOSアプリをビルドする・・・だと・・?
https://www.macincloud.com/
でもどうやら有料@$22.5/月だそうで
http://www.nuits.jp/entry/2016/04/02/124859
ちなみにMacBook買うと大体10まんえんぐらい
ん〜やっぱないわ
さすがにMac囲い込みすぎだろ
iOSは駆逐されて欲しいわ オラクルの決定以後、Java周りはざわざわしてて
おれもこの先どうするか考えつつ勉強してる
とりあえず実践編読み終わってからちゃんと決めようとは思ってるが
できたら実践編の次にある2冊を読みたい
Javaそのものの勉強に限らず、サーバやらデータベースやら、
この辺の一般的な知識を頭に入れるいい機会なんじゃないかと思う
他の言語に行くのはいいんだけど、また一からやったら深い所に行くまでにまた時間かかってしまう
言語の勉強だけにいつまでも時間費やせないんで、選択に迷うところだ
すでにJavaScript、C#、pythonの入門本は買ってあるんで
ちょいちょい浮気しながら様子を見ていこうと思ってる >>173
追加
Shift+F2でeclipse内でAPIドキュメントを表示することができる ZonedDateTimeは実践編で紹介されていたのか
この辺の新しい日付の処理方法は便利だな
newできないものが多いから注意か
既に作ったプログラムで
DateとThreadを使っているものがあるんだけど
正しく動作しないことがあると書いてある
ふむむ ArrayList 面白いな
ラッパークラスがここに結びついてくるのか eclipseでimport文いれるのがめんどくさくなってきた
マウスをクラス名に合わせてポップアップから選択してたんだけど
もっと簡単な方法があるはずだと思ってしらべてみた
まず、* を使って省略して一気にimportすることにした
ウィンドウ→設定→Java→コードスタイル→インポートの編成
.*に必要なインポート数
これが99になってたので1にする
インポートの追加([Ctrl] + [Shift] + [M]) 1個ずつimport
インポートの編成([Ctrl] + [Shift] + [O]) 一気に全部import
これでずっと楽になるはず 実装されていないメソッドの追加 のショートカット
alt + shift + s + v 空白を示す正規表現に \s というものがある
これをこうやって使ってみるとエラーがでる
boolean b = "abc def".contains("\s");
これだとエラーがでない
boolean b = "abc def".contains("\\s");
ここに理由が書いてあった
https://teratail.com/questions/31841
が、\n だと \\n にしないでも動く
理由の解明は後回しにすることにする
とりあえず正規表現で \\ としないと駄目なことがあるということで。 典型的な本読んだだけで理解したつもりになってるタイプだな
入門編読み終わったんならオブジェクト指向で簡単なアプリで作ったら?
DBの代わりにファイルに読み書きするToDoリストやクリックすると月が替わるGUIカレンダーとか
本当に理解してるならこのくらい簡単に作れるはず
それもできないのに正規表現やThreat知っても成長しないぞ インプットとアウトプットは両方大事だね
これはどんな勉強にも言える
入門編読んでから
4つ作って常時起動してるPCでずっと動かしてる
もちろん入門テキストの知識だけでは作れないものなので
いろんなサイト巡って知識かき集めて作ってある
今やってるというか、つい最近までやっていた作業は
最後に作ったプログラムから自分が気に入った機能を実現するコードを抜き出して
雑だったものをもう少ししっかりしたものに組み直す
こんな風にしてお手本コードとしていくつか作っておく
そして、こいつらを何も見ずにざっと書けるようにする
書くたびに所々アレンジを加えていろいろ試して見る
ということをやってた
一つが大体300行程度のコードか
これは結構楽しい
ベースとなるコードは毎日同じなんだけど、理解が深まって悪くない
正規表現はずっと昔からいろんな所で使ってきたんだけど
もちろんプログラミング始める前の話ではある。
覚えようと思ってはいたんだけど、使う機会が年に数回であとはコピペでいけちゃって
なんとなくうやむやにしてて、しっかり頭に入れてなかった
なんというか、正規表現には思い入れがあって、是非自分のものにしたいなぁと。
ちょいちょい毎日のアレンジに組み込んで使っているのだ
数日前からはテキストを読み進めている
アウトプットは楽しいけど、インプットも進めないと知識の幅が広がらない
スカスカな知識でもいいから、こういう事ができるんだということをなんとなく覚えていると
アウトプットとしてソフトを作っているときに選択肢が広がる 具体的にどんなアプリ作ったんだ?
もしかして>>160みたいなの? ちなみにカレンダーはそのうち作ろうと思っている
上のほうですでに書いたんだけど、今デスクトップ上で表示してるカレンダーが
日本の祝日や振替休日を正確に示していないので、代用品が欲しい。
その辺から拾ってこれば早いんだけどそれじゃなんだし。
ところで、プログラムを作ってて思うのは、自作のクラスの
インスタンスを何個も作って活用するという場面はなかなか出くわさないということ。
いや、正確にいうと、そういう場面に無理やり持っていくこともできるんだけど、
無理してる感がすごくて、不自然すぎる
毎日アレンジ練習でプロパティファイルReaderクラスを作って遊んでたりする
カプセル化を施すためにフィールドをprivateにしてsetter、getterを作って
setterにはフィルターかけたりなんかするわけだけど、今までつくったような小規模ソフトだと
ここまでやっても、おいおい無理スンナよ・・・という天の声が聞こえてくる
多様性の練習でabstractクラスやinterfaceをいくつも作るのは面白い
最後にforでまわして結果がでるとすっきりする
が、練習でしかない
その点、カレンダーは日付クラスを作ると大量にインスタンス生成できたりなんかして面白そうだ
月クラスや年クラスなんかも組み込んじゃって多重構造にしちゃったりとかいろいろ想像してる
祝日やらの情報は内閣府のcsvを自動で取り込んで組み込んでもいい
おそらく今の知識で足りるだろう
じゃ、なんで作ってないのかというと、実践編の知識を組み込みたいと思ったからだ
組み込んだほうがよりコード的に面白そうなのがつくれるのであれば、だけど。
今日はコレクションの章を読んだんだけど、この辺も使えそうなら使ってみるつもりだ
日付という集合はキッチリカッチリ仕様が固まっているものなので、
曖昧さが残るデータを取り扱うのに便利そうなコレクションの知識は使えないかもしれないが。
もう一点カレンダーを作るのを遅らせている理由
今の知識だとThreadクラスに定期実行の役割を担わせていくしかない
でもThreadクラスはいろいろと問題があるようだ
既にPCで動かしている4つのソフトはどれもThreadクラスを使っていて
これ以上そういうソフトを増やすことでPCを不安定リスクに晒したくないというのがある。
これについては問題があって、ざっと見る限り実践編では解決する手段が書かれていない
ネットを漁るか別のテキストに手を伸ばすか、という話になる
コピペして流用するのは簡単だ
でも使うならコピペではなく、ちゃんと理解した上で使いたい
代用となるクラスについては上の方でも何度か書いているが
イマイチ自分の理解が浅い部分がある
この辺の理解が深まった頃にカレンダーを作るかもしれない
そう急ぐものではない 俺も入門書読んでた頃、カレンダーアプリ作ったことある
俺はMVCモデルで、viewはSwingで年月変更するボタンと7×6個のJTextFieldを用意して、そこにmodelとなる二次元配列で作った日付をcontrollerではめ込んでいくって設計にした
でも、日付の始まりは月によって違うし祝日は年によって日付が変わるからそこら辺の調整が結構悩んだな
頭で理解するのと、実際にオリジナルのアプリを作るのでは全然違うことを知った
いきなりThreat使ったアプリなんて作れるわけないんだから、まずは簡単な設計でオブジェクト指向に則ったちゃんと機能するアプリを作ってはどうよ? 兄さん、それThreatじゃなくてThreadっすよ
何度も間違えてるところからして使ったことないんだろうけど・・・・
おれの作ったアプリは全てThreadクラス利用した定期実行プログラム
兄さん・・・・
おれVBAやってたんだけど
やり始めて数ヶ月後にカレンダーをクラスモジュールとform使って作った
クリックすれば月がどんどん変っていくやつ
日付をクリックすることでその日付が起点となってエクセルの表に入っていく
おれにとってカレンダーを作る事自体はそう難しくないんだよ
VBAみたいなオブジェクト指向でない言語でクラスモジュール使って書く方がよっぽど難しいんだ・・・
てかね、そんな競争みたいのどうでもいいんだ
なんで言語やってると後ろから蹴り飛ばしながらお前のあれが悪いこれが悪いの
言う人多いんだろうか
楽しんでやろうよ?ね? 予測変換使ってたから間違い気づかんかったw
VBAってExcelのマクロを組んだってことでしょ?
そうじゃなくて一からアプリを作ったことあるのかってこと
雑学で本読んでるだけならどうでもいいけど、本気でプログラミングを学びたいなら方向が間違ってるってアドバイスしてるだけ ArrayListのインスタンスが変更されると発生する例外
ConcurrentModificationException
いろいろと書いてみるとたまに出る
iteratorを使って回してると出た
iterator宣言文をちょい上の方に書いてしまうと出るようだ
whileの直前にしたら出ない
どうやらArrayListにaddする前にiteratorをArrayListを対象に宣言してしまうとでるみたいだ
addし終わってからwhileで回す直前にいれるようにしよう iterate v 〜を反復する 〜を繰り返して言う 実践編はなかなか重いな
重要なコードはそらで書けるようにしていこう
曖昧なままだと先に進んだところでつまずく
とかいいつつ、どれがほんまもんに大事なコードなのかは先に進まないと分からないのだが
一応ArrayListとHashMapの操作法は基本的な部分は頭にいれた
ジェネリスクについてより深くやっていくようなのでちょうどよかった public static final String LS = System.lineSeparator();
改行 定数
今度からこれを使う事にする
旧版
public static final String LS = System.getProperty("line.separator"); 継承関係
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を表示出来ないかと思って試して見たんだけど成功 for (BattleCreature bc : alBC) {
System.out.println(bc.getClass().isInstance(c0);
}
とすることでBattleCreatureの中身がCharacterかどうかをbooleanで戻す事ができる
c0としてあるが、これはCharacter変数であればなんでもいい
要は、Character変数に代入できるかどうかを判定してくれてる と思ったが違うわ
c0の中身がHeroだから
Heroかどうかしか判定してくれてないな
ん〜失敗 どちらか全滅までの自動バトルプログラム完成
魔法使いカンの攻撃!
スライム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)
勇者ぽんは逃げ出した!
勇者ぽんたちは、ぜんめつしてしまった! 多様性とArrayListの復習になった!
おれさまはレベルがあがった! 逃げ出したのに全滅してしまった、はダメか
ここは要修正だな WHSをずっとやってた
簡単なコードおぼえた
フォルダ作ったりファイルコピーしたり。
Javaと比べると簡単 今日は復習だけ
WSHのコード2つ
実践編のコード3つ
これだけ
実践編のジェネリクスと列挙型の練習問題、金庫にアイテム出し入れするやつ
最初見たとき一体これはなにやってんだと思ったけど、
いろいろやってたら理解できた
・自作のジェネリクス付きのクラスを使う事でいろんな型のインスタンスをを金庫に入れることができるようにする
・次に、金庫を守るためにカギとなる仕組みを作る
ここで列挙型を利用する
久しぶりのswitchがでてきて復習になった
switch (keytype) {
case LOCK :
break;
case FINGER :
break;
}
2つを分離して考えないといけない 昨日少しだけラムダ式だっけか
読んだけど、また明日にしよう 実践編は各章の練習問題を解けるようにすることを目標とする
解けるというか、覚えて利用出来るようにしておく
これだけだと、テキストに書いてあることの一部しかカバーできない
でも、実践編では、最低限の重要な知識を抑えることに焦点を絞ることにする
toStringのオーバーライドとかクソつまらなさそうなのは切って捨てたいけどどうすっか
この辺は自分で使うイメージが全くわかない
コレクションのところで自然順序とかなんとかでこの辺のオーバーライドがされてないと
ダメだと説教されたんで、大事なんだろうけど
とにかく最後までなんとか読み切る Javaでは型安全、型安全で列挙型やらやってるんだけど
WSHは変数宣言いらないわ全部Variantだわで適当もいいところだ
楽だけど 復習復習復習
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日加算されたオブジェクトに置換える必要がある 同じような間違いとして
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()をつなげることはそもそもできない もう何度もやってるからわかってるわいと思ってアレンジして書くといろいろと問題が起きる
細かい部分が分かってないことがアレンジによって露呈する そういえばすっきり入門の最初の方でこういうのを書いていた
String s = new java.util.Scanner(System.in).nextLine();
理屈はいいから覚えろみたいなことが書いてあったんだけど
覚え直した方が逆に楽になりそうだ
Scanner sc = new Scanner();
String s = sc.nextLine();
単純にScannerクラスのインスタンス生成して
nextLine()を呼び出しているだけ
importは別途必要だ ディープクローンが難しかった
テキストと同じ形式なら理解できたんだけど
少し違った形にすると突然難しくなる
ディープクローンの必要性がある変数がprivateで
さらに、コンストラクタの引数になっているような場合
やっと練習用雛形作れたから何度も書いて理解していこうと思う
equalsやhashCodeその他のオーバーライドも組み込んだから
この辺の復習として使う
結局この辺はコレクション関連分野でもあるんで
コレクションの復習にもなる >>183について
\n
\s
この2つはそもそも種類が違う
\n は改行で、\s は空白だから違うのは当たり前とかそういう意味じゃない
属しているグループが全然違う
\n は \t \r などと同じ「エスケープシーケンス」
\s は \w \d などと同じ「あらかじめ定義されている文字クラス」
\n
" " の中にそのまま書いただけで \n という文字そのものではなく、
「改行」として認識される
\s
" " の中に書いたときに 「 \s という文字列として認識」 された場合に
初めて特殊な意味、ここでは「空白」として認識される
もう少し詳しく書く
"\s" と書いてしまうと、\ を特殊な記号として認識してしまう
そのため、これはエスケープシーケンスの一種だな、と誤解してしまう
しかしエスケープシーケンスには \s は存在しないため、エラーとなる
「 \s という文字列として認識」 させるには \ がもつ特殊な機能を消し去って
\ そのままの文字列として認識させる必要がある
そこで、\ の前にもう一つエスケープのための \ をつける
こうすることで、 「 \s という文字列として認識」 してもらえる
つまり、あらかじめ定義された文字列を matches などで使う時は、総じて \\s \\d \\w
のような書き方をしなければならないということになる >>216
修正
つまり、あらかじめ定義された文字列を matches などで使う時は、
↓
つまり、あらかじめ定義された文字クラスを matches などで使う時は、 >>183の中に書いてあるURL
ここで質問している人は、おれと同じように、
\n のようなエスケープシーケンスと混同したのだと思う
回答にはエスケープシーケンスとの違いが説明しているものがない
質問した本人は分かったつもりでいるみたいだけど、
問題は解決できてないんじゃないかと思う
スッキリ実践編にもその辺を書いてくれるとよかったな ここで疑問がもう一つ生まれる
\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 と書くとエラーでるし。
今後の課題として残しておこう >>219
String s1 = "\\s";
System.out.println(s1);
if (s1.equals("\\s")) {
System.out.println("s1 ok");
}
これで一応おk
要は s1 で \s と認識できたわけだから
同じようなレベルで認識してもらえるようなメソッドを使えばよいだけ
そもそもmatchesでは不可能なのかもしれない
containsでもいけた C#関連(本買っただけで何もやってないが)
ビルドの中にコンパイルがある。
コンパイル:
コンピュータが実行するのに適した形式に変えて、実行可能なファイルに変換する。
ビルド:
コンパイル+使っているライブラリに関連づける(リンク)
https://qiita.com/rico/items/9ab8aa110e757a13ef37
Visual Studio が無い Windows 環境で c# コードをコンパイルする
https://qiita.com/asterisk9101/items/4f0e8da6d1e2e9df8e14 スクリプト
簡易的なプログラムのこと。スクリプトを記述するための言語をスクリプト言語といい
、機械語への翻訳を必要とせずに実行できる。スクリプト言語は、
アプリケーション開発用の本格的なプログラミング言語に比べ、
用途を限定することで、覚えやすいように簡単な構造になっている。
代表的なスクリプト言語としては、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もスクリプト言語 × A.instanceof(B)
○ A instanceof B
instanceofは演算子
演算子の種類としては関係演算子または比較演算子と呼ばれるもので
==
<
>
<=
<=
!=
などと同じ種類
メソッドだと勘違いしがちなので注意だ
https://www.javadrive.jp/start/ope/index11.html 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;
が正解 >>219
正規表現で\sという文字列を表すにはエスケープして\\sとなる
だがこれをそのまま引数に渡すとJVMが最初の\を文字エスケープと認識して\sという文字列に変換し、結果的に正規表現の空白文字にマッチするか検証することになる
\\sという文字列を正規表現として渡すには文字エスケープが2つ付けて、\\\\sとする必要がある >>227
なるほどねぇ
言われてみればそうだな
String s = "\\s";
System.out.println(s);
if (s.matches("\\\\s")) {
System.out.println("ok");
}
ちなみにだけど、>>227の前半部分の説明を \n についてすると? ラムダ式とかの6章クリア
練習問題とstream()の基本的な使い方ぐらいだけど、まぁいいか
ぐぐるとラムダ式使ってるコードってたまに出てくるから
参考にしたいときに使える知識かなとは思う 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) >>230の2つ目を考えるにあたって注意しなければならないこと
あくまでも ProcessBuilder は「外部」プログラムの実行に使われる
よって、
Javaのクラスファイルを実行するといっても、
外部に存在しているコンパイル済のクラスファイルの実行に使うであって
今現在組んでいるソースコードに存在する他のクラスを指定してもダメ
コードが正常に動くか実験したい時に勘違いしないようにする 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に放り込んだらうまく起動した ProcessBuilderのテストはまた今度にしよう ここつまんねぇなぁ
覚えても意味なさそうだぁ
とか思っててもいざ練習問題ちゃんと出来るようにしようとすると
派生的にいろんな所の復習することになる
この 「いろんな所」 が結構大事な分野だったりするんで
結局がんばってやったほうがいいんだろうな よし、ProcessBuilderによるclassファイル実行でけた
eclipseの今扱っているプロジェクトのプロジェクトフォルダの直下に
フォルダaaaをおいてこの中にMain.classを入れる
ProcessBuilder pb = new ProcessBuilder("java", "aaa.Main");
pb.start();
で起動確認済 >>235の状況下で
Class<?> c = Class.forName("aaa.Main");
System.out.println(c.getName());
はできなかった
ProcessBuilderではいけるのになぜだ
もしかしてと思いながらbinフォルダの中にaaaフォルダをぶちこんだら行けてしまった
手法がどうであれ、ClassクラスもProcessBuilderと同様に外部のクラスファイルに
アクセスできるようだ eclipseでコマンドライン引数を渡して実行する方法
実行の構成→「引数」タブ→プログラムの引数
ここにコマンドライン引数を並べればいいだけ >>236はちと違う感じがする
クラスファイルへのアクセスってのは内部も外部もないのでは。
この辺は学習が進めばハッキリしてくるだろう 7章の練習問題は解答が間違えてるようだ
https://teratail.com/questions/153338
問題の指示によると、
文字列配列を引数とするmainメソッドの存在を確認しなければならない
存在する場合のみ、第二引数による条件分岐に入る
にもかかわらず、
@条件分岐に入ってから存在確認処理をしているのが第二引数が I のケース
Aそもそも存在確認を行ってさえいないのが第二引数が E のケース
@の存在確認とは、
getMethod()によって 文字列配列が引数であるmainメソッドを指定している
この条件に当てはまるメソッドがない場合に例外が投げられるようになってる
(throws Exception)
例外はメソッドを呼び出したmainメソッドで処理される
という部分を指している >>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上、カレントフォルダはプロジェクトのフォルダ直下(この辺は不確実) いやはや
やたら時間を食う章だ
今日はこの辺で終わり ちなみにリフレクションによる実行では
ちゃんとコンソールにprintlnの内容が表示される
これが
External Launch と
Internal Launch の違いってことかな >>238の続きなんだけど、リフレクションによる実行は「内部」だね
>>236で、binフォルダにaaaをぶち込むと実行できたのは
まさにbinフォルダが内部的なものだからだ
普通にクラスのソースコードを書いて実行するとbinフォルダにクラスファイルが生成される
つまり、binフォルダにクラスファイルを置くということは、
ソースコードに書いたのと結果的に同じ
外部のクラスファイルを持ってきたという考えはしない方がいい >>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);
}
-------------------------------------------------------------- この問題は例外処理の復習になる
●例外インスタンスを自分で投げるケース
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()はエラーメッセージを簡潔に書きたいときに使うもの、とする あとこれ
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クラスのインスタンスをここにもってこいという事 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クラスのインスタンスを生成して使いなさい!ということらしい クラス名.class
クラスリテラルとかなんとか
タイプリテラルとか
リテラル記法とか
なにやらかなり特殊な書き方のようだ
今日はこれで終わり 自作Classに含まれるメソッドリスト
main
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
これまで間違えてコードを書いてたみたいで
main以外表示されてなかったんだけど、さっき間違いに気づいて修正
こんなにでてきた
Objectクラスから引き継いだものも表示されるのな
複数のwaitはオーバーロードか コマンドライン引数によって受けとったclassファイルを
ProcessBuilderによって起動するテストをeclipse上でやろうとすると失敗することが多い
というかclassファイルのソースコードを修正しては起動するみたいなことをしていると起動しなくなったりする
eclipse上ではなくてちゃんとコマンドラインから起動すれば正常に動くので
eclipseの問題なのか
まぁこれ以上ここに時間を費やすのもどうかと思うから追究するのはやめるか 今日はずっと前にやってたところの復習してた
せっかく覚えたのに忘れるのもったいないからたまにやらないとね 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 宣言されているため
インスタンス生成が不要だった点 こういった構造を、フェイクを使いながら書くと、こんな感じになるのか
これでいいのかな
警告はでてるけど実行可
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);
}
} >>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);
}
} 例えばこのスレを 「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 はググってでてきたものを適当にいれたらいけたってだけ TeraPad というテキストエディタを昔から使っているのだが、
下の方に文字コードが表示される
試しにこのスレやgoogleの検索結果のページやらをコピペしてみたり
パソコン内にあるいろんなファイルをTeraPadで開いてみたりしたが
全て SJIS と表示されていた
というか SJIS と指定して開いているからそう表示されるのかもしれないが
少なくとも、TeraPad でみたときに文字化けしていない状態で、SJIS と表示されているなら
SJIS がこの場合の正しい文字コードなんだなと
ちなみにeclipse上で、デフォルト文字コードを取得するこれ
System.out.println(System.getProperty("file.encoding"));
を確認してみると UTF-8 と表示される
この違いが文字化けの原因だ ■ このスレッドは過去ログ倉庫に格納されています