2012-02-21 6 views
2

私はいくつかのコードを見ています。オブジェクトに加えられた変更が実際にそれらのオブジェクトまたはそれらのオブジェクトのコピーに対して行われたかどうかを確認したいと思います。オブジェクトまたはそのオブジェクトのコピーを変更していますか?

ここではサンプルです:

for(int i = 0; i < myList.size(); i++) 
{ 
    DataObject myItem = (DataObject)myList.get(i); 
    myItem.setString("someKey", "someValue"); 
} 

はmyListは、データオブジェクトのリストであるので、私は目的が、リスト上のget()メソッドを呼び出した後のDataObjectに項目をキャストするのだったかわかりません。しかし、コンパイル時にどのように処理されるのだろうか?キャストは新しいオブジェクトを作成し、その新しいオブジェクトに対してsetString()メソッドが呼び出され、リスト内のオブジェクトには影響しませんか?または、myItemはリストの実際の項目を参照していますか?

ありがとうございました。

答えて

2

まだキャスト後のリストの項目への参照です。コピーは作成されません。

Listは、あらゆるタイプのObject(すべてのクラスがObjectを拡張するので)に使用できるように、Objectクラスの型を返します。しかし、setStringを呼び出すためには、参照型をより具体的なものにキャストして、コンパイラがどのような種類のオブジェクトを呼び出しているかを知る必要があります。

ジェネリックを使用します。 Listリストをタイプ指定すると、キャストする必要はありませんが、リストの作成を制御できない場合や、どのタイプのオブジェクトがそのリストに含まれているかわからない場合、または制限したい場合には適切でない場合があります。

0

ジェネリックを使用する場合、キャストする必要はありません。キャストする必要があります。キャストする必要があるのは、どのタイプのオブジェクトリストがあるかを知る方法がないためです。

しかし、それがコンパイルされたとき、私はこれがどのように扱われるか疑問に思う - キャストは新しいオブジェクトを作成します

コンパイラは、任意のオブジェクトを作成するつもりはありません。構文とセマンティクスをチェックするだけです。その特定の行をコンパイルする間、コンパイラーは参照がDataObject型であることを認識しますが、list.get()は互換性のない型になるオブジェクト型を戻します。したがって、明示的にキャストする必要があります。

1

キャストは新しいオブジェクトを作成しません。コンパイラに「ちょっと、私がやっていることを知っています。これはDataObjectです。

実際のList実装のタイプを知らなくても、取得しているものが同じオブジェクトであるかどうかはわかりません。 Java Collectionsコレクション(ArrayList、LinkedListなど)のいずれかを使用している場合は、同じオブジェクトインスタンスになります。しかし、私は、基本的なインスタンスではなくコピーを返す実装(もちろん自分で作った)を想像することができます。

public class MyList<T> implements List<T> { 
    private List<T> backingList = new ArrayList<T>(); 

    //methods to fulfil List interface contract... 

    @Override 
    public T get(int index) { 
     T t = backingList.get(index); 
     return makeCopy(t); 
    } 

    private T makeCopy(T t) { 
     //make a copy of t! 
    } 
} 

そして、それはget(int)メソッドは、コピーを返したりしませんならば、我々は(あなたが私たちの基本的なタイプを告げずに)伝えることができないこと、そのためです。

+0

+1リストが内部的に何をするかわからないという点については、非常に良い点です。それが不変のリスト要素を使うもう一つの理由です。 – biziclop

+0

ああ、私たちは皆、これがうまく動作するList実装であると仮定しています。しかし、get()メソッド*はコピーを返すことができます。しかし、それは非常にありそうもありません。しかし、キャスト自体は新しいオブジェクトを作成しません。いいですよ。 –

+0

良い点!私が言及すべきは、 'myList'は、' DataObject'型のオブジェクトに対して 'getList()'メソッドを呼び出すことによってコード内で先に宣言されました。 – Poosh

0

キャストは新しいDataObjectを作成しません。キャストは、プリミティブをラッパータイプに変換する場合は以外の新しいオブジェクトを一般に作成しません。また、toString()メソッドを呼び出す結果のStringへの明示的または暗黙のキャストの場合

1

これは、リスト内の実際の項目を参照している、すべてのキャストはありません、あなたがオブジェクトの実際タイプがあることを行っているか知っている、宣言タイプを無視するようにコンパイラに指示しています。 (間違っていると、ClassCastExceptionのランタイムが得られるので、可能であればキャストは避けるべきです。詳細については、ジェネリックスを参考にしてください。

今、この種のもの(コレクションの要素を変更する)は問題なくリストで動作しますが、Setで、Mapのキーでは、不変のオブジェクト(基本的には、コンストラクタの呼び出し後にフィールドが変更できないオブジェクト)を使用する必要があります。混乱。コレクションが複数のスレッド間で共有されている場合は、これも避ける必要があります。

+0

+1あなたに戻ってきます。 –

0

myList.get()は、オブジェクトなどのより一般的な型を返すように定義できます。参照変数は、それ自身よりも汎用的な型を参照することはできません。したがって、キャストを行う必要があります。

DataObject myItem = (DataObject) myList.get(i); 

キャストは新しいオブジェクトを作成しません。キャストは、変数myItemがリスト内の既存のオブジェクトを参照するようにします。したがって、setString()メソッドは実際のオブジェクトを変更します。したがって、同じオブジェクトであるため、リスト内のオブジェクトも変更されます。

List<DataObject> myList = new ArrayList<DataObject>(); 

その後、キャストは必要ありません。

0

myListの場合はそうのように、型指定されたリストとして宣言されています。ただし、型なしListの場合は、getメソッドはObjectのオブジェクトを返します。それはキャストが必要な理由かもしれません(宣言を見ることなく、私は伝えることはできません)。

キャストは新しいオブジェクトを作成していないと言っていますので、リストに既に存在するオブジェクトへの新しい参照です。つまり、変更はmyList内で発生します。

+0

変数myListは、コードの前の 'DataObject'で' getList() 'メソッドを呼び出すことによって宣言されています。私はおそらくそれを言及していたはずです。しかし、それは理にかなっています。 'get()'メソッドが 'Object'型のオブジェクトを返すので、彼らはそういう形で書く必要があります。ありがとう! – Poosh

0

おそらく同じオブジェクトです。

newオブジェクトを作成する唯一のものは何ですか? newキーワード。 clone()(正しく実装されている場合)が新しいオブジェクトを作成すると主張する人もいますが、それは何でしょうか?クローン機能にはnewというキーワードがあります!

あなたはどのような種類の対処をしているのか分かりませんが、それが標準Javaライブラリ(ArrayList, LinkedList, etc)の一部であると仮定すると、同じオブジェクトを取得します。

P.S.配列もオブジェクトであることを忘れないでください!

関連する問題