Permulaan kelas dan objek di Java

Kelas dan objek di Java mesti diinisialisasi sebelum digunakan. Anda sebelumnya telah mengetahui bahawa medan kelas diinisialisasi ke nilai lalai ketika kelas dimuat dan objek diinisialisasi melalui konstruktor, tetapi ada lebih banyak lagi untuk permulaan. Artikel ini memperkenalkan semua ciri Java untuk memulakan kelas dan objek.

muat turun Dapatkan kod Muat turun kod sumber misalnya aplikasi dalam tutorial ini. Dicipta oleh Jeff Friesen untuk JavaWorld.

Cara memulakan kelas Java

Sebelum kita meneroka sokongan Java untuk inisialisasi kelas, mari kita ulangi langkah-langkah untuk memulakan kelas Java. Pertimbangkan Penyenaraian 1.

Penyenaraian 1. Memulakan medan kelas ke nilai lalai

class SomeClass { static boolean b; static byte by; static char c; static double d; static float f; static int i; static long l; static short s; static String st; }

Penyenaraian 1 menyatakan kelas SomeClass. Kelas ini mengisytiharkan sembilan bidang jenis boolean, byte, char, double, float, int, long, short, dan String. Apabila SomeClassdimuat, setiap bit medan ditetapkan ke sifar, yang anda tafsirkan sebagai berikut:

false 0 \u0000 0.0 0.0 0 0 0 null

Medan kelas sebelumnya secara tidak langsung dimulakan menjadi sifar. Namun, Anda juga dapat menginisialisasi bidang kelas secara eksplisit dengan memberikan nilai secara langsung kepadanya, seperti yang ditunjukkan dalam Penyenaraian 2.

Penyenaraian 2. Memulakan medan kelas ke nilai eksplisit

class SomeClass { static boolean b = true; static byte by = 1; static char c = 'A'; static double d = 2.0; static float f = 3.0f; static int i = 4; static long l = 5000000000L; static short s = 20000; static String st = "abc"; }

Nilai setiap tugasan mestilah sesuai dengan jenis bidang kelas. Setiap pemboleh ubah menyimpan nilainya secara langsung, kecuali st. Pemboleh ubah stmenyimpan rujukan ke Stringobjek yang mengandungi abc.

Merujuk bidang kelas

Semasa memulakan medan kelas, adalah sah untuk mengisinya dengan nilai medan kelas yang sebelumnya dimulakan. Sebagai contoh, Penyenaraian 3 initializes yuntuk xnilai 's. Kedua-dua bidang diinisialisasi untuk 2.

Penyenaraian 3. Merujuk bidang yang dinyatakan sebelumnya

class SomeClass { static int x = 2; static int y = x; public static void main(String[] args) { System.out.println(x); System.out.println(y); } }

Namun, sebaliknya tidak sah: anda tidak dapat menginisialisasi medan kelas dengan nilai medan kelas yang kemudian dinyatakan. Penyusun Java akan keluar illegal forward referenceketika menghadapi senario ini. Pertimbangkan Penyenaraian 4.

Penyenaraian 4. Mencuba merujuk medan yang diisytiharkan kemudian

class SomeClass { static int x = y; static int y = 2; public static void main(String[] args) { System.out.println(x); System.out.println(y); } }

Pengkompilasi akan melaporkan illegal forward referenceketika ia bertemu static int x = y;. Ini kerana kod sumber disusun dari atas ke bawah, dan penyusun belum dapat dilihat y. (Ini juga akan mengeluarkan mesej ini jika ytidak diinisialisasi secara eksplisit.)

Blok permulaan kelas

Dalam beberapa kes, anda mungkin ingin melakukan inisialisasi berasaskan kelas yang kompleks. Anda akan melakukan ini setelah kelas dimuat dan sebelum objek dibuat dari kelas itu (dengan anggapan bahawa kelas itu bukan kelas utiliti). Anda boleh menggunakan blok inisialisasi kelas untuk tugas ini.

A blok kelas pengawalan adalah satu blok penyata didahului oleh statickata kunci yang yang diperkenalkan ke dalam badan class. Apabila kelas dimuat, pernyataan ini dilaksanakan. Pertimbangkan Penyenaraian 5.

