業務備忘録

備忘録です

【Java】Integerってなんなの

2023-08-11 18:42:50 | 日記

1.Integerって何?

標記の通り。

Java習いたての頃からInteger.parseInt()で文字列を数値に変換…といった操作は お手の物であるわけですが、
一方でinteger型の変数に平気で数値リテラルが代入されているのも見かけたりするわけで、じゃあIntegerってint型とは何が違うわけ?という疑問が浮かぶのも当然です。

プリミティブ型はオブジェクトではなく、単なる値であり、それ自身はメソッドを持ちません。
しかし、プログラムの中では、プリミティブ型の値に対する操作(文字列との相互変換など)が必要になる場面がたくさんあります。
そこでJavaは、プリミティブ型を内包し、そのプリミティブ型の値を操作する機能を備えた「ラッパークラス」を提供しています。

Java 本格入門, 2023, 技術評論社

要はコード内で値であるかオブジェクトであるかの違いなんですね〜

2.何ができるの?

メソッド名 機能 コメント
valueOf(int i) 指定されたint値を表すIntegerインスタンスを返す Integerオブジェクトをnewするよりこれを使うほうがいいらしい
compare(int x, int y) 2つのint値を数値的に比較する Mathクラスかと思ってた
comareTo(Integer anotherInteger) 2つのIntegerオブジェクトを数値的に比較する  
intValue() Integerの値をintとして返す  
parseInt(String s)    
toString() Integerの値を表すStringオブジェクトを返します  
フィールド 内容 コメント
MAX_VALUE int型の最大値231-1を表す 桁溢れのチェックに使えそう。
MIN_VALUE int型の最小値-231を表す  

 

3.実際に使ってみる

/new 演算子でIntegerオブジェクトを生成するのはdeprecated
Integer integerTest1 = new Integer(1);
Integer integerTest2 = Integer.valueOf(1);

拡張機能を入れたvsCode上だとnew Integer(1)の部分は線で見せ消ちにされます。deprecatedは非推奨という意味。
valueOfメソッドを使用する場合は、引数が-128〜127の範囲であれば、valueOfメソッドがあらかじめIntegerオブジェクトを予め保存しているため、新たにIntegerオブジェクトを生成せずに済むらしい。
一方new 演算子でコンストラクタを呼び出すと必ずIntegerオブジェクトが生成されるため、メモリを圧迫してしまうとのこと。

ただしこの仕様のせいで挙動に注意が必要らしい。

3.1valueOf()した場合とコンストラクタを呼び出した場合

boolean integerCompared1 = Integer.valueOf(1) == Integer.valueOf(1);
System.out.println("valueOf()の取得結果同士の比較=>" + Boolean.valueOf(integerCompared1));

boolean integerCompared2 = Integer.valueOf(1) == new Integer(1);
System.out.println("valueOf()とnewした場合の比較=>" + Boolean.valueOf(integerCompared2));

3.2結果

valueOf()の取得結果同士の比較=>true
valueOf()とnewした場合の比較=>false

valueOfはキャッシュしてある生成済みのオブジェクトを返すので、valueOfの引数に-128〜127を指定した結果同士を比較した1行目は同じオブジェクトのアドレスを指すことになる。したがって比較結果はtrueとなる。
一方、newした場合は異なるオブジェクトのアドレスを比較するのでfalseとなる。

3.3気をつけましょう

Integerはint型を代入することができる。これは内部的にはInteger.valueOf()してintからIntegerに暗黙的に変換している。
なので、「Integerってint型を代入できるんだ(*^○^*)!ついでに比較して処理をすすめよう!」と考えると痛い目にあうことになる。

Integer integerTest5 = 100;
Integer integerTest6 = 100;
System.out.println(Boolean.toString(integerTest5 == integerTest6));
//true
 
Integer integerTest7 = 999;
Integer integerTest8 = 999;
System.out.println(Boolean.toString(integerTest7 == integerTest8));
//false

こうなる理由は3.2参照

 

3.4比較したいときはどうするの

Integer integerTest7 = 999;
Integer integerTest8 = 999;
System.out.println(integerTest7.compareTo(integerTest8));
//0

compareTo()メソッドを使うことで数値的に比較できる。
2つのオブジェクトを数値的に比較した場合の差を返すので、同じ値の場合は0となる。

とにかくInteger同士を比較演算で比較するのは結構危険そう。

