このペーパーでは、JavaプログラミングのJDK1.4、JDK1.5、およびJDK1.6の違いを、例と組み合わせて分析します。次のように、参照のために共有してください。
簡単に言えば、1.4と1.5の間には2つの最大の違いがあります。 1つは、1.5にジェネリックがあり、もう1.5は8つの基本データ型のカプセル化されたデータ型を自動的にカプセル化できることです。つまり、整数a = 4は許可されていません。 1.5と1.6の間に大きな違いはありません。 1.6ほとんどの変更はGUIだと思います。これは、多くの便利なレイアウト管理と拡張機能を提供します。
この期間中、私は電子政府会社に加わり、Weblogic8を使用しました。次に、JDK1.4を使用しましょう。 EclipseはJDKバージョンを変更しました。ただし、以前のプロジェクトは基本的に人気があります。
★JDK1.5の新機能:
1。ジェネリック
2自動パッキング/ボックス化
3つのfor-for-for
4静的インポート
5変数長さパラメーター
1。ジェネリック(型キャストによって引き起こされる可能性のある実行エラーを避けてください)
例えば:
arrayList list = new ArrayList(); list.add(new Integer(3)); list.add(new Integer(4)); int i =((integer)(list.get(0)))。parseint();
とても面倒です
arrayList <integer> list = new ArrayList <Integer>(); list.add(new Integer(3)); list.add(new Integer(4)); int i = list.get(0).parseint();
2自動パッキング/ボックス化
上記の例の最後の文は次のように変更できます。
コードコピーは次のとおりです。Inti= list.get(0);
元のタイプと対応するラッパークラスを明示的に変換する必要はないため
3つのfor-for-for
ループの強化
int a [] = {......}; //初期化(int i:a){......}以前のi = 0; i <a.length; i ++を使用しないでください
4静的インポート
以前に調整されたJava.math
コードコピーは次のとおりです。Math.sqrt();
static Import Java.lang.math.sqrt;
sqrt();
これはあなた自身のクラスにこの方法を持つことと同等です
5変数長さパラメーター
int sum(int ... intlist){int sum; sum = 0; for(int i = 0; i <intlist.length; i ++){sum+= intlist [i]; } return sum;}パラメーターはありますが、配列として扱います
★JDK6.0の新機能
ループステートメントのために強化された「隠された」静的メソッドvariadicパラメーター(vararg)の列挙
ループステートメント用に強化されたワイルドカードと共分散リターン
セットと配列を反復するために、拡張されたループは、シンプルで互換性のある構文を提供します。言及する価値のある2つのポイントがあります:
1。ループでは、初期化式は一度だけ計算されます。 int式
強化されていない:
int sum = 0; integer [] numbers = computeNumbers(); for(int i = 0; i <numbers.length; i ++)sum+= numbers [i];
拡張:
int sum = 0; for(int number:computeNumbers())sum += number;
制限
ITERATORまたはsubscriptには、ループイテレーションのために強化されたときにアクセスできません
次の例をご覧ください。
for(int i = 0; i <numbers.length; i ++){if(i!= 0)system.out.print( "、"); system.out.print(number [i]);}別の例があります:
for(iterator <integer> it = n.iterator(); it.hasnext();)if(it.next()<0)it.remove();
コメント
コメント処理は大きなトピックです。この記事はコア言語機能のみに焦点を当てているため、考えられるすべての形式と落とし穴をカバーするつもりはありません。組み込みの注釈(抑制、抑制、非推奨、オーバーライド)と一般的な注釈処理の制限について説明します。
警告を抑制します
このコメントは、クラスまたはメソッドレベルでコンパイラ警告をオフにします。コンパイラよりも、コードが拒否されたメソッドを使用するか、タイプセーフがタイプセーフであるかどうかを静的に判断できないアクションを実行する必要があることをコンパイラよりも明確に知っている場合があります。
@suppresswarnings( "deprecation")public static void selfdestruct(){thread.currentthread()。stop();}これはおそらく、組み込みの注釈で最も有用なことです。残念ながら、1.5.0_04のJavacはそれをサポートしていません。しかし、1.6はそれをサポートしており、Sunはそれを1.5に後方に移植することに取り組んでいます。
この注釈はEclipse 3.1でサポートされており、他のIDEもサポートする場合があります。これにより、警告からコードを完全に解放できます。コンパイル時間に警告がある場合は、追加しただけであることを確認できます。安全でない可能性のあるコードを表示するのに役立ちます。ジェネリックを追加すると、使用する方が便利です。
非推奨
残念ながら、非推奨はそれほど有用ではありません。もともとは @deprecated Javadocタグを置き換えることを目的としていましたが、フィールドには含まれていないため、非推奨クラスまたはメソッドのユーザーが代替として使用するものを提案する方法はありません。ほとんど
両方の使用には、Javadocタグとこの注釈が必要です。
オーバーライド
Overrideによれば、注釈を付ける方法は、スーパークラスに同じ署名を使用してメソッドをオーバーライドする必要があると述べています。
@overridepublic int hashcode(){...}上記の例を見ると、「c」がハッシュコードで大文字になっていない場合、コンパイル時にエラーはありませんが、その方法は実行時に予想されると呼ばれません。オーバーライドタグを追加することにより、コンパイラが実際に書き換えを実行した場合にプロンプトが表示されます。
これは、スーパークラスが変化する状況でも役立ちます。新しいパラメーターがメソッドに追加され、メソッド自体が名前が変更された場合、スーパークラスから何も書き換えないため、サブクラスは突然コンパイルされません。
その他のメモ
コメントは他のシナリオで非常に役立ちます。動作を直接変更するのではなく、動作を強化する場合、特にボイラープレートコードを追加する場合、注釈はEJBやWebサービスなどのフレームワークで非常にうまく機能します。
コメントは、前処理者として使用することはできません。 Sunの設計は、コメントのために完全にクラスのバイトコードの変更を特に防ぎます。これにより、言語の結果を正しく理解することができ、IDEのようなツールは詳細なコード分析とリファクタリングを実行することもできます。
コメントは銀の弾丸ではありません。私が最初に遭遇したとき、人々はさまざまなテクニックを試みようとしました。他の人から入手した次の提案をご覧ください。
パブリッククラスfoo {@propertyprivate int bar;}アイデアは、プライベートフィールドバーのゲッターとセッターのメソッドを自動的に作成することです。残念ながら、このアイデアには2つの障害があります。1)動作せず、2)コードの読み取りと処理を困難にします。前述のように、太陽は特にコメントを含むクラスの変更を特に防ぐため、実装することは不可能です。
たとえ可能であっても、コードの読み取りが不十分になるため、それは良い考えではありません。このコードを初めて見たとき、コメントがメソッドを作成することはわかりません。また、将来これらの方法内でいくつかの操作を実行する必要がある場合、コメントは役に立たない。要するに、通常のコードがコメントでできることをしようとしないでください。
列挙します
Enumは、長年にわたって列挙値として使用されてきたPublic Static Final Int宣言に非常によく似ています。 INTの最大かつ最も明らかな改善は、タイプの安全性です。別のタイプを1つのタイプの列挙に誤って置き換えることはできません。これはINTとは異なり、すべてのINTはコンパイラで同じです。例外はほとんどありませんが、通常、すべてのenumスタイルのINT構造を列挙インスタンスに置き換える必要があります。
列挙はいくつかの追加機能を提供します。 2つの実用的なクラスの列挙と列挙設定は、列挙のために特別に最適化された標準セット実装です。コレクションに列挙型のみが含まれていることがわかっている場合は、ハッシュマップまたはハッシュセットの代わりにこれらの特別なコレクションを使用する必要があります。
ほとんどの場合、Enumを使用して、コード内のすべてのpublic Static Final Intを置き換えることができます。それらは同等であり、静的にインポートすることができるため、内部クラス(または内側の列挙タイプ)であっても、それらへの参照は同等のように見えます。列挙の種類を比較するとき、それらを宣言する命令は順次値を示していることに注意してください。
「隠された」静的方法
2つの静的メソッドがすべての列挙型宣言に表示されます。それらは列挙の方法自体ではなく、enumサブクラスの静的な方法であるため、javadoc of java.lang.enumには登場しません。
最初はvalues()で、列挙型のすべての可能な値の配列を返します。
2番目はvalueof()です。これは、提供された文字列の列挙タイプを返します。これは、ソースコード宣言と正確に一致する必要があります。
方法
列挙タイプに関する私たちのお気に入りの側面の1つは、メソッドを持つことができることです。過去には、public static final intを変換し、データベースタイプからJDBC URLに変換するためにコードを作成する必要がある場合があります。これで、列挙タイプ自体は完全に作成できます
コードを操作する方法。以下に、データベースタイプの列挙タイプの抽象的な方法と、各列挙インスタンスで提供される実装を含む例を示します。
public enum databaseType {oracle {public string getjdbcurl(){...}}、mysql {public string getjdbcurl(){...}}; public abstract string getjdbcurl();}これで、列挙型は実用的な方法を直接提供できます。例えば:
databaseType dbtype = ...;文字列jdbcurl = dbtype.getjdbcurl();
URLを取得するには、ユーティリティ方法がどこにあるかを事前に知る必要があります。
vararg
可変パラメーターを正しく使用すると、いくつかのジャンクコードがクリーンアップされます。典型的な例は、さまざまな数の文字列パラメーターを持つログメソッドです。
log.log(string code)log.log(string code、string arg)log.log(string code、string arg1、string arg2)log.log(string code、string [] args)
変数パラメーターを議論するとき、最初の4つの例を新しい変数パラメーターに置き換えると、互換性があります。
コードを次のようにコピーします:log.log(string code、string ... args)
すべての可変パラメーターはソース互換です - つまり、log()メソッドのすべての呼び出しプログラムが再コンパイルされている場合、4つのメソッドはすべて直接置き換えることができます。ただし、逆方向のバイナリ互換性が必要な場合は、最初の3つの方法を放棄する必要があります。文字列配列パラメーターを使用した最後のメソッドのみがVariadicバージョンに相当するため、Variadicバージョンに置き換えることができます。
タイプキャスト
どのタイプのパラメーターを使用するかを発信者に知りたい場合は、可変パラメーターを使用したタイプキャストを避ける必要があります。次の例を見ると、最初の希望はひもであり、2番目の希望は例外です。
log.log(object ... objects){string message =(string)objects [0]; if(objects.length> 1){例外e =(例外)オブジェクト[1]; //例外で何かを行う}}}}メソッドの署名は次のようにする必要があり、対応する可変パラメーターは、それぞれ文字列と例外を使用して宣言されます。
コードコピーは次のとおりです。Log.Log(Stringメッセージ、例外E、オブジェクト...オブジェクト){...}
タイプシステムを破壊するために可変パラメーターを使用しないでください。強く入力された場合にのみ使用できます。このルールでは、printStream.printf()は興味深い例外です。これらのタイプを後で受け入れることができるように、タイプ情報を最初の引数として提供します。
共分散のリターン
Covariant Returnの基本的な使用法は、実装のリターンタイプがAPIよりも具体的であることが知られている場合、タイプキャストを避けるためです。次の例では、動物オブジェクトを返す動物園インターフェイスがあります。実装はAnimalIMPLオブジェクトを返しますが、JDK 1.5の前に動物オブジェクトを返すように宣言する必要があります。 :
パブリックインターフェイスZoo {public Animal getAnimal();} public class zooimpl explention zoo {public animal getanimal(){return new Animalimpl();}}}Covariant Returnsの使用は、3つのアンチパターンに取って代わります。
直接フィールドアクセス。 APIの制限を回避するために、一部の実装はサブクラスを直接フィールドに公開します。
コードを次のようにコピーします:Zooimpl._animal
別のフォームは、実装が実際に特定のサブクラスであることを知って、呼び出しプログラムでダウンコンバージョンを実行することです。
コードコピーは次のとおりです。
私が見た最後のフォームは、まったく異なる署名によって引き起こされる問題を回避するために使用される具体的な方法です。
コードコピーは次のとおりです。Zooimpl._getanimal();
これらの3つのモードには問題と制限があります。それは十分にきれいではないか、不必要な実装の詳細を公開します。
共分散
Covariant Return Modeはよりクリーンで、より安全で、メンテナンスが簡単で、型キャストや特定の方法やフィールドを必要としません。
public Animalimpl getanimal(){return new Animalimpl(); }結果の使用:
コードコピーは次のとおりです。Zooimpl.getanimal()。emplmethod();
ジェネリックを使用します
ジェネリックの使用とジェネリックの構築という2つの視点からジェネリックについて学びます。リスト、セット、マップの明らかな使用については説明しません。一般的なコレクションは強力であり、頻繁に使用する必要があることを知るだけで十分です。
一般的な方法の使用と、タイプを推測するコンパイラの方法について説明します。通常、これらのいずれも間違っていませんが、何か問題が発生した場合、エラーメッセージは非常に混乱する可能性があるため、これらの問題を修正する方法を知る必要があります。
一般的な方法
一般的なタイプに加えて、Java 5は一般的な方法も導入します。 java.util.collectionsのこの例では、単一の要素リストが構築されています。新しいリストの要素タイプは、メソッドで渡されたオブジェクトのタイプに基づいて推測されます。
コードを次のようにコピーします:static <t> list <t> collections.singletonlist(t o)
使用例:
public list <integer> getListofone(){return collections.singletonList(1);}例では、INTに渡されます。したがって、メソッドの戻りタイプはlist <integer>です。コンパイラは整数に誘導します。これは、一般的にタイプパラメーターを明示的に指定する必要がないため、一般的なタイプとは異なります。
これは、オートボクシングとジェネリック間の相互作用も示しています。タイプパラメーターは参照タイプである必要があります。そのため、list <int>の代わりにlist <integer>を取得します。
パラメーターのない一般的な方法
emptyylist()メソッドは、java.util.collectionsのempty_listフィールドのタイプセーフ順列としてgenericsで紹介されます。
コードを次のようにコピーします:static <t> list <t> collectionsemptylist()
使用例:
public list <integer> getNointegers(){return collections.emptylist();}前の例とは異なり、この方法にはパラメーターがありません。コンパイラはTのタイプをどのように推測しますか?基本的に、パラメーターを1回使用しようとします。うまくいかない場合は、返品または割り当てタイプを再度使用しようとします。この例では、リターンはリスト<integer>であるため、tは整数として推測されます。
一般的なメソッドが戻り声明または割り当てステートメントの外部で呼び出されるとどうなりますか?その場合、コンパイラはタイプ推論の2回目の転送を実行できません。次の例では、emptylist()は条件演算子内から呼び出されます。
public List <integer> getNointegers(){return x? collections.emptylist():null;}コンパイラはリターンコンテキストを表示できず、Tを推測できないため、捨ててオブジェクトを取得します。 「リスト<Object>を変換することはできません<integer>」のようなエラーメッセージが表示されます。
このエラーを修正するには、タイプパラメーターをメソッド呼び出しに明示的に渡す必要があります。これにより、コンパイラはタイプパラメーターを推測しようとせず、正しい結果を得ることができます。
コードコピーは次のとおりです。xを返しますか?コレクション。<integer> emptylist():null;
これが頻繁に発生する別の場所は、メソッド呼び出しにあります。メソッドがリスト<string>パラメーターを取得し、そのパラメーターの渡されたemmthylist()を呼び出す必要がある場合、この構文も必要です。
コレクションの外
コレクションではなく、斬新な方法でジェネリックを使用する一般的なタイプの3つの例を以下に示します。 3つの例はすべて、標準のJavaライブラリからのものです。
次のようにコードをコピーします:クラス<t>
クラスはクラスタイプでパラメーター化されています。これにより、型キャストなしで新興味を構築することが可能になります。
次のようにコードをコピーします:同等の<t>
比較可能は、実際の比較タイプによってパラメーター化されています。これにより、()呼び出しを比較すると、より強いタイピングが提供されます。たとえば、文字列は比較可能な<string>を実装します。文字列以外のすべてのものでcompareto()を呼び出すと、コンパイル時に失敗します。
コードを次のようにコピーします。Enum<e ends enum <e >>
列挙は、列挙型によってパラメーター化されます。色という名前の列挙型は、enum <color>を拡張します。 getDeclaringClass()メソッドは、列挙タイプのクラスオブジェクトを返します。この例では、色オブジェクトです。 GetClass()とは異なり、名前のないクラスを返す可能性があります。
ワイルドカード
ジェネリックの最も複雑な部分は、ワイルドカードのキャラクターの理解です。 3種類のワイルドカードとその用途について説明します。
まず、配列の仕組みを理解しましょう。整数[]から番号[]に値を割り当てることができます。 floatを番号[]に書き込もうとすると、コンパイルできますが、実行時に失敗し、ArrayStoreExceptionが表示されます。
integer [] ia = new Integer [5]; number [] na = ia; na [0] = 0.5; //コンパイルですが、実行時に失敗します
例をジェネリックに直接変換しようとすると、割り当てが許可されていないため、コンパイル時に失敗します。
List <Integer> ilist = new ArrayList <Integer>(); list <number> nlist = ilist; // adoladnlist.add(0.5);
ジェネリックを使用する場合、コンパイル時にコードが表示されない限り、ランタイムClassCastExceptionに遭遇しません。
上限ワイルドカード
私たちが望むのは、アレイとは異なる正確な要素タイプのリストです。
リスト<number>は、要素タイプが特定のタイプ番号であるリストです。
リスト<?拡張番号>は、正確な要素タイプ不明のリストです。それは数字またはそのサブタイプです。
上限
最初の例を更新し、値をリストに割り当てると<?番号を拡張>、その後、割り当ては成功します。
List <Integer> ilist = new ArrayList <Integer>(); list <?番号> nlist = ilist; number n = nlist.get(0); nlist.add(0.5); //許可されていません
リストの正確な要素タイプ(フロート、整数、または番号)に関係なく、リストから番号を割り当てることができます。
フローティングポイントタイプをリストに挿入することはできません。これは、これが安全であることを証明できないため、コンパイル時に失敗します。フローティングポイントタイプをリストに追加したい場合、Ilistの初期タイプの安全性が破損します。整数のみを保存します。
ワイルドカードは、配列よりも表現力のあるパワーを与えてくれます。
ワイルドカードを使用する理由
次の例では、APIのユーザーからタイプ情報を非表示にするためにワイルドカードを使用します。内部的には、セットはcustomerimplとして保存されます。 APIユーザーは、顧客を読み取ることができるセットを取得していることのみを知っています。
ここでは、set <customerimpl>から<customer>をset set <customer>に割り当てることが不可能であるため、ここで必要です。
Public Class CustomerFactory {private set <CustomerImpl> _Customers; public set <? customers> getcustomers(){return _customers;}}ワイルドカードとコバリアンリターン
ワイルドカードキャラクターのもう1つの一般的な使用法は、Covariant Returnで使用することです。割り当てと同じルールを共変リターンに適用できます。書き換えられた方法でより具体的な一般的なタイプを返したい場合、宣言された方法はワイルドカードを使用する必要があります。
パブリックインターフェイスNumberGenerator {public List <? extends number> generate();} public class fibonaccigenerator extends novedgenerator {public list <integer> generate(){...}}配列を使用する場合、インターフェイスは番号[]を返すことができますが、実装は整数[]を返すことができます。
下限
私たちが話しているのは、主に上限のワイルドカードに関するものです。また、下限ワイルドカードもあります。リスト<? Super Number>は、正確な「要素タイプ」のリストで不明ですが、数値のスーパータイプである場合があります。したがって、それはリスト<number>またはリスト<Object>である可能性があります。
低い制限のあるワイルドカードは、上限のワイルドカードよりもはるかに一般的ではありませんが、必要なときに必要です。
下限と上限
リスト<?番号> readlist = new arrayList <integer>(); number n = readlist.get(0); list <? Super Number> WriteList = new ArrayList <Object>(); writeList.add(new Integer(5));
1つ目は、読むことができる数字のリストです。
2つ目は、書くことができる数字のリストです。
無制限のワイルドカード
最後に、リスト<?>リストのコンテンツは任意のタイプである可能性があり、リスト<とほぼ同じですか?オブジェクトを拡張>。オブジェクトはいつでも読み取ることができますが、コンテンツをリストに書き込むことはできません。
公共のAPIのワイルドカード
要するに、前述のように、ワイルドカードは発信者からの実装の詳細を隠す上で非常に重要ですが、下限のあるワイルドカードが読み取り専用アクセスを提供していると思われていても、remove(int position)などの一般的なメソッドのためにはそうではありません。本当に変更されていないコレクションが必要な場合は、java.util.collectionのようなメソッドをUnmodifiablelist()で使用できます。
APIを書くときはワイルドカードを覚えておいてください。一般的に、一般的なタイプを渡すときは、ワイルドカードを使用してみてください。より多くの発信者がAPIにアクセスできるようになります。
リストを受け取ることによって<?リスト> list <number>の代わりに拡張すると、次の方法はさまざまな種類のリストで呼び出すことができます。
コードコピーは次のとおりです。VOIDremovenegives(list <?extends number> list);
一般的なタイプを構築します
次に、独自の一般的なタイプの構築について説明します。ジェネリックを使用してタイプの安全性を改善できる例をいくつか示し、ジェネリックタイプを実装する際にいくつかの一般的な問題についても説明します。
コレクションのような機能
一般的なクラスの最初の例は、コレクションスタイルの例です。ペアには2つのタイプパラメーターがあり、フィールドは次のタイプのインスタンスです。
パブリックファイナルクラスペア<a、b> {パブリックファイナルAファースト;パブリックファイナルBセカンド、パブリックペア(1秒、b second){this.first = first; this.second = second;}}}これにより、2つのタイプの組み合わせごとに専用クラスを作成せずに、メソッドから2つのアイテムを返すことができます。別の方法は、オブジェクト[]を返すことです。これはタイプが安全でないか乱雑です。
次の使用法では、メソッドからファイルとブール値を返します。メソッドのクライアントは、型キャストなしでフィールドを直接使用できます。
public Pair <file、boolean> getFileandWritestatus(String Path){// file and status Return new Paile <file、boolean>(file、status);} paile <file、boolean> result = getFileandWritestatus( "...");ファイルf = result.first; Boolean Writeable = result.second;コレクションの外
次の例では、ジェネリックは追加のコンパイル時間セキュリティに使用されます。 DBFactoryクラスを作成したピアタイプにパラメーター化することにより、実際に工場のサブクラスにピアの特定のサブタイプを返すように強制しています。
public abstract class dbactory <t extends dbpeer> {protected abstract t creatementypeer(); public list <t> get(string constraint){list <t> peers = new arraylist <t>(); // Database MagicReturn Peers;}}}dbactory <customer>を実装することにより、customerFactoryはcreatementypeer()から顧客を返す必要があります。
Public Class CustomerFactoryはdbactory <cultions> {public customer createEmptypeer(){return new Customer();}}一般的な方法
パラメーター間の一般的なタイプに制約を課したいかどうか、およびパラメーターとリターンタイプ間で、一般的な方法を使用できます。
たとえば、記述された反転関数が位置的に反転している場合、一般的な方法は必要ない場合があります。ただし、反転を新しいリストに戻す場合は、新しいリストの要素タイプを次のリストのタイプと同じにすることができます。この場合、一般的な方法が必要です。
次のようにコードをコピーします:<t>リスト<t>逆(リスト<t>リスト)
コンクリート
一般的なクラスを実装する場合、配列t []を作成することもできます。ジェネリックは消去によって実装されるため、これは許可されていません。
オブジェクト[]をt []にキャストすることができます。しかし、これは安全ではありません。
コンクリートソリューション
一般的なチュートリアルの慣習によると、ソリューションは「タイプトークン」を使用しています。コンストラクターにクラス<T>パラメーターを追加することにより、クライアントにクラスのタイプパラメーターに正しいクラスオブジェクトを提供するように強制できます。
public class arrayexample <t> {private class <t> clazz; public arrayexample(class <t> clazz){this.clazz = clazz;} public t [] getArray(int size){return(t [])array.newinstance(clazz、size);}}}}arrayexample <string>を構築するには、string.classのタイプがclass <string>であるため、クライアントはstring.classをコンストラクターに渡す必要があります。
クラスオブジェクトを持つことにより、正しい要素タイプのグループを構築することができます
この記事がみんなのJavaプログラミングに役立つことを願っています。