Javaのいくつかの興味深い質問

最近では、アリの姉(妹もそう難しい問題外)「、記事を掲載した賞金を提供しました!「スーパーキングソースの世界に3%を収集する前に、5つの質問 - 最後に彼らの技術は非常にNiubiであることを証明するので、このタイトルを参照してください、私の心は、非常に、非常に興奮しています。

残念ながら、Java開発経験の8年間で、私は自分自身に間違った5つの質問をこの全体の解決策を見つけました!痛みを伴うレッスンは再び、私は97%のものをエンジニアスパイクの一つであったことを証明しています。

しかし、どのような結果、肌の特に厚い私の人々は、すべて間違っているものの、まだ自分自身との平和にあえて。

01、プリミティブ型フロート
最初の質問は次のようにコードがあるようなものです。

{クラスFloatPrimitiveTest公共
のpublic static無効メイン(文字列[] args){
フロートA = 1.0F - 0.9F;
フロート0.9FのB = - 0.8 F;
IF(== b)は{
のSystem.out.println( "真の" );
}他{
するSystem.out.println( "偽の");
}
}
}
。1
2
3。
4。
5。
6。
7。
8。
9。
10
11。
一見すると、この問題は右、単純すぎますか?

1.0F - 0.9f結果が0.1F、0.9fれる - 0.8f結果が0.1Fであり、当然== bのああです。

しかし、実際の結果は、それはあまりにも痛い、そうではありません。

フロート1.0F = - 0.9F;
のSystem.out.println(A); // 0.100000024
フロート0.9FのB = - 0.8 F;
のSystem.out.println(B); // 0.099999964
。1
2
。3
。4
プラス2文を印刷した後、私は理解して、精度の問題が発生していました。

floatとdouble、ラッパークラスのfloatとdoubleだけでなく、それらに対応する:Java言語は、2つの基本的な浮動小数点型をサポートしています。それらは科学的表記で塩基番号に使用されるIEEE 754規格は、10進浮動小数点数2のように表現されるに基づいています。

しかし、浮動小数点演算はほとんど正確です。いくつかの数字が正確2-1と同じである、例えば0.5ため、バイナリ分数として表現することができるが、しかし、いくつかの図面は正確例えば、0.1のために、示されていません。そのため、浮動小数点演算は、丸めエラーにつながる可能性があり、結果が近くにあるが、我々は結果を望んでいることを意味するものではありません。

だから、私達はわずかに大きく0.1より0.1の2つの類似の浮動小数点値、0.100000024の少しを参照し、一方が0.1より0.099999964の少しわずかに小さくなっています。

リテラル任意のJava浮動小数点のために、最終的に値が距離に等しいときに遭遇表すことができる最も近い浮動小数点値に丸め、約2つの浮動小数点値からデフォルト値は優先のも原理を表すことができます。 - 私たちは理由の浮動小数点値4の両端が表示されます理由です。

02は、包装フロートの種類は
次のように、2番目の質問を見て:

{クラスFloatWrapperTest公共
のpublic static無効メイン(文字列[] args){
フロートFloat.valueOf A =(1.0F - 0.9F);
フロートFloat.valueOf B =(0.9F - 0.8 F)、
IF(a.equals(B )){
するSystem.out.println( "真の");
}他{
するSystem.out.println( "偽の");
}
}
}
。1
2
3。
4。
5。
6。
7。
8。
9。
10
11。
一見すると、この問題も右、難しいことではありませんか?単に包装タイプのフロートの元の型に変身するフロートと、代替の使用は==判決に等しいです。

今回は、パッケージは、精度の問題を解決することを考えたので、私は出力が真であると思います。しかし、再び彼女の顔の結果 - 私は厚い皮を持っているが、それでも再びやや赤いくつかの顔を感じるが。

= Float.valueOfフロート(1.0F - 0.9F)
のSystem.out.println(A); // 0.100000024
フロートFloat.valueOf B =(0.9F - 0.8 F)
のSystem.out.println(B)/ / 0.099999964
1
2
3
4
2つの印刷ステートメントを追加した後、私はその元のラッパーを実現し、精度の問題を解決しないであろう。

フロート値ファイナルプライベート、
パブリックフロート(float値){
this.value =値;
}
パブリック静的のvalueOfフロート(フロートF){
新しい新しいfloat(F)を返す;
}
パブリックブール等しい(オブジェクトobj){
リターン(フロートOBJのinstanceof)
&&(floatToIntBits(((FLOAT)OBJ).Valueの)== floatToIntBits(値));
}
。1
2
3
4
5
6
7
8
9
10
11
ソースからは見ることができ、ラッパーフロートは、任意の加工精度を行いませんまた、equalsメソッドの内部で、まだ==裁判官を使用。

03は、スイッチはヌル文字列値を決定し
、以下のように、第三の問題につながります。

{クラスSwitchTest公共
のpublic static無効メイン(文字列[] args){
文字列のparam = NULL;
スイッチ(PARAM){
ケース"ヌル":
のSystem.out.println( "NULL");
BREAK;
デフォルト:
のSystem.out.println ( "デフォルト");
}
}
}
。1
2
3
4
5
6
7
8
9
10
11
12である
視力の私に少しこの質問。

