- 投稿日:2021-09-06T22:55:10+09:00
Java Silver 3章 演算子と分岐文①
演算子 演算子の優先度 式の中に複数の演算子があった場合に、どの演算子から計算するかの順序づけ 演算子の結合規則 式の中に同じ優先度の演算子が複数ある場合に、左右どちらから計算するか +と-は優先度同じで結合規則は左 int num = 10 - 5 - 3 + 12 = 5 - 3 + 12 = 2 + 12 = 14 演算の例 オペラント:演算の対称となる変数やリテラル リテラル:コード内に書く文字列や数値 0.2F null とか特殊な意味を持たせる事もある System.out.println(10 / 3); System.out.println(10 / 3.0); System.out.println(10 % 3); String str = "Hello"; int a = 10, b = 20; System.out.println(str + a); System.out.println(str + a + b); System.out.println(str + (a + b)); System.out.println(a + b + str); 出力結果 3 //整数同士の演算の実行結果は整数 3.3333333333333335 //小数を含む演算の実行結果は小数 1 //あまりは整数 Hello10 //文字列と数値では結合した文字列になる Hello1020 //文字列と数値を結合した文字列にさらに数値を結合 Hello30 //()内の式は数値のみなので計算後、文字列と結合 30Hello //結合規則が左からなので数値同士の計算後、文字列を結合 変数のデータ型や、リテラルの種類によって結果が変わる 演算の順番も結合規則と優先度に左右されるので注意が必要 単項演算子の"++"と"--" ++(インクリメント)と--(デクリメント) 変数の前に配置すると他の処理より前に 変数の後に配置すると他の処理より後に行われる int a = 10, b = 10, c = 10, d = 10; System.out.println(a++); System.out.println(++b); System.out.println(c--); System.out.println(--d); a = 10; b = 10; c = 10; d = 10; b = ++a; // 前置 System.out.println("a = " + a + " b = " + b); d = c++; // 後置 System.out.println("c = " + c + " d = " + d); 出力結果 10 11 10 9 a = 11 b = 11 bにaを代入する前にaを+1 c = 11 d = 10 dにcを代入した後にcを+1 代入演算子 =は左辺と右辺が等しい事を表しているのではなく 左辺に右辺を代入している += A += B //A = A + B と同じ -= A -= B //A = A - B と同じ *= A *= B //A = A * B と同じ /= A /= B //A = A / B と同じ %= A %= B //A = A % B と同じ 関係演算子 右辺と左辺を比較し条件に一致するかどうかFalse or True を返す int a = 10, b = 20, c = 10; a == b : false a == c : true a != b : true a != c : false a < b : true a <= c : true a > b : false a >= c : true 論理演算子 論理演算子はベン図がわかりやすい ただし上記に加えて条件の評価手順が違うので注意が必要 int a = 10, b = 10, c = 10, d = 10; boolean result1 = a++ > 10 & ++b > 10; //a > 10 を評価 False その後 a + 1する //b + 1 > 10 を評価 True System.out.println("result1:" + result1 + " a:" + a + " b:" + b); boolean result2 = c++ > 10 && ++d > 10; //c > 10 を評価 False その後 c + 1する //d + 1 > 10 の評価は行われない! System.out.println("result2:" + result2 + " c:" + c + " d:" + d); result1:false a:11 b:11 result2:false c:11 d:10 Stringクラス StringBuilderクラス String型 ・データは参照型 ・元の文字列は書き換えられず新しい文字列が作成され、参照先が変わる StringBuilser型 ・データは基本データ型 ・新しい文字列で上書きする ・文字列を操作するメソッドが多数用意されている 関係演算子による基本データ型の比較 int n1 = 10; int n2 = 1_0; long n3 = 10L; byte n4 = 10; char n5 = 'a'; float n6 = 10.0f; double n7 = 10.0; boolean n8 = true; System.out.println("n1 == n2 : " + ( n1 == n2 )); System.out.println("n1 == n3 : " + ( n1 == n3 )); System.out.println("n1 == n4 : " + ( n1 == n4 )); System.out.println("n5 == 'a' : " + ( n5 == 'a' )); System.out.println("n6 == n7 : " + ( n6 == n7 )); System.out.println("n8 == true : " + ( n8 == true )); n1 == n2 : true n1 == n3 : true n1 == n4 : true n5 == 'a' : true n6 == n7 : true n8 == true : true データ型が異なっても、値が同じならTrue Float型 :単精度浮動小数点(32bit) 符号1 指数8 仮数23bit Double型 :倍精度浮動小数点(64bit) 符号1 指数11 仮数52bit Double型の方がより0に近い正負の小数を表現できる事になります。 基本情報であれだけ勉強した浮動小数点数も忘れてきました。 関係演算子による参照型データの比較 配列は参照型データに分類される int[] a1 = {10}; int[] a2 = {10}; //a1とa2は配列の[0]要素に10という数値を持つ配列を参照している //参照する配列の構造、要素は同一だが a1,a2 は異なる配列を参照している System.out.println("a1 == a2 : " + ( a1 == a2 )); int[] a3 = {10}; int[] a4 = a3; //a4はa3が代入されているので、参照しているのはa3が参照する配列と同一となる System.out.println("a3 == a4 : " + ( a3 == a4 )); a1 == a2 : false a3 == a4 : true 非常にややこしいが図だと分かりやすい 文字列の比較 equals()メソッドによる比較 String型(参照型)データ equal()メソッドは参照先が異なっても、同一の文字列であればTrueを返す String s1 = "tanaka"; String s2 = "tanaka"; System.out.println("s1.equals(s2) : " + ( s1.equals(s2) )); String s3 = "TANAKA"; System.out.println("s1.equals(s3) : " + ( s1.equals(s3) )); s1.equals(s2) : true s1.equals(s3) : false 演算子==による比較 String s1 = "Hello"; String s2 = new String("Hello"); String s3 = "Hello"; String s4 = s2.intern(); System.out.println("s1 == s2 : " + ( s1 == s2 )); System.out.println("s1 == s3 : " + ( s1 == s3 )); System.out.println("s1 == s4 : " + ( s1 == s4 )); System.out.println("s2 == s4 : " + ( s2 == s4 )); String型データは参照型であるが、参照先の文字列はStringクラスの管理領域(プール)にある intern()メソッドは文字列プールを検索しs2と等しい文字列があればプール内の文字列を返す こちらもかなりややこしい new でインスタンス化したオブジェクトはインスタンス変数という 宣言した瞬間に使用できるString str = "ABC"; やint [] num = {10,20,30}と参照先が異なる s2はインスタンス変数で普通の変数と参照先が異なると思われる。 s4はs2と同じ文字列をStringプールから検索し参照している String型とStringBuilder型の注意点 新しい文字列の作成の際、Stringプールに新たな文字列が追加され参照先が変わる場合と 既存の文字列が書き換わる場合がある null比較 null:参照型データで何も参照していないことを表すリテラル String str1 = null; String str2 = ""; int[] array1 = null; int[] array2 = new int[1]; System.out.println(str1 == null); System.out.println(str2 == null); System.out.println(array1 != null); System.out.println(array2 != null); true false 空白はデータ領域が確保され参照しているためNot null false 配列やクラスは宣言した段階では領域確保されないためnull true インスタンス化した数値型の配列には初期化の時点で0が入る
- 投稿日:2021-09-06T21:37:05+09:00
転職活動管理アプリを作ろう②(開発環境構築~ログイン画面)
前回は コチラ ツール OS Windows 10 IDE eclipse (Version: 2020-12 (4.18.0)) [新規] > [Spring スターター・プロジェクト] より新規プロジェクトを作成 [ウィンドウ] > [ビューの表示] より「Bootダッシュボード」を開いておく DB MySQL (docker) ココ に docker-compose を置きました localhost:3306 で接続可能 http://localhost:8081/ で phpMyAdmin へ接続 プロジェクト設定 Spring Boot 必要なモジュールは以下の通り spring-boot-starter-data-jpa spring-boot-starter-security spring-boot-starter-thymeleaf spring-boot-starter-web spring-boot-starter-web-services spring-session-core thymeleaf-extras-springsecurity5 spring-boot-devtools mysql-connector-java spring-boot-starter-test spring-security-test spring-boot-starter-data-jdbc spring-boot-starter-jdbc application.properties DB 接続に必要な設定は以下の通り spring.datasource.url=jdbc:mysql://localhost:3306/sample spring.datasource.username=test spring.datasource.password=tset spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # spring.sql.init.mode=always # spring.sql.init.schema-locations=classpath:database/schema.sql # spring.sql.init.data-locations=classpath:database/data.sql spring.sql.init.encoding=utf-8 ログイン画面表示 $ docker-compose up -d で MySQL コンテナ(および phpMyAdmin コンテナ)を起動する 「Bootダッシュボード」より対象のプロジェクトを右クリック > [(再)起動] を選択 http://localhost:8080/ にアクセスするとログイン画面が表示される 次回に向けて docker(≒ dockerhub)を使うことで MySQL 環境構築がすぐ出来た Spring Boot が Tomcat を内包してくれているので、eclipse にプラグインを入れずともサーバー起動可能なことに感動した Linux 環境へのデプロイ方法や環境構築については後々調査する spring-boot-starter-security モジュールを入れることでログイン画面が即表示できた DB のスキーマ定義、実際のログイン処理については後々調査する
- 投稿日:2021-09-06T21:35:56+09:00
転職活動管理アプリを作ろう①(導入)
目的 転職活動のステータス管理を Excel でやっているのですが、Mac と Windows それぞれでファイルを持ってしまっているため管理が煩雑になりました。 マルチデバイスで管理し、かつ個人情報を自分がセキュリティレベルをコントロールできるところに配置したいと思い立ち、新規に(簡単に)作成することにしました。 (「Notion とか使えば?」という声は聞こえません) 欲しい機能 ログイン 企業の応募ステータス管理 Markdown によるメモ機能 ノウハウを貯めておく Wiki (できれば)CSV 出力 (できれば)CSV 取込 サイト要件 動作環境 Linux Amazon Linux か Heroku か別のホスティングかは未定 Chrome 最新版 その他のブラウザは知らない 技術要件 言語 / フレームワーク Java 11 Spring Boot 2.4 DB MySQL サーバ Tomcat、Apache バージョン管理 Git コンテナ docker k8s は要検討 上記内容で進めていこうと思います。
- 投稿日:2021-09-06T20:01:07+09:00
Java Tips
Java Tips Objectをjsonに変換 Gsonを使う。 https://github.com/google/gson dependencies { implementation 'com.google.code.gson:gson:2.8.7' } SampleModel results = SampleModel.findAll(); Gson gson = new Gson(); System.out.println(gson.toJson(results)); // 出力結果 // [{"id":1,"name":"Sample001"}, {"id":2,"name":"Sample002"}, {"id":3,"name":"Sample003"}] StreamAPIのmap PHPでいうarray_map、rubyでいうmap Java Stream APIをいまさら入門 /* * 以下のような値を持つModel * [{"id":1,"name":"Sample001"}, {"id":2,"name":"Sample002"}, {"id":3,"name":"Sample003"}] */ SampleModel model = SampleModel.findAll(); /* * map処理 * SampleModelに@Getterが付与されている前提 */ List results = model.stream() .map(elem -> elem.getName()) .collect(Collectors.toList()) // 出力結果:["Sample001", "Sample002", "Sample003"] System.out.println(results); @TestでprivateメソッドのExceptionが発生するかをテストする方法 [JAVA] JPAで1対Nで中間テーブルのあるDBをModelに落とし込む JPAのNo default constructor for entityエラーについて
- 投稿日:2021-09-06T15:17:56+09:00
Couchbase Server Java SDK解説: フィールドレベルの暗号化
Couchbase Server Java SDKを使用して、JSONドキュメントの特定のフィールドを暗号化および復号化することができます。 CouchbaseのJava SDK暗号化ライブラリは、独自の暗号化コンポーネントを実装するためのフレームワークを提供します。 ライブラリ フィールドレベルの暗号化機能は、エンタープライズサブスクリプションライセンス契約により、提供されるオプションのライブラリとして提供されています。 暗号化ライブラリを使用するには、プロジェクト構成ファイルに明示的に含める必要があります。 Mavenのdependency(依存関係)セクションを例示します。 <dependency> <groupId>com.couchbase.client</groupId> <artifactId>couchbase-encryption</artifactId> <version>${version}</version> </dependency> 使用法 構成 フィールドレベルの暗号化を有効にするには、ClusterEnvironmentにCryptoManagerを指定します。 KeyStore javaKeyStore = KeyStore.getInstance("MyKeyStoreType"); FileInputStream fis = new java.io.FileInputStream("keyStoreName"); char[] password = { 'a', 'b', 'c' }; javaKeyStore.load(fis, password); Keyring keyring = new KeyStoreKeyring(javaKeyStore, keyName -> "swordfish"); // AES-256 authenticated with HMAC SHA-512. Requires a 64-byte key. AeadAes256CbcHmacSha512Provider provider = AeadAes256CbcHmacSha512Provider.builder().keyring(keyring).build(); CryptoManager cryptoManager = DefaultCryptoManager.builder().decrypter(provider.decrypter()) .defaultEncrypter(provider.encrypterForKey("myKey")).build(); ClusterEnvironment env = ClusterEnvironment.builder().cryptoManager(cryptoManager).build(); Cluster cluster = Cluster.connect("localhost", ClusterOptions.clusterOptions("username", "password").environment(env)); データバインディングの例 データクラスの暗号化するフィールドに、@Encryptedアノーテーションを付けます。 public class Employee { @Encrypted private boolean replicant; // alternatively you could annotate the getter or setter public boolean isReplicant() { return replicant; } public void setReplicant(boolean replicant) { this.replicant = replicant; } } Employeeレコードを作成してCouchbaseに保存してみます。 Employee employee = new Employee(); employee.setReplicant(true); collection.upsert("employee:1234", employee); // encrypts the "replicant" field JsonObjectのフィールドが暗号化されていることを確認するために、ドキュメントとして取得します。 JsonObject encrypted = collection.get("employee:1234").contentAsObject(); // does not decrypt anything System.out.println(encrypted); contentAsObject()メソッドでは、何も復号化しないため、出力は次のようになります。 { "encrypted$replicant": { "alg": "AEAD_AES_256_CBC_HMAC_SHA512", "ciphertext": "xwcxyUyZ.....", "kid": "myKey" } } 次に、データバインディングを使用してデータを読み取ります。 Employee readItBack = collection.get("employee:1234").contentAs(Employee.class); // decrypts the "replicant" field System.out.println(readItBack.isReplicant()); 最後の行ではtrueが出力されます。 操作モード 2つの操作モードが利用可能です: Jacksonデータバインディング中の透過的な暗号化/復号化 JsonObjectCryptoを使用した手動フィールド編集 カスタムObjectMapperの使用 データバインディング中に暗号化/復号化を有効にするコードは、EncryptionModuleというJacksonモジュールとしてパッケージ化されています。 ドキュメントをシリアル化するときに独自にカスタマイズしたObjectMapperを提供する場合は、ObjectMapperに、カスタマイズを行ったCryptoManagerを用いて初期化したEncryptionModuleクラスをObjectMapperに登録します。 フィールドレベルの暗号化をサポートする独自の(ObjectMapperに基づく)カスタムJSONシリアライザーを使用するようにクラスター環境を構成する方法を紹介sます。 // CryptoManager cryptoManager = createMyCryptoManager(); KeyStore javaKeyStore = KeyStore.getInstance("MyKeyStoreType"); FileInputStream fis = new java.io.FileInputStream("keyStoreName"); char[] ksPassword = { 'a', 'b', 'c' }; javaKeyStore.load(fis, ksPassword); Keyring keyring = new KeyStoreKeyring(javaKeyStore, keyName -> "swordfish"); // AES-256 authenticated with HMAC SHA-512. Requires a 64-byte key. AeadAes256CbcHmacSha512Provider provider = AeadAes256CbcHmacSha512Provider.builder().keyring(keyring).build(); CryptoManager cryptoManager = DefaultCryptoManager.builder().decrypter(provider.decrypter()) .defaultEncrypter(provider.encrypterForKey("myKey")).build(); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JsonValueModule()); // for JsonObject mapper.registerModule(new EncryptionModule(cryptoManager)); // Here you can register more modules, add mixins, enable features, etc. ClusterEnvironment env = ClusterEnvironment.builder().cryptoManager(cryptoManager) .jsonSerializer(JacksonJsonSerializer.create(mapper)).build(); Cluster cluster = Cluster.connect(connectionString, ClusterOptions.clusterOptions(username, password).environment(env)); JsonObjectCrypto 復号化するフィールドをさらに制御する必要がある場合、またはCouchbaseのJsonObjectツリーモデルを使用することを望む場合、JsonObjectCryptoインスタンスを使用して、JsonObjectの暗号化されたフィールド値を読み書きできます。 JsonObject document = JsonObject.create(); JsonObjectCrypto crypto = document.crypto(collection); crypto.put("locationOfBuriedTreasure", "Between palm trees"); // This displays the encrypted form of the field System.out.println(document); collection.upsert("treasureMap", document); JsonObject readItBack = collection.get("treasureMap").contentAsObject(); JsonObjectCrypto readItBackCrypto = crypto.withObject(readItBack); System.out.println(readItBackCrypto.getString("locationOfBuriedTreasure")); 暗号化キーの作成 このライブラリに含まれているAEAD_AES_256_CBC_HMAC_SHA512アルゴリズムは、64バイト長の暗号化キーを使用します。 以下は、暗号化キーを含むJavaキーストアファイルを作成する方法を示す例です。 KeyStore keyStore = KeyStore.getInstance("JCEKS"); keyStore.load(null); // initialize new empty key store // Generate 64 random bytes SecureRandom random = new SecureRandom(); byte[] keyBytes = new byte[64]; random.nextBytes(keyBytes); // Add a new key called "my-key" to the key store KeyStoreKeyring.setSecretKey(keyStore, "my-key", keyBytes, "protection-password".toCharArray()); // Write the key store to disk try (OutputStream os = new FileOutputStream("MyKeystoreFile.jceks")) { keyStore.store(os, "integrity-password".toCharArray()); } 上記で作成したファイル(MyKeystoreFile.jceks)を使用して、フィールドレベル暗号化で使用するためのキーストアを作成する方法は次のとおりです。 KeyStore keyStore = KeyStore.getInstance("JCEKS"); try (InputStream is = new FileInputStream("MyKeystoreFile.jceks")) { keyStore.load(is, "integrity-password".toCharArray()); } KeyStoreKeyring keyring = new KeyStoreKeyring(keyStore, keyName -> "protection-password"); 参考情報 Field Level Encryption from the Java SDK Field Level Encryption
- 投稿日:2021-09-06T11:19:35+09:00
[paiza]スキルチェック見本問題 掛け算/足し算(paizaランク D 相当)
初めに ここまでのJavaの学習でpaizaラーニングにある スキルチェック見本問題の掛け算、足し算が解けるようになりました。 掛け算 (paizaランク D 相当) 見本問題なので問題の公開、コードの公開は問題ないそうです。 解答コード import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int num1 = sc.nextInt(); int num2 = sc.nextInt(); System.out.println(num1*num2); } } 足し算 (paizaランク D 相当) import java.util.*; public class Main { public static void main(String[] args) { // 自分の得意な言語で // Let's チャレンジ!! Scanner sc = new Scanner(System.in); int num1 = sc.nextInt(); int num2 = sc.nextInt(); System.out.println(num1+num2); } } おわり 随時勉強を進めていき、スキルチェックのランクを上げていきたいです。
- 投稿日:2021-09-06T11:00:35+09:00
[Java基礎⑤] forで繰り返し処理
初めに 今回はforでのループ処理の基本と、 標準入力からデータを読み込む方法を学びました。 最後に標準入力とループ処理を行います。 forでのループ処理の基本形 public class Main { public static void main(String[] args) { for(int i = 0; i<=4; i++){ System.out.println("hello world"); } } } 実行すると hello worldが4回出力されます。 HTMLを作成する public class Main { public static void main(String[] args) { System.out.println("<ul>"); for(int i = 1; i <= 100; i++) { System.out.println("<li>" + i + "</li>"); } System.out.println("</ul>"); } } HTMLを使う場合は、System.out.println("<li>" + i + "</li>");というふうに書くんですね 標準入力からデータを読み込む 文字列の読み込み import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String line = sc.next(); System.out.println(line); } } 数値の読み込み import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int line = sc.nextInt(); System.out.println(line); } } 「sc.nextInt();」が忘れがちでした。 標準入力×ループ処理 複数回出力したい場合には、nextメソッドを複数回実行すれば良いそうです。 // 標準入力とループ処理 import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int count = sc.nextInt(); for(int i=1; i<=count; i++){ System.out.println("スライムがあらわれた"); } } } 標準入力が3なら、スライムがあらわれた が3回出力されます。 import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int count = sc.nextInt(); String line; for(int i = 0; i < count; i++) { line = sc.next(); System.out.println(line); } } } 標準入力で 3 りんご メロン みかん と入力されれば、 りんご メロン みかん が出力されます。 終わり 複数データを読み込み、forで処理するのがまだ難しいです。
- 投稿日:2021-09-06T09:46:29+09:00
java 標準入力 (記録)
N行のデータの入力 public static void main(String[] args){ Scanner sc = new Scanner(System.in); String[]input_line = new String[sc.nextInt()]; sc.nextLine(); for(int i=0;i<input_line.length;i++){ input_line[i] = sc.nextLine(); System.out.println(input_line[i]); } } 入力例1 3 aaaaa bbbbbb cccc 出力例1 aaaaa bbbbbb cccc 3つのデータの入力 public static void main(String[] args){ Scanner sc = new Scanner(System.in); String a = sc.next(); String b = sc.next(); String c = sc.next(); System.out.println(a); System.out.println(b); System.out.println(c); } scにまず新しく入力されたものを入れるよと、new Scanner(System.in)と書く。 次に、sc.next()でスキャン文字を入れていく。nextの回数分scに入れる。 N個のデータの入力 (空白除去) public static void main(String[] args){ Scanner sc = new Scanner(System.in); String N = sc.nextLine(); int n = Integer.parseInt(N); // String[] str = sc.nextLine().split(","); String[] str = sc.nextLine().split("[ ]"); for(int i =0; i <n;i++){ System.out.println(str[i]); } } .split("[ ]")で空白行を除去して出力したりできます。 入力例1 3 aaaaa bbbbbb cccc 出力例1 aaaaa bbbbbb cccc カンマ区切りの3つのデータの入力 public static void main(String[] args){ Scanner sc = new Scanner(System.in); String[] str = sc.nextLine().split(","); System.out.println(str[0]); System.out.println(str[1]); System.out.println(str[2]); } } 入力例1 aaaaa,bbbbbb,cccc 出力例1 aaaaa bbbbbb cccc カンマ区切りのN個のデータの入力 public static void main(String[] args){ Scanner sc = new Scanner(System.in); String N = sc.nextLine(); int n = Integer.parseInt(N); String[] str = sc.nextLine().split(","); for(int i =0; i <n;i++){ System.out.println(str[i]); } } 入力例1 3 aaaaa,bbbbbb,cccc 出力例1 aaaaa bbbbbb cccc