Programmēšana

Kā lietot Java drošus uzrakstus

Java kods, kas izmanto tradicionālos uzskaitītos veidus, ir problemātisks. Java 5 deva mums labāku alternatīvu veidu drukāto uzrakstu veidā. Šajā rakstā es jūs iepazīstinu ar uzskaitītajiem tipiem un tipofe uzskaitījumiem, parādīšu, kā pasludināt typefe enum un izmantot to switch paziņojumā, kā arī apspriest typeafe enum pielāgošanu, pievienojot datus un uzvedību. Es iesaiņoju rakstu, izpētot java.lang.Enum klasē.

lejupielādēt Iegūt kodu Lejupielādējiet avota kodu piemēriem šajā Java 101 apmācībā. Izveidoja Jeff Friesen JavaWorld /.

Sākot no uzskaitītajiem tipiem un beidzot ar tipafe

An uzskaitītais tips kā vērtības norāda saistīto konstantu kopu. Piemēri ietver dienu nedēļu, standarta ziemeļu / dienvidu / austrumu / rietumu kompasa virzienus, valūtas monētu nominālvērtības un leksiskā analizatora žetonu veidus.

Uzskaitītie tipi tradicionāli tiek ieviesti kā veselu skaitļu konstantu sekvences, ko pierāda šāda virziena konstante:

statiskā gala int DIR_NORTH = 0; statiskais gala int DIR_WEST = 1; statiskais gala int DIR_EAST = 2; statiskais gala int DIR_SOUTH = 3;

Šai pieejai ir vairākas problēmas:

  • Tipa drošības trūkums: Tā kā uzskaitītā tipa konstante ir tikai vesels skaitlis, jebkuru skaitli var norādīt, kur konstante ir nepieciešama. Turklāt šīm konstantēm var veikt saskaitīšanas, atņemšanas un citas matemātikas darbības; piemēram, (DIR_NORTH + DIR_EAST) / DIR_SOUTH), kas ir bezjēdzīgi.
  • Vārdvietas nav: Uzskaitīta tipa konstantēm jābūt prefiksiem ar sava veida (cerams) unikālu identifikatoru (piem., DIR_), lai novērstu sadursmes ar cita uzskaitītā tipa konstantēm.
  • Trauslums: Tā kā uzskaitītās tipa konstantes tiek apkopotas klases failos, kur to burtiskās vērtības tiek glabātas (nemainīgos baseinos), mainot konstantes vērtību, šie klases faili un no tiem atkarīgie lietojumprogrammu klases faili ir jāatjauno. Pretējā gadījumā nedefinēta uzvedība notiks izpildlaikā.
  • Informācijas trūkums: Kad tiek izdrukāta konstante, tiek izvadīta tās veselā skaitļa vērtība. Šis izvade jums neko nepasaka par to, ko apzīmē vesela skaitļa vērtība. Tas pat nenosaka uzskaitīto tipu, kuram pieder konstante.

Izmantojot, jūs varētu izvairīties no “tipa drošības trūkuma” un “informācijas trūkuma” problēmām java.lang.Strings konstantes. Piemēram, jūs varat norādīt statiskā galīgā virkne DIR_NORTH = "NORTH";. Lai gan nemainīgā vērtība ir nozīmīgāka, Stīgakonstantes joprojām cieš no “vārda vietas nav” un trausluma problēmām. Tāpat atšķirībā no veselu skaitļu salīdzinājumiem, virknes vērtības nevar salīdzināt ar == un != operatori (kuri salīdzina tikai atsauces).

Šīs problēmas lika izstrādātājiem izgudrot uz klasēm balstītu alternatīvu, kas pazīstama kā Typesafe Enum. Šis modelis ir plaši aprakstīts un kritizēts. Džošua Blohs ieviesa paraugu sava 21. punktā Efektīva Java programmēšanas valodas rokasgrāmata (Addison-Wesley, 2001) un atzīmēja, ka tam ir dažas problēmas; proti, ka ir neērti apkopot typeafe enum konstantes kopās un ka uzskaites konstantes nevar izmantot slēdzis paziņojumi.