我々はすべて知っているように、スイッチが/他がはるかに容易に実際にある場合よりも効率的な裁判官の文章です。特に、JDK 1.7の後、ケースの条件スイッチは、char、バイト、ショート、整数、文字、バイト、ショート、整数、文字列、または列挙タイプにすることができます。

この問題では、String型のparamは、その後、私はそれがスイッチ状態の場合であると思うが、PARAMの値は確かに一致し、ヌルヌルと「ヌル」されていないですが、私はプログラムは、デフォルトのステートメントの出力デフォルトに入るべきだと思います。

しかし、その結果は、再び自分の顔を作ります!プログラムが例外をスローします。

スレッドの例外「メイン」java.lang.NullPointerExceptionがで
com.cmower.java_demo.Test.main(Test.java:7)AT
1つの
2
であり、ブラケット、スイッチ()が受信ヌルでは使用できません。なぜ?

私は、JDKの公式ドキュメントを通じて反転し、そのような記述があることがわかり、私は直接誰もが理解する上に移動見えます。

switch文が実行されると、最初の式が評価されます。式がNULLと評価された場合、NullPointerExceptionがスローされ、全体のswitch文は、その理由で中途完了する。結果が参照型である場合にそうでなければ、それはアンボクシング変換の対象となります。

式がnullの場合、一般的にswitch文が実行されたとき、それは第一のスイッチ()式を実行します、ということを意味、NullPointerExceptionがスローされます。

最終的にはそれはなぜですか?

公共の静的な無効メイン(文字列引数[])
{
文字列PARAM = NULL;
文字列s;
スイッチ((S = PARAM).hashCode())
{
ケース3392903:
IF(s.equals( "NULL"))
{
するSystem.out.println( "NULL")。
ブレーク;
}
//フォールスルー

デフォルト:
のSystem.out.println( "デフォルト");
BREAK;
}
}
。1
2
3
4
5
6
7
8
9
10
11
12は
13である
14
15
16
17
18れている
19。
JADによって、我々は、バイトコードをコンパイルするために切り替えるもの結果は、上に示しました。元のスイッチの内部実行()は式(S = PARAM).hashCode()であることが判明 、 paramはヌルである時は、sが自然にNullPointerExceptionがスローされたときのhashCode()メソッドを呼び出すこともヌルです。

04、BigDecimalの道の割り当て
次のように第四の質問を参照するには、コードは次のとおりです。

{クラスBigDecimalTest公共
のpublic static無効メイン(文字列[] args){
BigDecimalのBigDecimalの新しい新A =(0.1);
System.out.printlnは(A)
のBigDecimal新しい新B = BigDecimalを( "0.1");
System.out.printlnは( B);
}
}
。1
2
3。
4。
5。
6。
7。
8。
この質問は、唯一の違いは、実際には困難であること、フロート及びB場合コンストラクタBigDecimalの割り当てへの着信、着信列B 、a、bは、結果は0.1である必要がありますので、私はこれらの2つの代入が同じ方法だと思います。

しかし、実際には、出力は完全に私を驚かせました。

新しい新しい= BigDecimalをBigDecimalを(0.1)
のSystem.out.println(A); // 0.1000000000000000055511151231257827021181583404541015625
BigDecimalの新しい新B = BigDecimalを( "0.1");
のSystem.out.println(B); // 0.1
。1
2
。3
。4
本かここではどのように起こっていますか?

あなたは床のJavaDoc町のBigDecimalを(ダブルヴァル)の外に移動する時間である、公式ドキュメントを参照してください必要があります。

このコンストラクタの結果は多少することができる一つは、その書き込み新規のBigDecimal(0.1)は、Java(1のスケールで、1のスケーリングされていない値)0.1と正確に等しいのBigDecimalを作成すると仮定かもしれない。予測できないが、それは実際には同じです0.1ができるので0.1000000000000000055511151231257827021181583404541015625に。これは 、正確に二重(または、そのことについては、任意の有限長のバイナリ分数として)として表現されていない。したがって、コンストラクタに渡される値は、0.1に正確に等しくありません。出演はかかわらず
説明:など、実際の値として、予期しない結果を生成しますダブルパスパラメータを使用した場合0.1 0.1000000000000000055511151231257827021181583404541015625で、はっきりそれを置く、これは精度の問題です。(ケースであること、なぜそれをスクラップないこと?)

Stringコンストラクタは、他の一方で 、完全に予測可能である:新規のBigDecimalを書き込む(「0.1」)は一つのため期待通り、0.1に正確に等しいBigDecimalのを作成し、文字列コンストラクタを優先して使用することが一般的に推奨されています。 この一つに
説明:時間の結果の文字列パラメータ通過の使用が生成するような新しいBigDecimalのように、予想される(「0.1」)は、実際の結果は、0.1です。

