第1章Javaデータ型変換

この章の冒頭で、Java基本モジュールの知識ポイントを分析します。基本的なデータ型、パッケージングクラス、文字列、IO、例外、スレッド、コレクションなどの分析または元のコード分析を含みます。
この記事から始めて、Javaの基本的な知識のポイントを徐々に勉強していきます。また、常に学習しています。記事に間違った説明がある場合は、すべての神がより正確になることを願っています。
JAVA型変換は、コーディングでよく見られるものです。原理を深く理解していないと、いつか大きな穴に陥ってしまうと思います。したがって、この章では、Javaでのさまざまなデータ型の型変換と詳細な分析を紹介します。私があなたを助けることができれば、私はそれが好きになることを願っています。

この章の知識構造図:
ここに画像の説明を挿入

コンセプト紹介

所谓类型转换,即对数据的操作。java的数据类型分为两种;

1.基本的なデータ型

基本的なデータ型は、数値型と非数値型に分けられます。全部で8種類あります。

数値型
byte(1バイト)
short(2バイト)
int(4バイト)
long(8バイト)
float(4バイト)
double(8バイト)

非数値型
char(2バイト)
ブール(わからない)

2.参照データ型

参照データ型とは、ヒープ内のオブジェクトを指す参照変数を指します。これは、参照データ型です。たとえば、Book book = new Book(); bookは参照データ型です。

3.型変換

まず、強制変換のタイプ、いわゆる強制タイプ変換を分析しましょう。強い:必須、強制。
私自身の理解では、大きなスペースバイトは小さなスペースバイトに変換されます。たとえば、バイト変数が宣言されると、1バイトが割り当てられ、int変数には4バイトが割り当てられます。intがバイトに変換される場合、それは強制的な型変換です。同様に、longをintに変換することは、大きなスペースを小さなスペースに変換する動作でもあります。
強制的な型変換は、データオーバーフロー、いわゆるオーバーフローを簡単に引き起こす可能性があります。8つのデータ型を異なるサイズの8つのバケットと比較できます。

大きなバケツが小さなバケツに水を注ぐとき、(写真は少し醜いですが、写真はラフでラフではありません
小型バケットを搭載できるかどうかに関係なく、強制型変換(表示型変換)と呼ばます。
それどころか、小さなバケツからの水は大きなバケツに満たすことができます。暗黙的な型変換として知られています。

型変換の基本的な概念と原理はおそらく上記のとおりです。Javaでの実装の詳細を調べてみましょう。


1.基本的なデータ型

1.整数

	数值型有6种:
	byte (1字节)   		short(2字节)       int(4字节)
	long(8字节)    	float(4字节)       double(8字节)

(1)強制型変換

以下は、元のコード、1の補数、およびメモリの補数の計算に還元されるため、最初にいくつかの基本的な知識ポイントを強調します。

1.メモリ内のデータは補数の形式です
。2。メモリ内のデータは(符号ビット+真の値)で表されます。最上位ビットは符号ビットを表し、0ビットは正、1は負です。
4.正数の元のコード=逆数コード=補数コード。元のコード、逆数コード、および負の数の補数を計算する場合、最上位ビットの符号ビットは計算に含まれません。
3.シフト操作で、右にシフトすると、正の数の上位桁が不十分で0で埋められ、負の数の上位桁が不十分で1で埋められます。左にシフトすると、下位桁が不十分で、すべて0で埋められています

デモンストレーションの例

int i = 200;
byte b = (byte) i;
System.out.println(b);
结果:-56;

この例のプロセスを分析してみましょう。この例は、intからbyteへのキャストです。上記の基本的な知識によれば、int型は4バイトを割り当て、byte型は1バイトを割り当てることがわかっています。では、内部でどのように計算されるのでしょうか。

  • 解決策:
    変数iには4バイト、つまり32ビットが割り当てられます。容量32のバケツと想像できます。

    値200はバイナリ11001000にコンパイルされます。これは、水の量と考えることができます。値は正であるため、最上位ビットは0です。
    この値の元のコードは次のように表されます
    。000000000000 0000 0000 0000 1100 1000(合計32ビット)
    メモリは格納されている補完コードであるため、正の数は計算規則に従って計算されます。コード=逆コード=補数コード;
    値200の補数コードは次のとおりです:
    0000 0000 0000 0000 0000 0000 1100 1000(合計32ビット)
    ので、補数コードを配置する必要があります32スペースで。次に、変数bを分析します。

    変数bには、1バイト、つまり8ビットが割り当てられます。これは、容量が8のバケットに相当します。

    ここで、容量8のバケットを使用して、200の値、つまり、上記の32ビットメモリの補数であるint型の200値を保持する必要があります。
    補数には32ビットがあるためです。長さ、32スペースが必要ですが、バイトは8桁です。グリッドは8桁しか保持できないため、24桁がオーバーフローします。
    オーバーフロールールは高オーバーフローです。下位8ビットのみをインストールできます。
    したがって、実際には、変数bに格納されている値の補数は11001000です。

    補数コードの最上位ビットが1であるため、数値が負であることに注意してください。ただし、特定の値は元のコードに従って判断する必要があります。
    逆コード=補数コード-1から;逆コードを取得できます:
    1 100 0111 ;(引き算を間違えないでください、私はそれを間違って数えました)
    元のコード=逆コードから、元のコードを取得できます
    。1011 1000 ;
    最上位ビットは1で、これは左側の最初のビットでもあり、符号は負です。
    真の値は0111000であり、10進数に変換すると結果は56になります。
    したがって、最終結果は-56になります。

デモンストレーションの例

int = -40000;
short s = (short ) t;
System.out.println(s);
结果:保密;

まず、上記の方法で計算してみましょう。shortのデータ型は2バイト、つまり16ビットです。1つの符号ビットを除いて、残りの15の位置は値を格納できます。したがって、shortの値は、-2の15乗、+ 2の15乗、つまり-32767から32767の範囲になります。
int型の-40000値をshortに格納する場合は、-40000 <-32767です。だからそれは間違いなくオーバーフローします。結果を計算してみましょう。

変数tがint型の場合、32個のスペースが割り当てられ、最上位ビットは負であり、-40000のバイナリ表現は1001 1100 0100 0000です。
したがって、変数tの
元のメモリコードは次のようになります。10000000 0000 0000 1001 1100 0100 0000;
メモリ逆コードは次のとおりです:1 111 1111 1111 1111 0110 0011 1011 1111;
メモリ補数は次のとおりです:1 111 1111 1111 1111 0110 0011 1100 0000;

Shortには16グリッドしかないため、インストールできる補数は0110 0011 1100 0000です。
最上位ビットは0であるため、値は正です。したがって、正の数の補数=元のコードであるため、数値の元のコードは次のようになります
。01100011 1100 0000; 10進数に変換すると25536である
ため、最終結果は正の25536になります。
結論:大きなバケツの実際の水が小さなバケツの容量を超えると、強制的にオーバーフローします。その値が変わります。

では、大きなバケツの水を小さなバケツに入れることができれば、結果はどうなるでしょうか。

デモンストレーションの例

short s= 89;
byte b = (byte) s;
System.out.println(b);
结果:保密;

同様に、上記の計算方法をインストールして、計算してみましょう。
最初に、16個のグリッドがshort型の変数に割り当てられ、最上位ビットがシンボルで埋められ、残りの15ビットが値で埋められます。
89のバイナリビット:1011001
したがって、変数sのメモリ内の補数コードは次のとおりです。000000000101 1001
バイトタイプ変数bには8つのグリッドしかないため、含まれる補数コードは次のとおりです。01011001
観測最上位ビットは次のとおりです。補数コードを介して0。その値は正です。正の数の補数=元のコード。したがって、元のコードも0101 1001であり、10進数に変換すると89になります。
結論:大きなバケツの実際の水が小さなバケツの容量を超えない場合、その値は変わりません。

(2)暗黙的な型変換

原理は強制型変換と同じですが、大きなバケツを小さなバケツに入れるのと、小さなバケツを大きなバケツに入れるのが違います。大きなバケツは確実に収まります。大きなバケツに穴がない限り。
したがって、どのバケットに注がれても、その値は変わりません。同じです。計算方法は上記と同じです。
もう一度デモンストレーションしましょう:

デモンストレーションの例

byte b= -89;
short s = b;
System.out.println(s);
结果:保密;

まず、-89の元のコードは:1101 1001、
その逆コードは:1010 0110、
つまりbの補数は1010 0111です。ここで、-89を変数sにロードする必要があります。
短いタイプの変数sは16です。グリッド、変数bの値をsにロードした後
、元のコードは1 000 0000 1101 1001であり
、その補数は1 111 1111 11100111です。
ここでも考えましたが、変数bの補集合を変数sのグリッドに直接ロードして、
0 000 0000 10100111にしないのはなぜですか。代わりに、
1 000 0000 0010 0111になります。符号ビットがシフトするのはなぜですか?
私も困惑しています。しかし、シフト操作によって、その補数が正確に何であるかを確認できます。
0 000 0000 1010 0111の場合、最上位ビットは0であり、この値は正である必要が
あり、真の値の補数は10100111になります。ですから、私が知らない根本的な原則がいくつかあるに違いありません。しかし確かなことは、暗黙の型変換の値は絶対に変わらないということです。

(3)混合演算での型変換

デモンストレーションの例

short s = 1;
int  i =130;
byte g = (byte )(s+i);
System.out.println(g);
结果:-125

ここで、Javaのデフォルトのデータ型はintであることに注意してください。他の型を使用して受け取る場合は、型変換を実行する必要がありますが、一部は暗黙的な型変換であり、表示されません。
例:long n = 130;実際にはlongn =(long)130;と同等です。
ここで130はint型です。
したがって、上記の例を分析してみましょう。最初の2つの文は定義であり、焦点は最後の文にあります。

byte  g = (byte )(s+i);

ここで、sは短く、iはintであり、javaのデフォルトのデータ型はintであるため、s + iはデフォルトでintに変換されます。
したがって、s + iの後の値はint型の131です。両側の数値型が一致しない場合、コンパイラはエラーを報告します。
あなたはこの質問をするかもしれません:

byte g = (byte)s+(byte)i;

このように書くことは可能ですか?その値は、
書き込み後にデフォルトでint型131に変換されます。したがって、次のようにのみ書き込むことができます。

byte g = (byte )(s+i);

まず、s + iはint型131になり、次に強制的にintからbyteに変換されます。
デモンストレーションの例

byte b = 1;
b = b +1;
System.out.println(b);
结果:报错,b+1后变为int类型,不能直接转为byte。

byte b = 1;
b += 1;
System.out.println(b);
结果:2      += 除了可以实现增加,还会执行强转。因此已经由int转为了byte。

デモンストレーションの例

	short s = 1;
    int i =2147483647;
    long t = s+i;
    System.out.println(t);
    结果:-2147483648,那为什么不是2147483648?

intの数値型は-2 ^ 31から2 ^ 31、つまり-2147483648から2147483647です。結果がここにあるのはなぜですか-2147483648。それを推測しましょう。
控除の始めに、私は質問をしなければなりません、次の2つのint型の元のコード値は2つの10進数を表しています。

1000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000 

正の0と負の0のように見えますか?実際にはそう
はありません。その中で、
1000 0000 0000 0000 0000 0000 0000 0000は、負の範囲の最小値である-2147483648を表します。
0000 0000 0000 0000 0000 0000 0000 0000は、正の数の範囲の最小値、つまり0を表します。
私たちは推測することができます:

2147483648的二进制原码:1000 0000 0000 0000 0000 0000 0000 0000
正数的原码= 反码  1000 0000 0000 0000 0000 0000 0000 0000,在int类中,这个补码表示一个负数,
所以其值为-2147483648。
这也是为什么计算机发展过程中,为什么引入了补码的原因,
就是为了解决正0 和负0 的表达。所以规定了  补码=原码取反+1  的公式,只有这样才能表达出所有数字。

上記の例に戻ると、int i = 2147483647;
元のコード=補数コード= 0111 1111 1111 1111 1111 1111 11111111
この補数コード+1 = 1000 0000 0000 0000 0000 0000 0000 0000
上下、つまり2147483647 + (-2147483648)= -1、補数コード:
1111 1111 1111 1111 1111 1111 1111 1111
-1 + 1、1 0000 0000 0000 0000 0000 0000 0000 0000になりますが、intは32ビットしか保持できないため、上位ビットがオーバーフローし、残りの補数コードは
00000000 0000 0000 0000 0000 00000000
は10進数で0です。

2.浮動小数点

float(単精度)とdouble(倍精度)の2つの浮動小数点型があります。浮動小数点はコンピューターで科学的記数法を使用します。無限小数の場合、位置が長いほど精度が高くなります。ただし、言語が異なれば、使用範囲とコンピューターのコストに基づいて設定も異なります。Javaの
Float4バイト、合計32ビットのメモリスペースを占有します。
doubleは8バイト、合計64ビットのメモリスペースを占有します。
Javaの小数はデフォルトでdouble型になっています。floatに変換する必要がある場合は、強制型変換と呼ばれます。その後にfを追加するか、前にfloatを追加する必要があります。

float h = 1.0;     //结果 编译错误
float f = 1.0f;    // 结果  1.0
double d = 1.0;    //结果 1.0

(1)浮動小数点間の型変換

浮動小数点には小数点があり、異なる小数点の小数点の位置は、固定の32ビットまたは64ビット空間で異なります。数学の4つの規則に従って、数値を追加または削減する前に小数点を揃える必要があります。したがって、小数を揃えるために、異なる小数の間で加算と減算を行うと、必然的に小数が左または右に移動します。移動するとデータがオーバーフローし、結果が自然に変化します。これは、精度。これが、浮動小数点型が小数間の計算に使用されない理由です。
例:1.2 + 1.112 =?;通常の数学演算は2.312に等しいはずですが、コンピューターでは、結果は次のようになります。

结果: 2.3120000000000003

doubleは倍精度型であり、floatは単精度型であるため、doubleをfloatに変換すると、精度の高い10進数の場合、必然的に精度が失われます。これは、強制型変換です。暗黙の型変換です。その変更の詳細はここでは検討されません。

3.整数と浮動小数点の間の型変換

デモンストレーションの例

int  t = 1.234;
system.out.print(t)
// 结果: 1

.1.234はdouble型です。整数型に変換された後は、元の値の整数部分のみを保持できます。

デモンストレーションの例

double  d = 1;
system.out.print(d);
// 结果: 1.0

整数は浮動小数点に変換された後、浮動小数点になり、その後に10進数が続きます。

デモンストレーションの例

当整型 与 浮点型进行加减运算时的类型变化;
float a = 1 + 1.2f;    // 结果: 2.2  
double b = 1 + 1.2;    // 结果: 2.2
int t= (int)(1+1.2f)    

2、非数値

1.文字タイプ

文字タイプは基本データ型charを指します。charはユニコードでエンコードされているため、ユニコードは非常に厚い辞書として理解できます。

历史:
	计算机发明之初,美国人的只需要128个字符,即ASCII码,ASCII码是一本很薄很基础字典,
美国人用它就可以表示它的所有需求。后来随着计算机的普及,有些国家所需要表达的字符个数远远超过了128个,并且
不同国家有不同国家的字符。于是美国人又在ASCII码的基础上开始扩展,将所有国家的所有符号用全部统一起来做成了
一本厚字典。也就是Unicode码,它是采用16进制表示。那Unicode 和 UTF-8、UTF-16、UTF-32有什么关系呢?
	上述三种UTF-8、UTF-16、UTF-32是实现Unicode 转换为二进制所采用的的方式,因为现在使用了Unicode这个
字典,如果采用定长字节来表示,最多需要使用4个字节来表示,然后美国人或者有些国家用不着那么长的空间,
一个英文文本明明只需要1kB,结果现在变成了4kB。造成了极大的空间浪费。于是UTF-8就是不定长的编码方式,只需要
一个字节表示的字符,就只开辟一个字节空间,如果需要两个字节,则开辟两个字节空间。所以优秀的 UTF-8 的编码
方式被广泛应用于计算机领域。

Charは2バイトを占有し、65535文字を格納できます。この制限を超えると、オーバーフローが発生します。例えば

int a = 65 + 0;
char c = (char) a;
System.out.println( c );
结果:A

UnicodeはASCIIコードに基づいて拡張されているため、最初の128ビットはASCIIコードと同じです。ここでは、便宜上、128ビットより前のデータを例として使用します。したがって、
値65の元のコードは0000 0000 0000 0000 0000 0000 0100 0001であり、補数もこのコードであると計算できます
。charは16バイナリを保持できるため、charメモリ内の補数は実際には0000 0000 01000001です。 、コードはASCIIに対して解析され、文字はAです。

如果
int a = 65 + 65534;
char c = (char) a;
System.out.println( c );
结果: ?

結果はどのくらいになるはずですか?計算してみましょう。
Intタイプa = 65599、元のコード=補完コード= 0000 0000 0000 0001 0000 0000 0011 1111;
charは2バイトを占有し、補完コードの下位16ビットを取得するため、そのメモリの実際の補完コードは
0000 00000011
です。1111のは正であるため、元のコードも0000 0000 00111111です。これはASCIIコード比較による文字ですか?

如果
int b = '中';
System.out.println(b);
结果:20013   

例として漢字「中」を示します。charは2バイト、intは4バイトであるため、このコードは実際には暗黙的な型変換です。したがって、charからintへの変換は暗黙的な型変換です。私たちは、Baiduのを確認することができます

:あなたは漢字のバイナリコードがあることがわかります
1110 0100 1011 1000年1010年1101年
の中国の文字はUnicodeのコードの16進表現がcharポイントに保存されているので、なぜchar型することができますが、保存され、3つのバイトを占有し
てみましょうさん漢字のUnicodeコードポイントを確認してください。

漢字のコードポイントは\ u4e2d、\ uであることがわかりました。これは、符号なしを意味し、符号なしを意味します。16進数は4e2dです。
進4e2dをバイナリに変換されます
1110 0010 1101 0100
したがって、チャーに格納された中間ワードの実際の元のコード1110 0010 1101代わりに、3バイトのバイナリコードは、上記見つかったの0100です。
ここで、charをint番号に変換します。元のコードは、
0000 0000 0000 0100 1110 00101101です。
変換後、出力される10進数の結果は次のようになります。20013

3つのブール型変換

ブール型は他の基本データ型との間で変換できず、ビット演算は使用できません。それで私は研究をあきらめました。

4、参照型-型変換

参照データ型は、基本データ型を除くすべての型の参照変数です。
メモリでは、参照変数もデータの一部ですが、格納されている値はアドレスであり、変数の実際の値を指します。したがって、参照変数は参照データ型と呼ばれます。
参照データ型には住所が格納されるため、分析する状況がいくつかあります。

(1)この参照は空のオブジェクトを指しています

int a = null;
编译错误

aこの変数は基本データ型であり、基本データ型はnullオブジェクトを受け入れることができないため、コンパイルエラーが発生します。

Integer g = null;

gこの変数はオブジェクト参照であり、任意のオブジェクトにnullを強制できます。オブジェクトはnullを受け入れることができるためです。

(2)この参照は別のオブジェクトを指しています

デモの例:親子関係以外

	Student  a = new Student;
	Teacher t = (Teacher) a;

ここでは、StudentをTeacherオブジェクトに変換する必要があります。明らかに、型の不一致が原因で、コンパイラーはパスできないため、コンパイラーはエラーを報告します。

デモンストレーションの例:親子関係

Object ob = new Object();
Teacher t = (Teacher)ob;   父转为子(强制转换)也称为向下转型
Object  et = Teacher ;  子 转为 父(隐式转换)也称为向上转型

宇宙の太極拳のように、オブジェクトはすべての根源です。太極拳は2つの楽器を生成し、2つの楽器は4つの画像を生成し、4つの画像はゴシップを生成します。世界のすべてはオブジェクトから派生しています。したがって、これはすべてのオブジェクトの親クラスです。
ここでの変換には2つの単語が表示されます。1つは上向きの変換で、もう1つは下向きの変換です。なぜ下向きの移行は上向きの移行ではなく強制的な移行と呼ばれるのですか?
以前の基本データ型は、大きなスペースを小さなスペースに転送する強制変換として定義されており、データオーバーフローとデータエラーのリスクを引き起こします。ここでも同じことが言えます。
Xiao Yuanの理解では、変数は値であり、その値はヒープ内のオブジェクトを指します。宣言された変数のタイプは、ヒープ内のオブジェクトのマッピングです。写真を見てください。

オブジェクトには独自のプロパティと動作メソッドがあります。親クラスの場合、子クラスは親クラスのプロパティと動作メソッドの拡張です。したがって、同様に、Teacherクラスの変数tを宣言する場合、デフォルトでは、変数tがTeacherのインスタンスオブジェクトを指すことを示していますが、このポイントを親オブジェクトObjectに変更する必要があります。

これには、データエラーのリスクが伴います。変数tによって呼び出されるすべてのメソッド、Objectにはすべてがあり、そのすべてのメソッドを正常に呼び出すことができる場合、Teacherタイプの変数tでのデータエラーのリスクはなく、親子タイプの強制もありません。安全です。逆に、オブジェクトの変数tメソッドにメソッドがいくつかある場合、Teahcerオブジェクトにはあるが、Objectオブジェクトにはないメソッドを呼び出すと、エラーが発生します。

幸せな瞬間

小王是工程局的一名干事,有一天领导交给他一个工程让他去负责办理,三个月后验收。
小王心里高兴得不了,这项工程实际上一个月就可以完成了,于是他开始想剩下的两个月怎么办。
如果早早把工程就办完了,那就得继续干下个工程,即得不到多余的报酬,也浪费了这两个月假期。
于是小王带着一家人去了国外旅游,计划好时间。到时候回来开工。
谁曾想,返回的途中遇到了意料之外的麻烦,匆匆赶回国后只剩下15天时间了。但是还有领导交给他
的一个月工程没干。无奈之下,小王只有昼夜加班,只干完了主体工程。
...
到了交接那天,领导拿着图纸来查看工程进度。发现跟图纸不匹配,工程主体缺这儿缺那儿的,领导一肚子火气。
于是小王遭到了惩罚,被领导炒了鱿鱼。
跟上述对象强制转换一样。引用变量 t 原以为可以调用Teacher 类型的所有方法,结果中途被小王换成了
对象Object ,所以在调用某些方法时,程序就报错了。

おすすめ

転載: blog.csdn.net/weixin_43901067/article/details/103766581