Apsveriet šādu tipsafe enum modeļa piemēru. The Uzvalks klase parāda, kā jūs varētu izmantot klases alternatīvu, lai ieviestu uzskaitītu veidu, kas raksturo četrus kāršu uzvalkus (nūjas, dimantus, sirdis un lāpstas):

public final class Suit // Nevajadzētu spēt apakšklasē Suit. {public static final Suit CLUBS = jauns uzvalks (); public static final Suit DIAMONDS = new Uzvalks (); public static final Suit HEARTS = new Uzvalks (); public static final Suit SPADES = new Uzvalks (); privāts uzvalks () {} // nevajadzētu būt iespējai ieviest papildu konstantes. }

Lai izmantotu šo klasi, jūs ieviestu a Uzvalks mainīgo un piešķir to vienam no UzvalksŠādas konstantes:

Uzvalka uzvalks = Uzvalks.DIAMONDS;

Tad jūs varētu vēlēties nopratināt uzvalks iekšā slēdzis šāds paziņojums:

slēdzis (uzvalks) {gadījums Suit.CLUBS: System.out.println ("klubi"); pārtraukums; korpuss Suit.DIAMONDS: System.out.println ("dimanti"); pārtraukums; lieta Suit.HEARTS: System.out.println ("sirdis"); pārtraukums; korpuss Suit.SPADES: System.out.println ("lāpstas"); }

Tomēr, kad Java kompilators sastopas Uzvalks. KLUBI, tā ziņo par kļūdu, norādot, ka ir nepieciešama pastāvīga izteiksme. Jūs varētu mēģināt risināt problēmu šādi:

slēdzis (uzvalks) {case CLUBS: System.out.println ("klubi"); pārtraukums; korpuss DIAMONDI: System.out.println ("dimanti"); pārtraukums; gadījums SIRDS: System.out.println ("sirdis"); pārtraukums; gadījums SPADES: System.out.println ("lāpstas"); }

Tomēr, kad sastādītājs sastopas KLUBI, tā ziņos par kļūdu, norādot, ka tā nevarēja atrast simbolu. Un pat ja jūs ievietojat Uzvalks paketē, importēja paketi un statiski importēja šīs konstantes, kompilators sūdzas, ka nevar pārveidot Uzvalks uz int sastopoties uzvalks iekšā slēdzis (uzvalks). Attiecībā uz katru gadījumā, sastādītājs arī ziņo, ka ir nepieciešama pastāvīga izteiksme.

Java neatbalsta tipu Typesafe Enum ar slēdzis paziņojumi. Tomēr tas tomēr ieviesa typesafe enum valodas iezīme, lai apkopotu modeļa priekšrocības, vienlaikus risinot tā problēmas, un šī funkcija atbalsta slēdzis.

Deklarējot typeafe enum un izmantojot to switch paziņojumā

Vienkārša Java koda tipsafe enum deklarācija izskatās kā tās kolēģi C, C ++ un C # valodās:

enum Virziens {NORTH, WEST, EAST, SOUTH}

Šajā deklarācijā tiek izmantots atslēgvārds enum iepazīstināt Virziens kā typeafe enum (īpaša veida klase), kurā var pievienot patvaļīgas metodes un ieviest patvaļīgas saskarnes. The ZIEMEĻA, RIETUMI, AUSTRUMI, un DIENVIDIenum konstantes tiek ieviesti kā nemainīgām specifiskām klases struktūrām, kas nosaka anonīmās klases, paplašinot norobežojošo Virziens klasē.

Virziens un citu veidu seifu saraksti paplašinās Enum un pārmantot dažādas metodes, ieskaitot vērtības (), toString (), un Salīdzinot ar(), no šīs klases. Mēs izpētīsim Enum vēlāk šajā rakstā.

1. saraksts deklarē iepriekšminēto uzskaitījumu un izmanto to a slēdzis paziņojums, apgalvojums. Tas arī parāda, kā salīdzināt divas uzskaites konstantes, lai noteiktu, kura konstante nāk pirms citas konstantas.

1. saraksts: TEDemo.java (1. versija)

