Javaの小ネタ、Tips
概要
徒然なるままに書き綴ってみるだけです。役に立つかどうかは知りません。また、必ずしもJava固有の話ではないと思います。
内容
多重代入
複数の変数に同じ値を代入することができます。
int x, y;
x = y = 10;
System.out.println(x); // 10
System.out.println(y); // 10
これは、下記のように解釈されるっぽいです。yに10が代入されますが、Javaでは代入式も値が返りますから、 (y = 10)
全体の評価値がxに代入されるということですね。
x = (y = 10);
mainメソッドの書き方
mainメソッドは一般的には下記のように書くと思います。
public static void main(String[] args) {
System.out.println("Hello world!");
}
Java5以降なら下記のように書いてもOKです。
public static void main(String... args) {
System.out.println("Hello world!");
}
String[]
か String...
の違いだけです。前者は配列で後者は可変長引数ですが、mainメソッドはどちらでもいいようです。
ただのスコープ
if文やfor文などを使うと新しいスコープが作られますが、条件分岐やループなどをしない単なるスコープを作ることもできます。
{
int x = 10;
System.out.println(x); // 10
}
{
int x = 100;
System.out.println(x); // 100
}
// System.out.println(x); // コンパイルエラー
x
が2回定義されていますが、スコープが別なのでコンパイルエラーにはなりません。また、x
のスコープはブレースで囲った範囲だけなので、ブレースの外で x
を参照しようとするとコンパイルエラーです。
HashSetの実装
HashSetは、実装としてはただHashMapをラップしているだけのクラスです。
(※実装の詳細の話なので、将来変更される可能性はあります)
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
AbstractStringBuilder
StringBuilder
や StringBuffer
はJavaDocではObjectクラス直下のサブクラスであるかのように書かれていますが、実際には AbstractStringBuilder
のサブクラスです。
AbstractStringBuilder
はパッケージプライベート(公開APIではない)のでJavaDocには書かれてないのかもしれません。
(※実装の詳細の話なので、将来変更される可能性はあります)
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
{
// 後略
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
{
// 後略
メソッド内でメソッドを定義する
通常はJavaではメソッド内にメソッドを定義することはできません。しかし、Java10で導入された var
を使えばそれっぽいことができます。(別の記事に書いたことがありますが)
public class Main {
public static void main(String[] args) {
// func.capitalize() で呼び出せる
// func はローカル変数なので、このメソッドの外からは呼べない
var func = new Object() {
private String capitalize(String s) {
return s.substring(0, 1).toUpperCase() + s.substring(1, s.length()).toLowerCase();
}
};
System.out.println(func.capitalize("tokyo")); // => Tokyo
System.out.println(func.capitalize("TOKYO")); // => Tokyo
}
}
Javaのソースコードをコンパイルなしで実行する
これも別の記事に書きましたが、Java11以降は javac
を使わず java
コマンドでソースファイルを指定して実行させることができます。ちょっとした動作確認のために便利かもしれません。
まあ、本当にコンパイルなしで実行するわけではなくて裏でコンパイルしているのだろうと思いますが。
既存クラスのメソッドに処理を埋め込む
Javaでは匿名クラスを使って既存のメソッドに処理を埋め込むことができます。
List<String> list = new ArrayList<>() {
@Override
public boolean add(String s) {
System.out.println("add called. arg: " + s);
return super.add(s);
}
};
list.add("hello"); // add called. arg: hello
list.add("world"); // add called. arg: world
System.out.println(list); // [hello, world]
null
に対して instanceof
を使う
null
に対して instanceof
を使うことができます。
System.out.println(null instanceof Object); // false
true
にならないのは当然ですが、 NullPointerException
が投げられないというのが注目ポイントかと思います。 null
が代入されている変数でも同じ結果になりますので、 instanceof
の前に null
チェックをしなくて済みます。
null
を throw
する
例外型の変数に null
が入っていた場合、 throw
すると変数の型に関係なく NullPointerException
が投げられます。
RuntimeException e = null;
throw e; // NullPointerException
null
をキャストする
あまり意味がないですが、とりあえず何の例外も投げられません。
Object obj = null;
String str = (String)obj;
System.out.println(str); // null
サブクラスを許容しない型判定
instanceof
を使うと、インスタンスの型が指定したクラスのサブクラスの場合も true
となります。
System.out.println("str" instanceof Object); // true
サブクラスの場合は false
にしたいなら下記のように Class
型同士を equals
で比較するといいでしょう。
System.out.println(new Object().getClass().equals(Object.class)); // true
System.out.println("str".getClass().equals(Object.class)); // false
配列は型安全ではない
配列は、ある型の配列と、その型のサブクラスの配列に代入互換性があります。
そのため、下記のようなコードがコンパイルされてしまい、実行時にエラーとなります。
Object[] array = new String[3];
array[0] = new Integer(10); // ArrayStoreException
ジェネリクスを使ったListであれば、コンパイルエラーになるため上記のような問題は発生しません。
List<Object> list = new ArrayList<String>(); // incompatible types: ArrayList<String> cannot be converted to List<Object>
オーバーフローを検知する
演算時にオーバーフローが発生すると、何のエラーも出ずにただ不正な計算結果になります。
Math
クラスのメソッドで、オーバーフローが発生した際に例外を投げるユーティリティーメソッドがあるため、その例外を捕捉することでオーバーフローを検知できます。
System.out.println(Integer.MAX_VALUE + 1); // -2147483648
Math.addExact(Integer.MAX_VALUE, 1); // ArithmeticException: integer overflow
まあ、最初から BigInteger
を使えばいいような気もしますけれど。
終わりに
何か一つでも参考になる項目があれば幸いです。
他に何か思いついたら追記するかもしれませんし、しないかもしれません。
Author And Source
この問題について(Javaの小ネタ、Tips), 我々は、より多くの情報をここで見つけました https://qiita.com/dhirabayashi/items/16e9fe4f5418c6bba0df著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .