Javaの自動梱包と解体を理解するために
4244 ワード
Javaでの自動梱包と解体
箱詰め(Boxing)は、パッケージ(Wrapper)とも呼ばれ、オブジェクトにプリミティブタイプ(primitive type)を配置するプロセスであり、プリミティブ(primitive)が参照オブジェクトとして使用できるようにする.
ここの
通常、これらのクラスは包装器(wrapper)と呼ばれる.これらのオブジェクトパッケージクラスには、Integer、Long、Float、Double、Short、Byte、Character、Void、Boolean(上位6クラスは共通のスーパークラスNumberから派生)という明らかな名前があります.
オブジェクトパッケージクラスは可変ではありません.すなわち、パッケージが構築されると、パッケージの値を変更することはできません.また、オブジェクトパッケージクラスはfinalなので、サブクラスを定義することはできません.
一般的な例を見てみましょう.例えば、intタイプのArrayListを作成し(ArrayListの汎用型は基本タイプが許されないため、ここではそれらのパッケージクラスしか使用できません)、ArrayListに要素を追加し、そこから要素を取得します.一般的には次のように書かれています.
ここではそれぞれ自動梱包と自動解体がトリガーされ、ここでadd操作は
自動梱包と自動解体がどのように実現されているかをバイトコードで表示
私たちはよく自動梱包、自動解体と言っていますが、いったいどのような自動法なのか、javaコードで生成されたバイトコードを見て、コンパイラが私たちのコードに何をしたのかを見てみましょう.
バイトコードの表示方法
ここでは、2つのバイトコードを表示する方法について説明します.1つ目は、javacとjavapで表示します.まずjavacで.javaコードを.classバイトコードにコンパイルし、javapでバイトコードを分析します.
これでバイトコードの情報が表示されます.
2つ目は、IDEプラグインASM Bytecode Outlineで確認します.具体的な操作方法はプラグインの説明を参照してください.
自動梱包と解体のバイトコードの表示
このjavaコードのバイトコードを生成します.コア部分は次のとおりです.
L 1部の最後から2行目、
次に、自動梱包対応バイトコード、すなわちL 2部分を見て、まず
ここを見て、
自動梱包と解体のトリガタイミング
次に、自動梱包と解体のトリガタイミングについて説明します.具体的には、次のとおりです.
基本タイプの自動梱包と取り外し方法のまとめ
基本タイプ
梱包タイプ
梱包方法
箱の取り外し方法
int
Integer
Integer#valueOf()
Integer#intValue()
long
Long
Long.valueOf()
Long.longValue()
byte
Byte
Byte.valueOf()
Byte.byteValue()
short
Short
Short.valueOf()
Short.shortValue()
float
Float
Float.valueOf()
Float.floatValue()
double
Double
Double.valueOf()
Double.doubleValue()
char
Character
Character.valueOf()
Character.charValue()
boolean
Boolean
Boolean.valueOf()
Boolean.booleanValue()
興味のある学生は自分でいろいろな操作を試して、自動的に箱詰めと箱を分解する表現をして、対応するバイトコードを見ることができます.
リファレンス
Wikiedia:Object type(object-oriented programming)5分徹底理解-Java自動梱包・解体
箱詰め(Boxing)は、パッケージ(Wrapper)とも呼ばれ、オブジェクトにプリミティブタイプ(primitive type)を配置するプロセスであり、プリミティブ(primitive)が参照オブジェクトとして使用できるようにする.
ここの
primitive type
はJavaの基本タイプで、すべての基本タイプに対応するクラスがあります.例えば、Integerクラスは基本タイプintに対応する.通常、これらのクラスは包装器(wrapper)と呼ばれる.これらのオブジェクトパッケージクラスには、Integer、Long、Float、Double、Short、Byte、Character、Void、Boolean(上位6クラスは共通のスーパークラスNumberから派生)という明らかな名前があります.
オブジェクトパッケージクラスは可変ではありません.すなわち、パッケージが構築されると、パッケージの値を変更することはできません.また、オブジェクトパッケージクラスはfinalなので、サブクラスを定義することはできません.
とは、タイプ変換(暗黙的または明示的)によって値タイプから参照タイプを取得することを意味し、この作業は
によって行われます.一般的な例を見てみましょう.例えば、intタイプのArrayListを作成し(ArrayListの汎用型は基本タイプが許されないため、ここではそれらのパッケージクラスしか使用できません)、ArrayListに要素を追加し、そこから要素を取得します.一般的には次のように書かれています.
// int
ArrayList integerArrayList = new ArrayList<>();
integerArrayList.add(1);
int i = integerArrayList.get(0);
ここではそれぞれ自動梱包と自動解体がトリガーされ、ここでadd操作は
操作をトリガーし、intをIntegerに変換した.次にArrayListから要素を取得し、我々の目標変数タイプは基本タイプintであるが、取得した要素タイプはIntegerであるため、
はここで
の操作を手伝ってくれた.自動梱包と自動解体がどのように実現されているかをバイトコードで表示
私たちはよく自動梱包、自動解体と言っていますが、いったいどのような自動法なのか、javaコードで生成されたバイトコードを見て、コンパイラが私たちのコードに何をしたのかを見てみましょう.
バイトコードの表示方法
ここでは、2つのバイトコードを表示する方法について説明します.1つ目は、javacとjavapで表示します.まずjavacで.javaコードを.classバイトコードにコンパイルし、javapでバイトコードを分析します.
(base) tinytongtongdeMacBook-Pro% javac TestAutoWrapper.java
(base) tinytongtongdeMacBook-Pro% javap -verbose TestAutoWrapper
これでバイトコードの情報が表示されます.
2つ目は、IDEプラグインASM Bytecode Outlineで確認します.具体的な操作方法はプラグインの説明を参照してください.
自動梱包と解体のバイトコードの表示
public static void main(String[] args) {
// int
ArrayList integerArrayList = new ArrayList<>();
integerArrayList.add(1);//
int i = integerArrayList.get(0);//
}
このjavaコードのバイトコードを生成します.コア部分は次のとおりです.
// access flags 0x9
public static main([Ljava/lang/String;)V
...
L1
LINENUMBER 15 L1
ALOAD 1
ICONST_1
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z
POP
L2
LINENUMBER 16 L2
ALOAD 1
ICONST_0
INVOKEVIRTUAL java/util/ArrayList.get (I)Ljava/lang/Object;
CHECKCAST java/lang/Integer
INVOKEVIRTUAL java/lang/Integer.intValue ()I
ISTORE 2
...
L 1部の最後から2行目、
INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z
INVOKEVIRTUAL
命令は虚メソッド呼び出しを示しています.ここで具体的にはjavaコードのintegerArrayList.add(1);
です.自動梱包はどこで発生しますか.その上に、INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
INVOKESTATIC
は静的メソッド呼び出しを表し、ここで対応するJava文はInteger#valueOf()メソッドである.次に、自動梱包対応バイトコード、すなわちL 2部分を見て、まず
INVOKEVIRTUAL java/util/ArrayList.get (I)Ljava/lang/Object;
を見て、対応するjavaコードはintegerArrayList.get(0)
で、ArrayListからIntegerタイプオブジェクトを取得したことを示します.自動解体は、次のNVOKEVIRTUAL java/lang/Integer.intValue ()I
という命令で発生し、対応するjavaメソッドはInteger#intValue()メソッドです.ここを見て、
と
について具体的な認識があると信じています.つまり、コンパイラは状況に応じて私たちのためにいくつかの仕事をしてくれて、バイトコードの命令を挿入することで、私たちのために箱詰めと箱取りの操作を完了します.int対応の梱包方法はInteger#valueOfであり、解体方法はInteger#intValue()である.自動梱包と解体のトリガタイミング
次に、自動梱包と解体のトリガタイミングについて説明します.具体的には、次のとおりです.
* = ( )
* +,-,*,/ ( )
* >,
基本タイプの自動梱包と取り外し方法のまとめ
基本タイプ
梱包タイプ
梱包方法
箱の取り外し方法
int
Integer
Integer#valueOf()
Integer#intValue()
long
Long
Long.valueOf()
Long.longValue()
byte
Byte
Byte.valueOf()
Byte.byteValue()
short
Short
Short.valueOf()
Short.shortValue()
float
Float
Float.valueOf()
Float.floatValue()
double
Double
Double.valueOf()
Double.doubleValue()
char
Character
Character.valueOf()
Character.charValue()
boolean
Boolean
Boolean.valueOf()
Boolean.booleanValue()
興味のある学生は自分でいろいろな操作を試して、自動的に箱詰めと箱を分解する表現をして、対応するバイトコードを見ることができます.
リファレンス
Wikiedia:Object type(object-oriented programming)5分徹底理解-Java自動梱包・解体