IDEが非常に賢い場合、「clone()」をキャストする必要があるのはなぜですか?


13

コードを入力している間、IDE(NetBeans)タイプがチェックしCollectionsます。しかし、その後、返されたオブジェクトをキャストする必要があるのはなぜObject.clone()ですか?大丈夫です。害もファウルもありません。しかし、それでも理解できません。

型チェックは、キャストせずに、返されたオブジェクトをObject.clone()不可能ですか?ジェネリックフレームワークは、私はIDEがチェックできると思いますタイプ「の右側のオブジェクト参照の=私はタイピングをしていながら、キャストなし」マークを?わかりません。

補遺
私の使用例は、私がプライベートCalendarフィールドpubdateを持っていたことだけでした。私は書くつもりでした:

Calendar getPubdate() {
    return pubdate;
}

しかし、呼び出し側がpubdateを変更する可能性があるため、コピーを返しました。

Calendar getPubdate() {
    return (Calendar) pubdate.clone();
}

次に、なぜキャストする必要があるのか​​疑問に思いましたpubdate.clone()。メソッドシグニチャにはタイプがあります。NetBeansはそれを理解できるはずです。そしてNetBeansはに関して同様のことをしているようCollectionsでした。


5
短い(!)コード例が役立ちます。
ドックブラウン

78
IDEは言語自体から分離されているため、Netbeansがいかにスマートであるかは、言語のJavaの動作には影響しません。
ジャックB

7
戻り値の型の共分散のため、MyObjectからclone()ではなく戻り値を使用することをお勧めしObjectます。これにより、この問題全体が解消されます。さらに、絶対に使用しないことをお勧めしますclone()(有効なJavaアイテム#11)。
スパイダーボリス

あなたの質問の重点は、または「キャスト「clone()」」ですか?前者から生じる質問は、実際には後者からの質問よりもはるかに良い質問である可能性があるためです。
user541686

質問のタイトルを読んだとき、私が考える唯一のことはthis.clone()プログラマーオブジェクト、特に火のリリース後の水曜日の夜です。すみませんが、このコメントを書かなければなりません。なぜスマートIDEがすべてのバグを修正できないのでしょうかLOL
Mai

回答:


53

なぜ返されたオブジェクトをキャストする必要がありObject.clone()ますか?

戻るからObject

ジェネリックフレームワークは、私はIDEがチェックできると思いますタイプ「の右側のオブジェクト参照の=私はタイピングをしていながら、キャストなし」マークを?わかりません。

Object.clone ジェネリックではありません。

clone設計時にジェネリックが存在していた場合、おそらく次のようになりました(F境界ポリモーフィズムを使用)。

interface Cloneable<T extends Cloneable<T>> {
  T clone();
}

JavaにMyType機能がある場合、次のようになります。

interface Cloneable {
  this clone();
}

しかし、GenericsはObject.clone設計時に存在していなかったし、JavaにはMyTypesがないため、の型安全でないバージョンがObject.clone作業する必要があります。


私を混乱させたIDE機能はバックグラウンドコンパイルであることに気付いたのですか。つまり、それがコード補完とジェネリックによる自動型チェックを可能にするのですか?個人的には、明示的なコンパイルまで型チェックを遅らせることを好みます。しかし、私はコード補完が大好きです。
コニシキ

1
@konishikiとJava 8(およびある程度Java 7)の型推論、支援を提供するために、IDEは型を推論する必要があります。これには部分的なコンパイルが必要です。型推論の前に、オートコンプリートにコンパイルは必要ありません。
スパイダーボリス

@BoristheSpiderフィードバックありがとうございます!私は間違いなく、さらにテスト/思考する必要があります。非常に高く評価。
コニシキ

なぜ合格する必要があるのoriginalですか?
Clashsoft

@Clashsoft:明白な関数型プログラミングバージョンを適応させている間、愚かな考え方。ありがとう。
ヨルグWミットタグ

26

これはIDEの機能ではなく、言語定義の機能です。

IDEを使用すると、プログラミング言語をより効率的に使用できます。その言語のセマンティクスは変更されません。つまり、エディターヘルパーは、必要なキャストが明らかな場合にキャストを自動的に挿入する可能性がありますが、単に言語の規則を破り、コンパイルされないコードが有効であると装うことはできません。

編集 IDEが独自のコンパイラをバンドルできることは事実です。実際には、たとえば、部分解析ツリーへの内部情報を増やしてエラーレポートを改善するために、多くのコンパイラがまさにそれを行います。ただし、この内部コンパイラに公式SDKとは異なる言語セマンティクスを実装させることは非常に悪い考えです。これは、開発中に動作するコードが実稼働環境にインストールされたときに不可解に失敗し始める可能性があることを意味します。デバッグ可能!


これが何が起こったのかです:コード補完がIDEの機能であると確信しています(リフレクションによって行われます)。そして、私が話していた自動型チェックは、IDEで(バックグラウンドコンパイルを介して)行われます。それが起こっていることを願っています。
コニシキ

1
IDEができる非常に簡単に、言語仕様のすべてのルールを破ると、ちょうどとにかくコードをコンパイルします。たとえば、NetBeansとEclipseの両方が独自のコンパイラを使用していることを知っています。そのため、これらの場合、IDEとコンパイラは事実上同じものです。良いアイデアとは言いませんが、Cコンパイラは常にそれを行っています。
MichaelS

@MichaelS C言語仕様は、実装ごとに大きな違いを許容するように設計されているため、さまざまなベンダーがさまざまな可能なアプローチから選択して、追加機能を追加できます。これにより、仕様にあいまいさのさまざまな領域が作成されますが、これらのバリエーションを許可するために必要です。「C」という名前は商標ではないため、誰もこの用語の使用を管理していません。Java仕様は、あいまいさを可能な限り排除するように設計されており、Javaは商標登録されており、商標権者は準拠実装でのみ使用できることを強制しています。
ジュール

とにかく、現代のIDEにはコンパイラが必要です。コード補完のヒントでは、カーソルの前のコードを解析する必要があります。そして確かに、単なるパーサーではなく、完全なコンパイラーを必要とするジェネリック(またはC ++テンプレート)で。
MSalters

3

これは、Object.cloneメソッドの型シグネチャによるものです。型シグネチャは、メソッドがObject型のオブジェクトを返すことを示しています。

protected Object clone() throws CloneNotSupportedException

コレクションは、いわゆるジェネリック型を使用して、キャストの型を自動的に置き換えます。

このコードがある場合:

List<Integer> ints = Arrays.asList(1,2,3);
int x = ints.get(0);`

コンパイラはキャストを舞台裏で追加するため、実際のコードは次のようになります。

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);

0

完全を期すために、Java 5以降、共変の戻り型が許可されています。したがって、次のように記述できます。

public MyObject implements Cloneable {
  @Override
  public MyObject clone() {
    try {
      return (MyObject)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError();
    }
  }
}

これにより、次のコードは有効です。

MyObject original = new MyObject();
MyObject clone = original.clone();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.