Setelah diajari selama hari-hari C ++ saya tentang kejahatan operator cor gaya-C, saya senang pada awalnya menemukan bahwa di Java 5 java.lang.Class
telah memperoleh cast
metode.
Saya pikir akhirnya kami memiliki cara OO untuk menangani casting.
Ternyata Class.cast
tidak sama dengan static_cast
di C ++. Ini lebih seperti reinterpret_cast
. Ini tidak akan menghasilkan kesalahan kompilasi seperti yang diharapkan dan sebagai gantinya akan menunda waktu proses. Berikut adalah kasus pengujian sederhana untuk menunjukkan perilaku yang berbeda.
package test;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class TestCast
{
static final class Foo
{
}
static class Bar
{
}
static final class BarSubclass
extends Bar
{
}
@Test
public void test ( )
{
final Foo foo = new Foo( );
final Bar bar = new Bar( );
final BarSubclass bar_subclass = new BarSubclass( );
{
final Bar bar_ref = bar;
}
{
// Compilation error
final Bar bar_ref = foo;
}
{
// Compilation error
final Bar bar_ref = (Bar) foo;
}
try
{
// !!! Compiles fine, runtime exception
Bar.class.cast( foo );
}
catch ( final ClassCastException ex )
{
assertTrue( true );
}
{
final Bar bar_ref = bar_subclass;
}
try
{
// Compiles fine, runtime exception, equivalent of C++ dynamic_cast
final BarSubclass bar_subclass_ref = (BarSubclass) bar;
}
catch ( final ClassCastException ex )
{
assertTrue( true );
}
}
}
Jadi, inilah pertanyaan saya.
- Haruskah
Class.cast()
dibuang ke tanah Generik? Di sana ia memiliki beberapa kegunaan yang sah. - Haruskah kompiler menghasilkan kesalahan kompilasi saat
Class.cast()
digunakan dan kondisi ilegal dapat ditentukan pada waktu kompilasi? - Haruskah Java menyediakan operator cast sebagai konstruksi bahasa yang mirip dengan C ++?
java
generics
casting
compiler-warnings
Alexander Pogrebnyak
sumber
sumber
Class.cast()
ketika kondisi ilegal dapat ditentukan pada waktu kompilasi. Dalam hal ini, semua orang kecuali Anda hanya menggunakan operator transmisi standar. (3) Java memang memiliki operator cast sebagai konstruksi bahasa. Ini tidak mirip dengan C ++. Itu karena banyak konstruksi bahasa Java tidak mirip dengan C ++. Terlepas dari kemiripan yang dangkal, Java dan C ++ sangat berbeda.Jawaban:
Saya hanya pernah
Class.cast(Object)
menghindari peringatan di "tanah generik". Saya sering melihat metode melakukan hal-hal seperti ini:Seringkali yang terbaik adalah menggantinya dengan:
Itulah satu-satunya kasus penggunaan yang
Class.cast(Object)
pernah saya temui.Mengenai peringatan kompilator: Saya menduga itu
Class.cast(Object)
tidak khusus untuk kompilator. Ini dapat dioptimalkan ketika digunakan secara statis (yaituFoo.class.cast(o)
daripadacls.cast(o)
) tetapi saya belum pernah melihat ada orang yang menggunakannya - yang membuat upaya membangun pengoptimalan ini ke dalam kompiler agak tidak berguna.sumber
Pertama, Anda sangat tidak disarankan untuk melakukan hampir semua pemeran, jadi Anda harus membatasinya sebanyak mungkin! Anda kehilangan keuntungan dari fitur waktu kompilasi Java yang sangat diketik.
Bagaimanapun,
Class.cast()
harus digunakan terutama saat Anda mengambilClass
token melalui refleksi. Menulis itu lebih idiomatisdaripada
EDIT: Kesalahan pada waktu kompilasi
Secara keseluruhan, Java melakukan pemeriksaan cast hanya pada waktu proses. Namun, kompilator dapat mengeluarkan kesalahan jika ia dapat membuktikan bahwa transmisi tersebut tidak akan pernah berhasil (mis. Mentransmisikan kelas ke kelas lain yang bukan supertipe dan mentransmisikan tipe kelas akhir ke kelas / antarmuka yang tidak ada dalam hierarki tipenya). Di sini karena
Foo
danBar
merupakan kelas yang tidak berada dalam hierarki satu sama lain, pemeran tidak akan pernah berhasil.sumber
Class.cast
tampaknya sesuai dengan tagihan, hal itu menciptakan lebih banyak masalah daripada menyelesaikannya.Selalu bermasalah dan sering menyesatkan untuk mencoba menerjemahkan konstruksi dan konsep antar bahasa. Transmisi tidak terkecuali. Terutama karena Java adalah bahasa dinamis dan C ++ agak berbeda.
Semua casting di Java, tidak peduli bagaimana Anda melakukannya, dilakukan saat runtime. Jenis informasi disimpan saat runtime. C ++ lebih merupakan campuran. Anda dapat mentransmisikan struct di C ++ ke yang lain dan itu hanyalah interpretasi ulang dari byte yang mewakili struct tersebut. Java tidak bekerja seperti itu.
Juga generik di Java dan C ++ sangat berbeda. Jangan terlalu memikirkan cara Anda melakukan C ++ di Java. Anda perlu mempelajari cara melakukan berbagai hal dengan cara Java.
sumber
(Bar) foo
memang menghasilkan kesalahan pada waktu kompilasi, tetapiBar.class.cast(foo)
tidak. Menurut saya jika digunakan dengan cara seperti ini seharusnya.Bar.class.cast(foo)
secara eksplisit memberi tahu compiler bahwa Anda ingin melakukan cast saat runtime. Jika Anda ingin waktu kompilasi memeriksa validitas cast, satu-satunya pilihan Anda adalah melakukan(Bar) foo
style cast.Class.cast()
jarang digunakan dalam kode Java. Jika digunakan maka biasanya dengan tipe yang hanya diketahui saat runtime (mis. Melalui masing-masingClass
objek dan oleh beberapa parameter tipe). Ini hanya sangat berguna dalam kode yang menggunakan obat generik (itu juga alasan mengapa tidak diperkenalkan sebelumnya).Ini tidak mirip dengan
reinterpret_cast
, karena ini tidak akan memungkinkan Anda untuk merusak sistem tipe pada saat runtime lebih dari yang dilakukan cast normal (yaitu Anda dapat merusak parameter tipe generik, tetapi tidak dapat merusak tipe "nyata").Kejahatan operator cor gaya-C umumnya tidak berlaku untuk Java. Kode Java yang terlihat seperti cor gaya-C paling mirip dengan file
dynamic_cast<>()
dengan tipe referensi di Java (ingat: Java memiliki informasi tipe runtime).Umumnya membandingkan operator casting C ++ dengan casting Java cukup sulit karena di Java Anda hanya dapat memberikan referensi dan tidak ada konversi yang pernah terjadi pada objek (hanya nilai primitif yang dapat dikonversi menggunakan sintaks ini).
sumber
dynamic_cast<>()
dengan tipe referensi.Umumnya operator cor lebih disukai daripada metode cor Kelas # karena lebih ringkas dan dapat dianalisis oleh kompiler untuk mengeluarkan masalah mencolok dengan kode.
Class # cast bertanggung jawab untuk pemeriksaan tipe pada saat run-time daripada selama kompilasi.
Tentu ada kasus penggunaan untuk cast Kelas #, terutama dalam hal operasi reflektif.
Sejak lambda datang ke java, saya pribadi suka menggunakan Class # cast dengan API koleksi / aliran jika saya bekerja dengan tipe abstrak, misalnya.
sumber
C ++ dan Java adalah bahasa yang berbeda.
Operator cast gaya-C Java jauh lebih terbatas daripada versi C / C ++. Secara efektif cast Java seperti C ++ dynamic_cast jika objek yang Anda miliki tidak dapat ditransmisikan ke kelas baru, Anda akan mendapatkan pengecualian waktu proses (atau jika ada cukup informasi dalam kode untuk waktu kompilasi). Jadi ide C ++ untuk tidak menggunakan cast tipe C bukanlah ide yang bagus di Java
sumber
Selain untuk menghapus peringatan cast jelek seperti yang paling banyak disebutkan, Class.cast adalah cast run-time yang sebagian besar digunakan dengan casting generik, karena info generik akan dihapus pada saat run time dan beberapa bagaimana setiap generik akan dianggap Object, ini mengarah ke tidak melempar ClassCastException awal.
misalnya serviceLoder menggunakan trik ini saat membuat objek, centang S p = service.cast (c.newInstance ()); ini akan memunculkan eksepsi cast kelas ketika SP = (S) c.newInstance (); tidak akan dan mungkin menampilkan peringatan 'Type safety: Unchecked cast from Object to S' . (sama seperti Object P = (Object) c.newInstance ();)
-sederhana itu memeriksa bahwa objek yang dicor adalah turunan dari kelas pengecoran kemudian itu akan menggunakan operator cor untuk melemparkan dan menyembunyikan peringatan dengan menekannya.
implementasi java untuk cast dinamis:
sumber
Secara pribadi, saya telah menggunakan ini sebelumnya untuk membangun konverter JSON ke POJO. Jika JSONObject diproses dengan fungsi berisi larik atau JSONObjects bersarang (menyiratkan bahwa data di sini bukan dari tipe primitif atau
String
), saya mencoba untuk memanggil metode penyetel menggunakanclass.cast()
cara ini:Tidak yakin apakah ini sangat membantu, tetapi seperti yang dikatakan di sini sebelumnya, refleksi adalah salah satu dari sedikit kasus penggunaan sah yang
class.cast()
dapat saya pikirkan, setidaknya Anda memiliki contoh lain sekarang.sumber