4.Integerの初期値

クラスのフィールドとして、プリミティブ型のintを宣言した場合、初期値は0です。
これに対して、ラッパー型のIntegerを宣言した場合、初期値はnullとなります。
[...]このため、0とデータ型がない状態(空)を区別したい場合は、 ラッパー型を用いる必要があることがわかります。
[...]プリミティブ型を使用していると、値が取得できない場合に0(初期値)となるため、値が指定されていなくて初期値の0となったのか、値として0が指定されていたのかが区別できません。

Java 本格入門, 2023, 技術評論社

なるほど。

 

参考:

https://meetup-jp.toast.com/1808

『Java 本格入門』(2023,技術評論社)


【Java】hashMapを触る

2023-08-09 23:12:23 | 日記

Javaに触る機会ができたので渋々勉強します。今回はHashMapクラスで、要は合言葉(key)で値を取り出す連想配列です。

 

1.とりあえず触ってみる

vsCodeの拡張のせいで連想配列のメソッドの引数にラベル(key,value)がついてしまっていますが本来は無い想定で。

Map<Integer, String> map = new HashMap<>()
と初期化したので、今回はキーはInteger型で値はString型です。

注)コールバック関数…引数に指定された別の関数。画像では使い捨てのラムダ式を使用。

 

removeメソッドは存在しないキーを指定しても例外などは発生しない(nullを返す)。

2.キーと値の型を指定しない場合はObject型になるらしい

2.1 なんでも入るぞ

標題の通り、型を指定しない場合はkeyもvalueもObject型となります。Object型はすべてのクラスの基底クラスなので、
つまり、この場合は連想配列にはなんでも追加できることになります。
画像でもvalueにBooleanやString,int,自作のクラスも入れることができます。

もちろんkeyにもあらゆる型を代入可能。

2.2 キャストしないとね

当然ですがObject型で連想配列を使用している場合は型独自のメソッドなどは参照できないのでキャストする必要があります。

 

結局、Object型のHashMapを利用すれば複数の型・戻り値でreturnできるというわけですが、
なんでもObject型で解決するなら静的型付け言語の意味なくないですかね?


『ゼロからの自作OS入門』軽く詰まったところ①

2023-07-30 14:41:56 | 日記

10月の応用情報の申し込みをすっぽかしてしまったので、1月くらいまで暇。
そこで前から気になっていた『ゼロからの自作OS入門』を読み始めることにしました。あんまりネット上に記事もないので、詰まったことはちょっとしたことでも書いておきます。

【第1章 1.3】

まずはコマンドの中身から。

WSL(Windows SubSystem for Linux)上のubuntuからEFIファイルをUSBメモリにコピーするさいのコマンド(p.31)。

$ sudo mkdir -p /mnt/usbmem
$ sudo mount -t drvfs F: /mnt/usbmem
$ sudo mkdir -p /mnt/usbmem/EFI/BOOT
$ sudo cp BOOTX64.EFI /mnt/usbmem/EFI/BOOT
$ sudo umonut /mnt/usbmem

