Hi! Ayo dadi pirembagan bab jinis liyane nested kelas. Aku ngomong babagan kelas lokal (kelas batin metode-lokal). Sadurunge nyilem, kita kudu ngelingi panggonane ing struktur kelas nested.
Saka diagram kita, kita bisa ndeleng manawa kelas lokal minangka subspesies saka kelas njero, sing wis dibahas kanthi rinci ing materi sadurunge . Nanging, kelas lokal duwe sawetara fitur penting lan beda saka kelas batin biasa. Ingkang utama yaiku ing deklarasi: Kelas lokal diumumake mung ing blok kode. Paling asring, deklarasi iki ana ing sawetara metode kelas njaba. Contone, bisa uga katon kaya iki:

public class PhoneNumberValidator {
public void validatePhoneNumber(String number) {
class PhoneNumber {
private String phoneNumber;
public PhoneNumber() {
this.phoneNumber = number;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
// ...number validation code
}
}
PENTING!Yen sampeyan wis nginstal Java 7, kode iki ora bakal dikompilasi nalika ditempelake menyang IDEA. Kita bakal ngomong babagan alasan iki ing pungkasan pelajaran. Singkatipun, cara kerja kelas lokal gumantung banget marang versi basa kasebut. Yen kode iki ora kompilasi kanggo sampeyan, sampeyan bisa ngganti versi basa ing IDEA kanggo Java 8, utawa nambah tembung final
kanggo parameter cara supaya katon kaya iki validatePhoneNumber(final String number)
:. Sawise iku, kabeh bakal bisa. Iki minangka program cilik sing validasi nomer telpon. Cara kasebut validatePhoneNumber()
njupuk senar minangka input lan nemtokake manawa iku nomer telpon. Lan ing cara iki, kita ngumumake PhoneNumber
kelas lokal kita. Sampeyan bisa uga takon apa sebabe. Yagene persis kita bakal ngumumake kelas ing sawijining metode? Apa ora nggunakake kelas batin biasa? Bener, kita bisa nggawePhoneNumber
kelas lan kelas batin. Nanging solusi pungkasan gumantung saka struktur lan tujuan program sampeyan. Ayo kelingan conto saka pawulangan babagan kelas batin:
public class Bicycle {
private String model;
private int maxWeight;
public Bicycle(String model, int maxWeight) {
this.model = model;
this.maxWeight = maxWeight;
}
public void start() {
System.out.println("Let's go!");
}
public class HandleBar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left!");
}
}
}
Ing kono, kita nggawe HandleBar
kelas jero sepeda. Apa bedane? Kaping pisanan, cara kelas digunakake beda. Kelas HandleBar
ing conto kapindho minangka entitas sing luwih rumit tinimbang PhoneNumber
kelas ing conto pisanan. Pisanan, HandleBar
duwe umum right
lan left
metode (iki dudu setter / getters). Kapindho, iku mokal kanggo prédhiksi ing advance ngendi kita perlu lan Bicycle
kelas njaba sawijining. Bisa uga ana puluhan panggonan lan cara sing beda-beda, sanajan ing program siji. Nanging kanthi PhoneNumber
kelas, kabeh luwih gampang. Program kita prasaja banget. Wis mung siji waé: kanggo mriksa apa nomer iku nomer telpon bener. Ing kasus paling, kitaPhoneNumberValidator
malah ora bakal dadi program dewekan, nanging rodo bagéan saka logika wewenang kanggo program luwih gedhe. Contone, macem-macem situs web asring njaluk nomer telpon nalika pangguna ndhaptar. Yen sampeyan ngetik sawetara omong kosong tinimbang nomer, situs web bakal nglaporake kesalahan: "Iki dudu nomer telpon!" Pangembang situs web kasebut (utawa, mekanisme wewenang pangguna) bisa uga kalebu sing padha karo kitaPhoneNumberValidator
ing kode sing. Ing tembung liyane, kita duwe siji kelas njaba karo siji cara, kang bakal digunakake ing sak panggonan ing program lan ora liya. Lan yen digunakake, mula ora ana sing bakal diganti: siji cara nindakake tugase - lan iku. Ing kasus iki, amarga kabeh logika diklumpukake dadi siji cara, iku bakal luwih trep lan tepat kanggo encapsulate kelas tambahan ana. Ora ana cara dhewe kajaba getter lan setter. Ing kasunyatan, kita mung butuh data saka konstruktor. Iku ora melu ing cara liyane. Mulane, ora ana alesan kanggo njupuk informasi babagan iki ing njaba mung cara sing digunakake. Kita uga menehi conto ing ngendi kelas lokal diumumake kanthi cara, nanging iki ora mung siji-sijine pilihan. Bisa diumumake mung ing blok kode:
public class PhoneNumberValidator {
{
class PhoneNumber {
private String phoneNumber;
public PhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
}
public void validatePhoneNumber(String phoneNumber) {
// ...number validation code
}
}
Utawa malah ing for
daur ulang!
public class PhoneNumberValidator {
public void validatePhoneNumber(String phoneNumber) {
for (int i = 0; i < 10; i++) {
class PhoneNumber {
private String phoneNumber;
public PhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
// ...some logic
}
// ...number validation code
}
}
Nanging kasus kaya mengkono arang banget. Umume kasus, deklarasi bakal kedadeyan ing metode kasebut. Dadi, kita nemtokake deklarasi, lan kita uga ngomong babagan "filsafat" :) Apa fitur tambahan lan bedane kelas lokal dibandhingake karo kelas batin? Objek saka kelas lokal ora bisa digawe ing njaba metode utawa blok sing diumumake. Mbayangno yen kita butuh generatePhoneNumber()
cara sing bakal ngasilake nomer telpon acak lan ngasilake PhoneNumber
obyek. Ing kahanan saiki, kita ora bisa nggawe metode kasebut ing kelas validator:
public class PhoneNumberValidator {
public void validatePhoneNumber(String number) {
class PhoneNumber {
private String phoneNumber;
public PhoneNumber() {
this.phoneNumber = number;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
// ...number validation code
}
// Error! The compiler does not recognize the PhoneNumber class
public PhoneNumber generatePhoneNumber() {
}
}
Fitur penting liyane saka kelas lokal yaiku kemampuan kanggo ngakses variabel lokal lan paramèter metode. Yen sampeyan lali, variabel sing diumumake ing sawijining metode dikenal minangka variabel "lokal". Yaiku, yen kita nggawe String usCountryCode
variabel lokal ing validatePhoneNumber()
metode sawetara alasan, kita bisa ngakses saka PhoneNumber
kelas lokal. Nanging, ana akeh subtleties sing gumantung saka versi basa sing digunakake ing program kasebut. Ing wiwitan pawulangan, kita nyathet yen kode kanggo salah sawijining conto bisa uga ora dikompilasi ing Jawa 7, elinga? Saiki ayo nimbang alasan kanggo iki :) Ing Jawa 7, kelas lokal bisa ngakses variabel lokal utawa parameter metode mung yen diumumake kaya final
ing metode:
public void validatePhoneNumber(String number) {
String usCountryCode = "+1";
class PhoneNumber {
private String phoneNumber;
// Error! The method parameter must be declared as final!
public PhoneNumber() {
this.phoneNumber = number;
}
public void printUsCountryCode() {
// Error! The local variable must be declared as final!
System.out.println(usCountryCode);
}
}
// ...number validation code
}
Ing kene compiler ngasilake loro kesalahan. Lan kabeh ana ing kene:
public void validatePhoneNumber(final String number) {
final String usCountryCode = "+1";
class PhoneNumber {
private String phoneNumber;
public PhoneNumber() {
this.phoneNumber = number;
}
public void printUsCountryCode() {
System.out.println(usCountryCode);
}
}
// ...number validation code
}
Saiki sampeyan ngerti kenapa kode saka wiwitan pawulangan ora bakal dikompilasi: ing Jawa 7, kelas lokal mung nduweni akses menyang final
parameter metode lan final
variabel lokal. Ing Jawa 8, solah bawane kelas lokal wis owah. Ing versi basa iki, kelas lokal nduweni akses ora mung menyang final
variabel lan parameter lokal, nanging uga kanggo sing effective-final
. Effective-final
yaiku variabel sing nilaine ora owah wiwit wiwitan. Contone, ing Jawa 8, kita bisa kanthi gampang nampilake usCountryCode
variabel ing console, sanajan ora final
. Sing penting regane ora owah. Ing conto ing ngisor iki, kabeh bisa digunakake kaya sing dikarepake:
public void validatePhoneNumber(String number) {
String usCountryCode = "+1";
class PhoneNumber {
public void printUsCountryCode() {
// Java 7 would produce an error here
System.out.println(usCountryCode);
}
}
// ...number validation code
}
Nanging yen kita ngganti nilai variabel sanalika sawise initialization, kode ora bakal kompilasi.
public void validatePhoneNumber(String number) {
String usCountryCode = "+1";
usCountryCode = "+8";
class PhoneNumber {
public void printUsCountryCode() {
// Error!
System.out.println(usCountryCode);
}
}
// ...number validation code
}
Ora ana wonder yen kelas lokal minangka subspesies saka konsep kelas batin! Dheweke uga duwe ciri umum. Kelas lokal nduweni akses menyang kabeh (malah pribadi) lapangan lan cara saka kelas njaba: loro statis lan non-statis. Contone, ayo nambah String phoneNumberRegex
kolom statis menyang kelas validator:
public class PhoneNumberValidator {
private static String phoneNumberRegex = "[^0-9]";
public void validatePhoneNumber(String phoneNumber) {
class PhoneNumber {
// ......
}
}
}
Validasi bakal ditindakake nggunakake variabel statis iki. Cara mriksa yen string liwati ngemot karakter sing ora cocog karo ekspresi reguler " [^0-9]
" (yaiku karakter apa wae sing dudu digit saka 0 nganti 9). Kita bisa kanthi gampang ngakses variabel iki saka PhoneNumber
kelas lokal. Contone, nulis getter:
public String getPhoneNumberRegex() {
return phoneNumberRegex;
}
Kelas lokal padha karo kelas njero, amarga ora bisa nemtokake utawa nyatakake anggota statis. Kelas lokal ing cara statis mung bisa ngrujuk anggota statis saka kelas enclosing. Contone, yen sampeyan ora nemtokake variabel (bidang) saka kelas enclosing minangka statis, compiler Java ngasilake kesalahan: "Variabel non-statis ora bisa dirujuk saka konteks statis." Kelas lokal ora statis, amarga padha duwe akses kanggo anggota Kayata ing pemblokiran enclosing. Akibaté, padha ora bisa ngemot paling jinis deklarasi statis. Sampeyan ora bisa ngumumake antarmuka ing blok: antarmuka pancen statis. Kode iki ora kompilasi:
public class PhoneNumberValidator {
public static void validatePhoneNumber(String number) {
interface I {}
class PhoneNumber implements I{
private String phoneNumber;
public PhoneNumber() {
this.phoneNumber = number;
}
}
// ...number validation code
}
}
Nanging yen antarmuka diumumake ing njero kelas njaba, PhoneNumber
kelas kasebut bisa ngetrapake:
public class PhoneNumberValidator {
interface I {}
public static void validatePhoneNumber(String number) {
class PhoneNumber implements I{
private String phoneNumber;
public PhoneNumber() {
this.phoneNumber = number;
}
}
// ...number validation code
}
}
Inisialisasi statis (pamblokiran wiwitan) utawa antarmuka ora bisa diumumake ing kelas lokal. Nanging kelas lokal bisa duwe anggota statis, kasedhiya sing variabel pancet ( static final
). Lan saiki sampeyan ngerti babagan kelas lokal, wong! Nalika sampeyan bisa ndeleng, padha duwe akeh beda saka kelas utama biasa. Kita malah kudu delve menyang fitur saka versi tartamtu saka basa supaya ngerti carane padha bisa digunakake :) Ing pawulangan sabanjuré, kita bakal pirembagan bab kelas njero anonim — klompok pungkasan nested kelas. Good luck ing pasinaon! :)
GO TO FULL VERSION