public class TEDemo {enum Direction {NORTH, WEST, EAST, SOUTH} public static void main (String [] args) {for (int i = 0; i <Direction.values ​​(). length; i ++) {Direction d = Direction .vērtības () [i]; System.out.println (d); slēdzis (d) {gadījums NORTH: System.out.println ("Pārvietoties uz ziemeļiem"); pārtraukums; gadījums WEST: System.out.println ("Pārvietoties uz rietumiem"); pārtraukums; gadījums EAST: System.out.println ("Pārvietoties uz austrumiem"); pārtraukums; gadījums SOUTH: System.out.println ("Pārvietoties uz dienvidiem"); pārtraukums; noklusējums: apgalvot nepatiesu: "nezināms virziens"; }} System.out.println (Direction.NORTH.compareTo (Direction.SOUTH)); }}

1. saraksts deklarē Virziens tipsafe enum un atkārto savus pastāvīgos locekļus, kas vērtības () atgriežas. Katrai vērtībai slēdzis paziņojums (uzlabots, lai atbalstītu tipafe enums) izvēlas gadījumā kas atbilstd un izdod atbilstošu ziņojumu. (Jums nav prefiksa enum konstante, piem., ZIEMEĻA, ar tā uzskaites veidu.) Visbeidzot, 1. sarakstā tiek novērtēts Direction.NORTH.compareTo (Direction.SOUTH) lai noteiktu, vai ZIEMEĻA nāk pirms DIENVIDI.

Apkopojiet avota kodu šādi:

javac TEDemo.java

Palaidiet apkopoto lietojumprogrammu šādi:

java TEDemo

Jums jāievēro šāda izeja:

ZIEMEĻI Pārvietojieties uz ziemeļiem uz rietumiem Pārvietojieties uz rietumiem EAST Pārvietojieties uz austrumiem DAUDZ virzieties uz dienvidiem -3

Rezultāts atklāj, ka mantots toString () metode atgriež uzskaites konstantes nosaukumu un to ZIEMEĻA nāk pirms DIENVIDI salīdzinot šīs enum konstantes.

Datu un uzvedības pievienošana tipafe enum

Datus (lauku veidā) un uzvedību (metožu veidā) jūs varat pievienot tipafe sarakstam. Piemēram, pieņemsim, ka jums ir jāievada Kanādas monētu uzskaite un ka šai klasei ir jānodrošina līdzekļi, lai atgrieztu niķeļu, dimeju, ceturtdaļu vai dolāru skaitu patvaļīgā pensu skaitā. 2. saraksts parāda, kā izpildīt šo uzdevumu.

2. saraksts: TEDemo.java (2. versija)