mountコマンド…「「mount」は、HDDやUSBメモリ、DVD-ROMなどのフォーマット済みの領域(ファイルシステム)を指定したディレクトリ(マウントポイント)と一時的に結び付けてアクセスできるようにするコマンドです」。
(https://atmarkit.itmedia.co.jp/ait/articles/1802/15/news035.html)

Windows側のドライブをマウントする場合は-t[ype] drvfsを指定する。
USBドライバー「F:」とubuntuの/mnt/usbmemディレクトリが結び付けられている。

そのため、3行目でmkdirコマンドで/EFI/BOOTディレクトリを作成したさいは、USB側にもF:直下にEFI/BOOTディレクトリが作成されている。

詰まったのは4行目のコピーコマンドです。
$ sudo cp BOOTX64.EFI /mnt/usbmem/EFI/BOOT
cp: cannot stat 'BOOTX64.EFI': No such file or directory

問題
Windows側のドキュメントフォルダに保存していたのでEFIファイルが見つからない。

解決

$ sudo cp /mnt/c/Users/[ユーザ名]/Documents/BOOTX64.efi /mnt/usbmem/EFI/BOOT

ubuntu側からはmnt/cからWindows側ユーザのCドライブが見られるようです。


【JavaScript】locationインターフェースを使えば遷移パラメータも簡単に取得できたのに

2023-07-29 20:06:49 | 日記

JSのlocationインターフェースを使う機会があったので勉強。

1.locationインターフェース(*)とは?

Location インターフェイスは、関連付けられたオブジェクトの場所 (URL) を表します。

                                ーmdn web docs

プロパティからURLの状態を取得したりメソッドで操作できる。

(*)「概念的に共通した部品と機能の集まり(もしくは操作の集まり)のことを インタフェース/interface」といいます
(https://zenn.dev/ojk/articles/js-interface)

概念として部品とその機能を定義したのがインターフェースで実体化されたものがオブジェクト。

2.実際に中身を見る

https://www.google.co.jp/?id=001&value=%22hello%22
にて実行!

後述のメソッドを使わなくても、location.hrefプロパティを更新するだけで遷移することができます。

  URL location.origin location.host location.hrefにセットする値
https://www.google.com/ "https://www.google.com" "www.google.com" "test"
https://www.google.com/test "https://www.google.com" "www.google.com" "https://yahoo.co.jp"
https://www.yahoo.co.jp/ "https://www.yahoo.co.jp" "www.yahoo.co.jp" "www.google.com"
  https://www.yahoo.co.jp/ "https://www.yahoo.co.jp" "www.yahoo.co.jp"

"test"のようにhref属性に指定する値にhttpsなどからはじまるプロトコル名を省略すると、originプロパティからの相対パスになるようです。
"https://yahoo.co.jp"のようにプロトコル名を指定した場合はそのまま遷移します。
"www.google.com"のようにホスト名を指定した場合は元のURLに遷移します。

 

メソッドたち。

assign() 引数に指定したURLに遷移。
reload() 現在のURLを再読み込みする。
replace() 引数に指定したURLに遷移。ただし戻るボタンを使用して戻ることはできない。
toString() URL全体を収めた文字列を返す。

 

3.URLから遷移パラメータをいい感じに切り出す

locationインターフェースのsearchプロパティにはクエリ文字列(*)が渡されます。
(*)クエリ文字列:遷移パラメータ、URLパラメータに同じ。


昔書いたダメな例
JSでURLから遷移パラメータを切り出そうとしています。

http:****?id=001&value=02のようなURLを処理するとして、
「substring()でクエリ文字列全体を切り出して、split()でパラメータ名と値を切り分けて…」などと書いていくのは面倒くさい。
そもそもlocationのsearchプロパティにクエリ文字列が格納されているので、substring()による切り出しは全く不要。

よさそうな例
URLインターフェースのsearchParamsプロパティを使いましょう。
searchParamsプロパティはキーと値がセットになったURLSearchParamsオブジェクトを返し、mapオブジェクト(*)と同様に操作することができます。
URLオブジェクトを使うために、当該ページのURL = location をコンストラクターに渡して初期化しています。
行数も格段に減りましたね。
 
URLオブジェクトの初期化時のパラメータには「絶対 URL または相対 URL を表す USVString」(mdn web docs)を渡しますが、渡すのはlocationオブジェクトでもlocation.hrefプロパティでもよいようです。

(*)map: 連想配列。合言葉となるキー(key)によって値(value)を取り出す。値を取得するときはget([キー名])メソッドを使用する。列挙するときはfor-inではなくfor-ofやforeachで。

SQL ServerにSQL認証でログインするときに出るエラーコード26

2023-07-29 02:03:26 | 日記

SQL Serverをインストール後、SQL認証にてログインしようとすると、必ず出るエラー。

SQL Server への接続を確立しているときにネットワーク関連またはインスタンス固有のエラーが発生しました。
サーバーが見つからないかアクセスできません。
インスタンス名が正しいこと、および SQL Server がリモート接続を許可するように構成されていることを確認してください。


サーバー認証を「SQL Server認証とWindows認証」(*)に選択しただけだとSQL認証でログインすることはできません。
* Windows認証はWIndowsのユーザ情報でログインする方式のこと。

結論から言うと、インストール後はデフォルトでSQL server Browserが起動していないので、起動させる必要がある。

  1. コントロールパネル→システムとセキュリティ→管理ツール→サービス→一覧からSQL Server Browserのプロパティを開いて、スタートアップの種類を「手動」にする。
  2. SQL Server構成マネージャを起動→SQL Serverのサービス→SQL Server Browserの開始モードを「自動」にする。

1.の手順を踏まないと構成マネージャから起動できないので注意。