ダブルとして使用されなければならない場合 、このコンストラクタは正確な変換を提供することに注意し、BigDecimalのソース、それが持つDouble.toString(二重)を使用して文字列に二重の変換方法およびその後のBigDecimalを使用して同じ結果を与えません。その取得する(文字列)コンストラクタの結果を、静的のvalueOf(ダブル)メソッドを使用します。
説明:あなたはBigDecimalのパラメータとして、ダブル合格する必要がある場合、それは二重のパス文字列値マッチング値ことをお勧めします。2つの方法があります。

=ダブル0.1;
// 0.1;するSystem.out.println(新しい新規のBigDecimal(String.valueOf(A)))
のSystem.out.println(BigDecimal.valueOf(A)); // 0.1
。1
2
。3
第一、文字列に倍増するString.valueOf()を使用します。

第二、のvalueOf()メソッドを使用し、内部メソッドは次のように持つDouble.toString()は、文字列、ソースコードに倍増する呼び出し:

パブリック静的BigDecimalをのvalueOf(ダブルヴァル){
//注意:0個の二重リターン「0.0」、私たちはファーストパスすることはできません
//定数ZEROを使用します。これは十分に重要であるかもしれない
工場出荷時のアプローチ、キャッシュ、または少数の民間正当化//
後で、//定数を。
返す新しいBigDecimalを(持つDouble.toString(ヴァル));
}
1
2
3
4
5
6
7
05、ReentrantLockの
最后一题、也就是第五题、代码如下。

パブリッククラスLockTest {
民間最終静的ロックロック=新しいReentrantLockの();

パブリック静的無効メイン(文字列[] args){
{試みる
)(lock.tryLockします。
}キャッチ(例外e){
e.printStackTrace();
}最後に{
lock.unlock()。
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
问题如下。

:ロックラッチは、非フェアである
B:最後にブロックがスローしない
C:のtryLockは、ロックを取得できなかった下方直接行われます

非常に恥ずかしい、私はReentrantLockのはフェアロックではないかわからない、finallyブロックは、例外がスローされますかわからない。しかし、障害が直接ダウン実行されませんと、ロックを獲得するのtryLock知りません。ない答え。

問題への5つの連続した道路ソリューションは、私は肌の非常に厚いですが、出てくるだけでなく、容赦なく顔に平手打ちをポンピングしているように、彼の顔の燃焼を感じていません。

私はそれを研究調査してみましょう。

1)非公正ロックロック

ReentrantLockのは、サポートリエントラント、すなわち現在のスレッドがロックを取得した後、再びブロックされません、共有リソースにロックを繰り返すことができ、非常に高い周波数のロックです。

ReentrantLockの株式及び非株式ロックロックの両方。何の呼び出しは非公正コンストラクタのパラメータロック、以下のソースコードがない場合:

ReentrantLockのパブリック(){を
同期新しい新しいNonfairSync =();
}
。1
2
。3
ので、この問題をロックする非ロックが公平であると、Aは、正しい選択肢です。

ReentrantLockの構造はまた、他の方法は、以下のソースコードを提供します。

ReentrantLockの公開(ブールフェア){の
SYNC =フェア新しい新しいFairSync():?新しい新しいNonfairSync();
}
。1
2
。3
擬似ロックするとき、非公正、公平ロックに渡されたときに真。

最終的には公正かつ不公平ロックロック、それがどのような違いを作るのですか?

フェアロック要求は、公正ロックの「飢餓」という現象が生じ、ロックするために得ることはできない他のスレッドをもたらすことができるのではなく、時間的に資源の絶対的な順序を保証することができます。

時間程度の公正なロックを保証するために、公正なロックは、コンテキストスイッチの数を減少させるのではなく、頻繁なコンテキスト切り替えを必要とする、パフォーマンス・オーバーヘッドが比較的小さい、システムは高いスループットを確保することができます。

2)finallyブロックはスローされません。

現在のスレッドがロックを保持していない場合は、ロック解除メソッドを呼び出すときにオブジェクトをロックし、この方法は、その後は、IllegalMonitorStateException例外を投げ、tryRelease AbstractQueuedSynchronizerを呼び出します。

フォーム用に最適化され、この質問へのサンプルコード(サービスコードブロックに入る前に、まず現在のスレッドがロックを保持しているかどうかを決定する)ことをお勧めします。

lock.tryLock isLocked =ブール();
IF(isLocked){
試み{
//のdoSomething();
}キャッチ(例外E){
e.printStackTrace();
} {最後に
lock.unlock();
}
}
。1
2
3
4。
5
。6
。7
。8
。9
10
。3)のtryLock直接下方実行ロックを取得できませんでした

以下の通りのJavadocのtryLock()メソッドは次のとおりです。

それが利用可能であり、真の値と、すぐに返された場合、ロックを取得します。ロックが利用できない場合、このメソッドは値falseをしてすぐに戻ります。

ロックを使用することができれば、その後すぐにロックを獲得し、ロックが利用できない場合にtrueを返すことを中国の意味は、直ちにfalseを返します。

この質問のために、そして、のtryLockにロックが失敗した取得、プログラムはfinallyブロック内のコードを実行します。

おすすめ

転載: www.cnblogs.com/yxs98/p/11210622.html