Penyenaraian 5. Memulakan susunan nilai sinus dan kosinus

class Graphics { static double[] sines, cosines; static { sines = new double[360]; cosines = new double[360]; for (int i = 0; i < sines.length; i++) { sines[i] = Math.sin(Math.toRadians(i)); cosines[i] = Math.cos(Math.toRadians(i)); } } }

Penyenaraian 5 mengisytiharkan Graphicskelas yang menyatakan sinesdan memboleh cosinesubah pemboleh ubah. Ia juga menyatakan blok inisialisasi kelas yang membuat susunan elemen 360 yang rujukannya diberikan kepada sinesdan cosines. Ia kemudian menggunakan forpernyataan untuk menginisialisasi elemen array ini kepada nilai sinus dan kosinus yang sesuai, dengan memanggil kaedah dan kaedah Mathkelas . ( adalah sebahagian dari pustaka kelas standard Java. Saya akan membincangkan kelas ini dan kaedah ini dalam artikel yang akan datang.)sin()cos()Math

Muslihat prestasi

Oleh kerana prestasi penting untuk aplikasi grafik, dan kerana lebih cepat untuk mengakses elemen array daripada memanggil kaedah, pemaju menggunakan trik prestasi seperti membuat dan memulakan susunan sinus dan kosinus.

Menggabungkan pemula bidang kelas dan blok permulaan kelas

Anda boleh menggabungkan beberapa pemula bidang kelas dan blok inisialisasi kelas dalam aplikasi. Penyenaraian 6 memberikan contoh.

Penyenaraian 6. Melakukan inisialisasi kelas dalam urutan atas-bawah

class MCFICIB { static int x = 10; static double temp = 98.6; static { System.out.println("x = " + x); temp = (temp - 32) * 5.0/9.0; // convert to Celsius System.out.println("temp = " + temp); } static int y = x + 5; static { System.out.println("y = " + y); } public static void main(String[] args) { } }

Penyenaraian 6 menyatakan dan menginisialisasi sepasang medan kelas ( xdan y), dan menyatakan sepasang staticpemula. Susun senarai ini seperti yang ditunjukkan:

javac MCFICIB.java

Kemudian jalankan aplikasi yang dihasilkan:

java MCFICIB

Anda harus memerhatikan output berikut:

x = 10 temp = 37.0 y = 15

Output ini menunjukkan bahawa inisialisasi kelas dilakukan dalam urutan atas-bawah.

() kaedah

When compiling class initializers and class initialization blocks, the Java compiler stores the compiled bytecode (in top-down order) in a special method named (). The angle brackets prevent a name conflict: you cannot declare a () method in source code because the < and > characters are illegal in an identifier context.

After loading a class, the JVM calls this method before calling main() (when main() is present).

Let's take a look inside MCFICIB.class. The following partial disassembly reveals the stored information for the x, temp, and y fields:

Field #1 00000290 Access Flags ACC_STATIC 00000292 Name x 00000294 Descriptor I 00000296 Attributes Count 0 Field #2 00000298 Access Flags ACC_STATIC 0000029a Name temp 0000029c Descriptor D 0000029e Attributes Count 0 Field #3 000002a0 Access Flags ACC_STATIC 000002a2 Name y 000002a4 Descriptor I 000002a6 Attributes Count 0

The Descriptor line identifies the JVM's type descriptor for the field. The type is represented by a single letter: I for int and D for double.

The following partial disassembly reveals the bytecode instruction sequence for the () method. Each line starts with a decimal number that identifies the zero-based offset address of the subsequent instruction:

 0 bipush 10 2 putstatic MCFICIB/x I 5 ldc2_w #98.6 8 putstatic MCFICIB/temp D 11 getstatic java/lang/System/out Ljava/io/PrintStream; 14 new java/lang/StringBuilder 17 dup 18 invokespecial java/lang/StringBuilder/()V 21 ldc "x = " 23 invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 26 getstatic MCFICIB/x I 29 invokevirtual java/lang/StringBuilder/append(I)Ljava/lang/StringBuilder; 32 invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String; 35 invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V 38 getstatic MCFICIB/temp D 41 ldc2_w #32 44 dsub 45 ldc2_w #5 48 dmul 49 ldc2_w #9 52 ddiv 53 putstatic MCFICIB/temp D 56 getstatic java/lang/System/out Ljava/io/PrintStream; 59 new java/lang/StringBuilder 62 dup 63 invokespecial java/lang/StringBuilder/()V 66 ldc "temp = " 68 invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 71 getstatic MCFICIB/temp D 74 invokevirtual java/lang/StringBuilder/append(D)Ljava/lang/StringBuilder; 77 invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String; 80 invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V 83 getstatic MCFICIB/x I 86 iconst_5 87 iadd 88 putstatic MCFICIB/y I 91 getstatic java/lang/System/out Ljava/io/PrintStream; 94 new java/lang/StringBuilder 97 dup 98 invokespecial java/lang/StringBuilder/()V 101 ldc "y = " 103 invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 106 getstatic MCFICIB/y I 109 invokevirtual java/lang/StringBuilder/append(I)Ljava/lang/StringBuilder; 112 invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String; 115 invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V 118 return

The instruction sequence from offset 0 through offset 2 is equivalent to the following class field initializer:

static int x = 10;

The instruction sequence from offset 5 through offset 8 is equivalent to the following class field initializer:

static double temp = 98.6;

The instruction sequence from offset 11 through offset 80 is equivalent to the following class initialization block:

static { System.out.println("x = " + x); temp = (temp - 32) * 5.0/9.0; // convert to Celsius System.out.println("temp = " + temp); }

The instruction sequence from offset 83 through offset 88 is equivalent to the following class field initializer:

static int y = x + 5;

The instruction sequence from offset 91 through offset 115 is equivalent to the following class initialization block:

static { System.out.println("y = " + y); }

Finally, the return instruction at offset 118 returns execution from () to that part of the JVM that called this method.

Don't worry about what the bytecode means

The takeaway from this exercise is to see that all code in Listing 6's class field initializers and class initialization blocks is located in the () method, and is executed in top-down order.

How to initialize objects

After a class has been loaded and initialized, you'll often want to create objects from the class. As you learned in my recent introduction to programming with classes and objects, you initialize an object via the code that you place in a class's constructor. Consider Listing 7.

Listing 7. Using the constructor to initialize an object

class City { private String name; int population; City(String name, int population) { this.name = name; this.population = population; } @Override public String toString() { return name + ": " + population; } public static void main(String[] args) { City newYork = new City("New York", 8491079); System.out.println(newYork); // Output: New York: 8491079 } }

Listing 7 declares a City class with name and population fields. When a City object is created, the City(String name, int population) constructor is called to initialize these fields to the called constructor's arguments. (I've also overridden Object's public String toString() method to conveniently return the city name and population value as a string. System.out.println() ultimately calls this method to return the object's string representation, which it outputs.)

Before the constructor is called, what values do name and population contain? You can find out by inserting System.out.println(this.name); System.out.println(this.population); at the start of the constructor. After compiling the source code (javac City.java) and running the application (java City), you would observe null for name and 0 for population. The new operator zeroes an object's object (instance) fields before executing a constructor.

Seperti medan kelas, anda boleh mengeksplisit bidang objek secara jelas. Sebagai contoh, anda boleh menentukan String name = "New York";atau int population = 8491079;. Walau bagaimanapun, biasanya tidak ada yang dapat diperoleh dengan melakukan ini, kerana bidang ini akan diinisialisasi dalam konstruktor. Satu-satunya faedah yang dapat saya fikirkan ialah memberikan nilai lalai ke medan objek; nilai ini digunakan apabila anda memanggil konstruktor yang tidak memulakan bidang:

int numDoors = 4; // default value assigned to numDoors Car(String make, String model, int year) { this(make, model, year, numDoors); } Car(String make, String model, int year, int numDoors) { this.make = make; this.model = model; this.year = year; this.numDoors = numDoors; }

Permulaan objek mencerminkan permulaan kelas