enum Monēta {NICKEL (5), // konstantēm vispirms jāparādās DIME (10), QUARTER (25), DOLLAR (100); // semikols ir nepieciešams private final int valueInPennies; Monēta (int valueInPennies) {this.valueInPennies = valueInPennies; } int toCoins (int pennies) {return pennies / valueInPennies; }} public class TEDemo {public static void main (String [] args) {if (args.length! = 1) {System.err.println ("lietojums: java TEDemo summaInPennies"); atgriešanās; } int santīmi = Integer.parseInt (args [0]); par (int i = 0; i <Monētu vērtības (). garums; i ++) System.out.println (santīmi + "santīmos ir" + Monētas.vērtības () [i] .toCoins (santīmus) + "" + Monēta .values ​​() [i] .toString (). toLowerCase () + "s"); }}

2. saraksts vispirms deklarē a Monēta enum. Parametrētu konstantu sarakstā ir identificēti četri monētu veidi. Katrai konstantei nodotais arguments norāda monētu pārstāvēto santīmu skaitu.

Katrai konstantei nodotais arguments faktiski tiek nodots Monēta (int valueInPennies) konstruktors, kas saglabā argumentu vērtībasInPennies instances lauks. Šim mainīgajam var piekļūt no monētas () instances metode. Tas tiek sadalīts pensu skaitā, kas nodoti toCoin ()’S santīmus parametrs, un šī metode atgriež rezultātu, kas, iespējams, ir monētu skaits naudas nominālvērtībā, ko apraksta Monēta nemainīgs.

Šajā brīdī jūs esat atklājis, ka jūs varat deklarēt eksemplāru laukus, konstruktorus un instanču metodes tipa drukas sarakstā. Galu galā, typeafe enum būtībā ir īpašs Java klases veids.

The TEDemo klases galvenais () metode vispirms pārbauda, ​​vai ir norādīts viens komandrindas arguments. Šis arguments tiek pārveidots par veselu skaitli, izsaucot java.lang.Integer klases parseInt () metodi, kas parsē virknes argumenta vērtību veselā skaitlī (vai izmet izņēmumu, ja tiek konstatēta nederīga ievade). Man būs vairāk ko teikt Vesels skaitlis un tās brālēnu klases nākotnē Java 101 rakstu.

Virzīties uz priekšu, galvenais () atkārtojas MonētaKonstantes. Tā kā šīs konstantes tiek glabātas a Monēta [] masīvs, galvenais () novērtē Monēta.vērtības (). Garums lai noteiktu šī masīva garumu. Katrai cilpas indeksa iterācijai i, galvenais () novērtē Monētu vērtības () [i] lai piekļūtu Monēta nemainīgs. Tas atsaucas uz katru no monētas () un toString () uz šīs konstantes, kas to vēl vairāk pierāda Monēta ir īpaša klases klase.

Apkopojiet avota kodu šādi:

javac TEDemo.java

Palaidiet apkopoto lietojumprogrammu šādi:

java TEDemo 198

Jums jāievēro šāda izeja:

198 pennies satur 39 niķeļus. 198 pennies satur 19 dimes. 198 pennies satur 7 ceturtdaļas. 198 pennies satur 1 dolāru

Izpētīt Enum klasē

Java kompilators apsver enum lai tas būtu sintaktiskais cukurs. Sastopoties ar typeafe enum deklarāciju, tā ģenerē klasi, kuras nosaukums ir norādīts deklarācijā. Šajā klasē apakšklase ir abstrakta Enum klase, kas kalpo kā bāzes klase visu veidu seifiem.

EnumFormālais parametru saraksts izskatās šausmīgi, taču to nav tik grūti saprast. Piemēram, kontekstā Monēta pagarina Enum, jūs šo oficiālo tipu parametru sarakstu interpretētu šādi:

  • Jebkura Enum jānorāda faktiskā tipa arguments Enum. Piemēram, MonētaGalvene norāda Enum.
  • Faktiskajam argumenta tipam jābūt Enum. Piemēram, Monēta ir apakšklase Enum.
  • Apakšklase Enum (piemēram, Monēta) jāievēro idioma, ka tā piegādā savu vārdu (Monēta) kā faktiskā tipa arguments.

Pārbaudiet EnumJava dokumentāciju, un jūs atklāsiet, ka tā tiek ignorēta java.lang.Object's klons (), vienāds (), pabeigt (), hashCode (), un toString () metodes. Izņemot toString (), tiek deklarētas visas šīs svarīgākās metodes galīgais lai tos nevarētu ignorēt apakšklasē:

  • klons () tiek ignorēts, lai novērstu konstantu klonēšanu, lai nekad nebūtu vairāk par vienu konstantes kopiju; pretējā gadījumā konstantes nevarēja salīdzināt == un !=.
  • vienāds () tiek ignorēts, lai salīdzinātu konstantes, izmantojot to atsauces. Konstantes ar vienādām identitātēm (==) jābūt vienādam (vienāds ()), un atšķirīgas identitātes nozīmē atšķirīgu saturu.
  • pabeigt () tiek ignorēts, lai nodrošinātu, ka konstantes nevar pabeigt.
  • hashCode () tiek ignorēts, jo vienāds () tiek ignorēts.
  • toString () tiek ignorēts, lai atgrieztu konstantes vārdu.

Enum sniedz arī savas metodes. Šīs metodes ietver galīgaisSalīdzinot ar() (Enum īsteno java.lang.Salīdzināms interfeiss), getDeclaringClass (), nosaukums (), un kārtas numurs () metodes:

$config[zx-auto] not found$config[zx-overlay] not found