.
.
EstaapostiladaCaelumvisaensinardeumamaneiraelegante,mostrandoapenasoqueénecessárioequandoénecessário,nomomentocerto,poupandoo leitordeassuntosquenãocostumamserdeseuinteresseemdeterminadasfasesdoaprendizado.
ACaelumesperaquevocêaproveiteessematerial.Todososcomentários,críticasesugestõesserãomuitobem-vindos.
Essa apostila é constantemente atualizada edisponibilizadano sitedaCaelum.Sempre consulteositeparanovasversõese,aoinvésdeanexaroPDFparaenviaraumamigo,indiqueositeparaqueelepossasemprebaixarasúltimasversões.Vocêpodeconferirocódigodeversãodaapostilalogono naldoíndice.
Baixesempreaversãomaisnovaem:www.caelum.com.br/apostilas
Esse material é parte integrante do treinamento Java e Orientação a Objetos e distribuídogratuitamente exclusivamente pelo site da Caelum. Todos os direitos são reservados à Caelum. Adistribuição, cópia, revenda eutilizaçãoparaministrar treinamentos são absolutamente vedadas.Parausocomercialdestematerial,porfavor,consulteaCaelumpreviamente.
SOBREESTAAPOSTILA
2233
55679
10101112121315151617171819
202023242425
Sumário
1ComoAprenderJava1.1Oqueérealmenteimportante?1.2Sobreosexercícios1.3Tirandodúvidaseindoalém
2OqueéJava2.1Java2.2UmabrevehistóriadoJava2.3MáquinaVirtual2.4Javalento?HotspoteJIT2.5VersõesdoJavaeaconfusãodoJava22.6JVM?JRE?JDK?Oquedevobaixar?2.7OndeusareosobjetivosdoJava2.8Especificaçãoversusimplementação2.9ComooFJ-11estáorganizado2.10Compilandooprimeiroprograma2.11Executandoseuprimeiroprograma2.12Oqueaconteceu?2.13Parasabermais:comoéobytecode?2.14Exercícios:ModificandooHelloWorld2.15Oquepodedarerrado?2.16Umpoucomais...2.17Exercíciosadicionais
3VariáveisprimitivaseControledefluxo3.1Declarandoeusandovariáveis3.2Tiposprimitivosevalores3.3Exercícios:Variáveisetiposprimitivos3.4Discussãoemaula:convençõesdecódigoecódigolegível3.5Castingepromoção
SumárioCaelum
272929303132333335
363638404042434548505254545959
61616466697072747476
7777
3.6Oifeoelse3.7OWhile3.8OFor3.9Controlandoloops3.10Escopodasvariáveis3.11Umblocodentrodooutro3.12Parasabermais3.13Exercícios:Fixaçãodesintaxe3.14Desafios:Fibonacci
4Orientaçãoaobjetosbásica4.1Motivação:problemasdoparadigmaprocedural4.2Criandoumtipo4.3UmaclasseemJava4.4Criandoeusandoumobjeto4.5Métodos4.6Métodoscomretorno4.7Objetossãoacessadosporreferências4.8Ométodotransfere()4.9Continuandocomatributos4.10Parasabermais:UmaFábricadeCarros4.11Umpoucomais...4.12Exercícios:OrientaçãoaObjetos4.13Desafios4.14Fixandooconhecimento
5Modificadoresdeacessoeatributosdeclasse5.1Controlandooacesso5.2Encapsulamento5.3GetterseSetters5.4Construtores5.5Anecessidadedeumconstrutor5.6Atributosdeclasse5.7Umpoucomais...5.8Exercícios:Encapsulamento,construtoresestatic5.9Desafios
6EclipseIDE6.1OEclipse
CaelumSumário
7879818587888992
939394959798
100
102102104106107110111111113120
123123127128129131133133138
139139
6.2ApresentandooEclipse6.3ViewsePerspective6.4Criandoumprojetonovo6.5Criandoomain6.6Executandoomain6.7Pequenostruques6.8Exercícios:Eclipse6.9Discussãoemaula:Refactoring
7Pacotes-Organizandosuasclassesebibliotecas7.1Organização7.2Diretórios7.3Import7.4Acessoaosatributos,construtoresemétodos7.5UsandooEclipsecompacotes7.6Exercícios:Pacotes
8Ferramentas:jarejavadoc8.1Arquivos,bibliotecaseversões8.2GerandooJARpeloEclipse8.3Javadoc8.4GerandooJavadoc8.5Exercícios:JareJavadoc8.6Importandoumjarexterno8.7Exercícios:Importandoumjar8.8Manipulandoacontapelainterfacegráfica8.9Exercícios:Mostrandoosdadosdacontanatela
9Herança,reescritaepolimorfismo9.1Repetindocódigo?9.2Reescritademétodo9.3Invocandoométodoreescrito9.4Polimorfismo9.5Umoutroexemplo9.6Umpoucomais...9.7Exercícios:HerançaePolimorfismo9.8Discussõesemaula:Alternativasaoatributoprotected
10ClassesAbstratas10.1Repetindomaiscódigo?
SumárioCaelum
141142144146146
148148152156157158161162
164164166170171174175176177179179180182182
184184184185186190191194195
10.2Classeabstrata10.3Métodosabstratos10.4Aumentandooexemplo10.5Parasabermais...10.6Exercícios:ClassesAbstratas
11Interfaces11.1Aumentandonossoexemplo11.2Interfaces11.3Dificuldadenoaprendizadodeinterfaces11.4Exemplointeressante:conexõescomobancodedados11.5Exercícios:Interfaces11.6Exercíciosavançadosopcionais11.7Discussão:favoreçacomposiçãoemrelaçãoàherança
12Exceçõesecontroledeerros12.1Motivação12.2Exercícioparacomeçarcomosconceitos12.3ExceçõesdeRuntimemaiscomuns12.4Outrotipodeexceção:CheckedExceptions12.5UmpoucodagrandefamíliaThrowable12.6Maisdeumerro12.7Lançandoexceções12.8Oquecolocardentrodotry?12.9Criandoseuprópriotipodeexceção12.10Parasabermais:finally12.11Exercícios:Exceções12.12Desafios12.13Discussãoemaula:catchethrowsemException
13Opacotejava.lang13.1Pacotejava.lang13.2UmpoucosobreaclasseSystem13.3java.lang.Object13.4Métodosdojava.lang.Object:equalsetoString13.5Exercícios:java.lang.Object13.6java.lang.String13.7Exercícios:java.lang.String13.8Desafio
CaelumSumário
195
197197198199200201204206
207207208212213214217219221222223225227228229229233233
237237238238240242243244245
13.9Discussãoemaula:OquevocêprecisafazeremJava?
14Umpoucodearrays14.1Oproblema14.2Arraysdereferências14.3Percorrendoumaarray14.4PercorrendoumaarraynoJava5.014.5Exercícios:Arrays14.6Umpoucomais...14.7DesafiosOpcionais
15Collectionsframework15.1Arrayssãotrabalhosos,utilizarestruturadedados15.2Listas:java.util.List15.3ListasnoJava5eJava7comGenerics15.4Aimportânciadasinterfacesnascoleções15.5Ordenação:Collections.sort15.6Exercícios:Ordenação15.7Conjunto:java.util.Set15.8Principaisinterfaces:java.util.Collection15.9PercorrendocoleçõesnoJava515.10Parasabermais:Iterandosobrecoleçõescomjava.util.Iterator15.11Mapas-java.util.Map15.12Parasabermais:Properties15.13Parasabermais:EqualseHashCode15.14Parasabermais:Boaspráticas15.15Exercícios:Collections15.16Desafios15.17Parasabermais:Comparators,classesanônimas,Java8eolambda
16Pacotejava.io16.1ConhecendoumaAPI16.2Orientaçãoaobjetosnojava.io16.3InputStream,InputStreamReadereBufferedReader16.4LendoStringsdoteclado16.5Aanalogiaparaaescrita:OutputStream16.6Umamaneiramaisfácil:ScannerePrintStream16.7Umpoucomais...16.8Integereclasseswrappers(box)
SumárioCaelum
245246247249
251251251252252
254254257259260261
264264264265266267268270271273273274
278278280281282282
285285286
16.9AutoboxingnoJava5.016.10Parasabermais:java.lang.Math16.11Exercícios:JavaI/O16.12Discussãoemaula:DesignPatternseoTemplateMethod
17Eagora?17.1Web17.2PraticandoJavaeusandobibliotecas17.3GruposdeUsuários17.4Próximoscursos
18Apêndice-ProgramaçãoConcorrenteeThreads18.1Threads18.2Escalonadoretrocasdecontexto18.3GarbageCollector18.4Exercícios18.5Easclassesanônimas?
19Apêndice-Sockets19.1Motivação:umaAPIqueusaosconceitosaprendidos19.2Protocolo19.3Porta19.4Socket19.5Servidor19.6Cliente19.7Imagemgeral19.8Exercícios:Sockets19.9Desafio:MúltiplosClientes19.10Desafio:broadcastdasmensagens19.11Soluçãodosistemadechat
20Apêndice-Problemascomconcorrência20.1Threadsacessandodadoscompartilhados20.2Controlandooacessoconcorrente20.3VectoreHashtable20.4Umpoucomais...20.5Exercíciosavançadosdeprogramaçãoconcorrenteelocks
21Apêndice-InstalaçãodoJava21.1InstalandonoUbuntueemoutrosLinux21.2NoMacOSX
CaelumSumário
286
291291291294300309309
21.3InstalaçãodoJDKemambienteWindows
22Apêndice-Debugging22.1Oqueédebugar22.2DebugandonoEclipse22.3Perspectivadedebug22.4Debugavançado22.5Profiling22.6ProfilingnoEclipseTPTP
Versão:21.5.22
SumárioCaelum
.
CAPÍTULO1
"Buscouminstantefelizquejustifiqueminhaexistência"--FiodórDostoiévski
Muitoslivros,aopassardoscapítulos,mencionamtodososdetalhesdalinguagemjuntamentecomseus princípios básicos. Isso acaba criando muita confusão, em especial porque o estudante nãoconseguedistinguirexatamenteoqueéprimordialaprenderno início,daquiloquepodeserestudadomaisadiante.
Seumaclasseabstratadeveounãoteraomenosummétodoabstrato,seoifsóaceitaargumentosbooleanosetodososdetalhessobreclassesinternas,realmentenãodevemsetornarpreocupaçõesparaaquelecujoobjetivoprimárioéaprenderJava.Essetipodeinformaçãoseráadquiridacomotempo,enãoénecessárionoinício.
Nestecurso,separamosessasinformaçõesemquadrosespeciais, jáquesãoinformaçõesextras.Ouentão, apenas citamos num exercício e deixamos para o leitor procurar informações se for de seuinteresse.
Porfim,faltamencionaralgosobreaprática,quedevesertratadaseriamente:todososexercíciossãomuito importantes e os desafios podem ser feitos quando o curso terminar. De qualquer maneirarecomendamosaosalunosestudarememcasa,epraticarembastantecódigoevariações.
OCURSO
ParaaquelesqueestãofazendoocursoJavaeOrientaçãoaObjetos,recomendamosestudarememcasaaquiloquefoivistoduranteaaula,tentandoresolverosexercíciosopcionaiseosdesafiosapresentados.
COMOAPRENDERJAVA
1.1OQUEÉREALMENTEIMPORTANTE?
.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
Os exercícios do curso variam de práticos até pesquisas na Internet, ou mesmo consultas sobreassuntosavançadosemdeterminadostópicosparaincitaracuriosidadedoaprendiznatecnologia.
Existemtambém,emdeterminadoscapítulos,umasériededesafios.Eles focammaisnoproblemacomputacionalquenalinguagem,porémsãoumaexcelenteformadetreinarasintaxee,principalmente,familiarizar o aluno com a biblioteca padrão Java, alémde proporcionar umganhona velocidade dedesenvolvimento.
Para tirar dúvidas dos exercícios, ou de Java em geral, recomendamos o fórum do GUJ(http://www.guj.com.br/), onde sua dúvida será respondida prontamente. O GUJ foi fundado pordesenvolvedoresdaCaelum,ehojecontacommaisdeummilhãodemensagens.
Foraisso,sinta-seàvontadeparaentraremcontatocomseuinstrutorparatirartodasasdúvidasquesurgiremduranteocurso.
Seoquevocêestábuscandosãolivrosdeapoio,sugerimosconheceraeditoraCasadoCódigo:
http://www.casadocodigo.com.br
ACaelumfornecemuitosoutroscursosJava,comdestaqueparaoFJ-21quetrazaaplicaçãodoJavanaweb.
http://www.caelum.com.br/
Há tambémcursosonlineque vão te ajudar a ir além, commuita interação comos instrutores, a
JáconheceoscursosonlineAlura?
1.2SOBREOSEXERCÍCIOS
1.3TIRANDODÚVIDASEINDOALÉM
.
CAPÍTULO2
"Computadoressãoinúteis,elesapenasdãorespostas"--Picasso
ChegouahoraderesponderasperguntasmaisbásicassobreJava.Aotérminodessecapítulo,vocêserácapazde:
responderoqueéJava;mostrarasvantagensedesvantagensdoJava;entenderbemoconceitodemáquinavirtual;compilareexecutarumprogramasimples.
Entender um pouco da história da plataforma Java é essencial para enxergar os motivos que alevaramaosucesso.
Quaiseramosseusmaioresproblemasquandoprogramavanadécadade1990?
ponteiros?gerenciamentodememória?organização? falta debibliotecas? ter de reescrever parte docódigoaomudardesistemaoperacional?custofinanceirodeusaratecnologia?
AlinguagemJavaresolvebemessesproblemas,queatéentãoapareciamcomfrequêncianasoutraslinguagens. Alguns desses problemas foram particularmente atacados porque uma das grandesmotivações para a criação da plataforma Java era de que essa linguagem fosse usada em pequenosdispositivos, como tvs, videocassetes, aspiradores, liquidificadores e outros.Apesar disso a linguagemteveseulançamentofocadonousoemclientesweb(browsers)pararodarpequenasaplicações(applets).Hoje emdia essenãoéograndemercadodo Java: apesarde ter sido idealizadocomumpropósito elançadocomoutro,oJavaganhoudestaquenoladodoservidor.
O Java foi criado pela antiga Sun Microsystems e mantida através de um comitê(http://www.jcp.org). Seu site principal era o java.sun.com, e java.com um site mais institucional,voltadoaoconsumidordeprodutoseusuáriosleigos,nãodesenvolvedores.ComacompradaSunpelaOracle em 2009,muitasURLs e nomes tem sido trocados para refletir amarca daOracle. A páginaprincipaldoJavaé:http://www.oracle.com/technetwork/java/
No Brasil, diversos grupos de usuários se formaram para tentar disseminar o conhecimento da
OQUEÉJAVA
2.1JAVA
.
linguagem.UmdeleséoGUJ(http://www.guj.com.br),umacomunidadevirtualcomartigos,tutoriaisefórumparatirardúvidas,omaioremlínguaportuguesacommaisdecemmilusuáriose1milhãodemensagens.
Encorajamostodososalunosausarmuitoosfórunsdomesmo,poiséumadasmelhoresmaneirasparaacharsoluçõesparapequenosproblemasqueacontecemcomgrandefrequência.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
ASuncriouumtime(conhecidocomoGreenTeam)paradesenvolver inovações tecnológicasem1992.EssetimefoilideradoporJamesGosling,consideradoopaidoJava.Otimevoltoucomaideiadecriaruminterpretador(jáeraumamáquinavirtual,veremosoqueéissomaisafrente)parapequenosdispositivos,facilitandoareescritadesoftwareparaaparelhoseletrônicos,comovídeocassete,televisãoeaparelhosdeTVacabo.
Aideianãodeucerto.Tentaramfechardiversoscontratoscomgrandes fabricantesdeeletrônicos,comoPanasonic,masnãohouveêxitodevidoaoconflitode interesses e custos.Hoje, sabemosqueoJavadominaomercadodeaplicaçõesparacelularescommaisde2.5bilhõesdedispositivoscompatíveis,porémem1994aindaeramuitocedoparaisso.
Com o advento da web, a Sun percebeu que poderia utilizar a ideia criada em 1992 para rodarpequenasaplicaçõesdentrodobrowser.Asemelhançaeraquenainternethaviaumagrandequantidadede sistemasoperacionais ebrowsers, e com isso seria grandevantagempoderprogramarnumaúnicalinguagem, independente da plataforma. Foi aí que o Java 1.0 foi lançado: focado em transformar obrowser de apenas um cliente magro (thin client ou terminal burro) em uma aplicação que possa
SaberinglêsémuitoimportanteemTI
2.2UMABREVEHISTÓRIADOJAVA
.
tambémrealizaroperaçõesavançadas,enãoapenasrenderizarhtml.
OsappletsdeixaramdeserofocodaSun,enemaOraclenuncateveinteresse.Écuriosonotarqueatecnologia Java nasceu com um objetivo em mente, foi lançado com outro, mas, no final, decoloumesmonodesenvolvimentodeaplicaçõesdoladodoservidor.Sorte?HáhojeoJavaFX,tentandodarforçaparaoJavanãosónodesktopmascomoaplicaçõesricasnaweb,masmuitosnãoacreditamquehajaespaçoparatal,considerandoodestinodetecnologiascomoAdobeFlexeMicrosoftSilverlight.
VocêpodelerahistóriadalinguagemJavaem:http://www.java.com/en/javahistory/
Eumvídeointeressante:http://tinyurl.com/histjava
Em2009aOraclecomprouaSun,fortalecendoamarca.AOraclesemprefoi,juntocomaIBM,umadasempresasquemaisinvestiramefizeramnegóciosatravésdousodaplataformaJava.Em2014surgeaversãoJava8commudançasinteressantesnalinguagem.
Em uma linguagem de programação como C e Pascal, temos a seguinte situação quando vamoscompilarumprograma:
O código fonte é compilado para código de máquina específico de uma plataforma e sistemaoperacional.Muitasvezesoprópriocódigofonteédesenvolvidovisandoumaúnicaplataforma!
Esse código executável (binário) resultante será executado pelo sistema operacional e, por essemotivo,eledevesaberconversarcomosistemaoperacionalemquestão.
Istoé, temosumcódigoexecutávelparacadasistemaoperacional.Énecessáriocompilarumavez
2.3MÁQUINAVIRTUAL
.
paraWindows,outraparaoLinux,eassimpordiante,casoagentequeiraqueessenossosoftwarepossaserutilizadoemváriasplataformas.EsseéocasodeaplicativoscomooOpenOffice,Firefoxeoutros.
Como foi dito anteriormente, na maioria das vezes, a sua aplicação se utiliza das bibliotecas dosistemaoperacional,como,porexemplo,adeinterfacegráficaparadesenharas"telas".AbibliotecadeinterfacegráficadoWindowsébemdiferentedasdoLinux:comocriarentãoumaaplicaçãoquerodedeformaparecidanosdoissistemasoperacionais?
Precisamosreescreverummesmopedaçodaaplicaçãoparadiferentessistemasoperacionais,jáqueelesnãosãocompatíveis.
Já o Java utiliza do conceito de máquina virtual, onde existe, entre o sistema operacional e aaplicação, uma camada extra responsável por "traduzir" -mas não apenas isso - o que sua aplicaçãodesejafazerparaasrespectivaschamadasdosistemaoperacionalondeelaestárodandonomomento:
Dessaforma,amaneiracomaqualvocêabreumajanelanoLinuxounoWindowséamesma:vocêganhaindependênciadesistemaoperacional.Ou,melhorainda,independênciadeplataformaemgeral:nãoéprecisosepreocuparemqualsistemaoperacionalsuaaplicaçãoestárodando,nememquetipodemáquina,configurações,etc.
Reparequeumamáquinavirtualéumconceitobemmaisamploqueodeuminterpretador.Comoopróprio nome diz, uma máquina virtual é como um "computador de mentira": tem tudo que umcomputador tem. Em outras palavras, ela é responsável por gerenciar memória, threads, a pilha deexecução,etc.
Sua aplicação roda sem nenhum envolvimento com o sistema operacional! Sempre conversandoapenascomaJavaVirtualMachine(JVM).
Essacaracterísticaéinteressante:comotudopassapelaJVM,elapodetirarmétricas,decidirondeémelhoralocaramemória,entreoutros.UmaJVMisolatotalmenteaaplicaçãodosistemaoperacional.SeumaJVMterminaabruptamente,sóasaplicaçõesqueestavamrodandonelairãoterminar:issonãoafetaráoutrasJVMsqueestejamrodandonomesmocomputador,nemafetaráosistemaoperacional.
.
Essacamadadeisolamentotambéméinteressantequandopensamosemumservidorquenãopodesesujeitararodarcódigoquepossainterferirnaboaexecuçãodeoutrasaplicações.
Essa camada, a máquina virtual, não entende código java, ela entende um código de máquinaespecífico.Essecódigodemáquinaégeradoporumcompiladorjava,comoojavac,eéconhecidopor"bytecode",poisexistemmenosde256códigosdeoperaçãodessalinguagem,ecada"opcode"gastaumbyte.OcompiladorJavageraessebytecodeque,diferentedaslinguagenssemmáquinavirtual,vaiservirparadiferentessistemasoperacionais,jáqueelevaiser"traduzido"pelaJVM.
WRITEONCE,RUNANYWHERE
EsseeraumsloganqueaSunusavaparaoJava,jáquevocênãoprecisareescreverpartesdasuaaplicaçãotodavezquequisermudardesistemaoperacional.
HotspotéatecnologiaqueaJVMutilizaparadetectarpontosquentesdasuaaplicação:códigoqueéexecutadomuito,provavelmentedentrodeumoumaisloops.QuandoaJVMjulgarnecessário,elavaicompilar estes códigos para instruções realmente nativas da plataforma, tendo em vista que isso vaiprovavelmentemelhoraraperformancedasuaaplicação.EssecompiladoréoJIT:JustinTimeCompiler,ocompiladorqueaparece"bemnahora"quevocêprecisa.
Você pode pensar então: porque a JVM não compila tudo antes de executar a aplicação? É queteoricamentecompilardinamicamente,amedidadonecessário,podegerarumaperformancemelhor.Omotivoésimples:imagineum.exegeradopeloVisualBasic,pelogccoupeloDelphi;eleéestático.Elejáfoiotimizadobaseadoemheurísticas,ocompiladorpodetertomadoumadecisãonãotãoboa.
Já a JVM, por estar compilando dinamicamente durante a execução, pode perceber que umdeterminadocódigonãoestácomperformanceadequadaeotimizarmaisumpoucoaqueletrecho,ouaindamudaraestratégiadeotimização.ÉporessemotivoqueasJVMsmaisrecentesemalgunscasoschegamaganhardecódigosCcompiladoscomoGCC3.x.
2.4JAVALENTO?HOTSPOTEJIT
.
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
Java1.0e1.1sãoasversõesmuitoantigasdoJava,mas já traziambibliotecas importantescomooJDBCeojava.io.
Com o Java 1.2 houve um aumento grande no tamanho da API, e foi nesse momento em quetrocaramanomenclaturadeJavaparaJava2,comoobjetivodediminuiraconfusãoquehaviaentreJavaeJavascript.Mas lembre-se,nãoháversão"Java2.0",o2 foi incorporadoaonome, tornando-seJava21.2.
DepoisvieramoJava21.3e1.4,eoJava1.5passouasechamarJava5, tantoporumaquestãodemarketingeporquemudançassignificativasnalinguagemforamincluídas.Énessemomentoqueo"2"donomeJavadesaparece.Reparequeparafinsdedesenvolvimento,oJava5aindaéreferidocomoJava1.5.
HojeaúltimaversãodisponíveldoJavaéa8.
OquegostaríamosdebaixarnositedaOracle?
JVM=apenasavirtualmachine,essedownloadnãoexiste,elasemprevemacompanhada.JRE = Java Runtime Environment, ambiente de execução Java, formado pela JVM ebibliotecas, tudoquevocêprecisaparaexecutarumaaplicação Java.Masnósprecisamosdemais.JDK=JavaDevelopmentKit:Nós,desenvolvedores,faremosodownloaddoJDKdoJavaSE
AprendasedivertindonaAluraStart!
2.5VERSÕESDOJAVAEACONFUSÃODOJAVA2
2.6JVM?JRE?JDK?OQUEDEVOBAIXAR?
.
(StandardEdition).EleéformadopelaJREsomadoaferramentas,comoocompilador.
Tanto o JRE e o JDK podem ser baixados do site http://www.oracle.com/technetwork/java/. Paraencontrá-los,acesseolinkJavaSEdentrodostopdownloads.ConsulteoapêndicedeinstalaçãodoJDKparamaioresdetalhes.
Nodecorrerdocurso,vocêpodeacharqueoJavatemmenorprodutividadequandocomparadacomalinguagemquevocêestáacostumado.
ÉprecisoficarclaroqueapremissadoJavanãoéadecriarsistemaspequenos,ondetemosumoudoisdesenvolvedores,maisrapidamentequelinguagenscomophp,perl,eoutras.
Ofocodaplataformaéoutro:aplicaçõesdemédioagrandeporte,ondeotimededesenvolvedorestemváriaspessoasesemprepodeviramudarecrescer.NãotenhadúvidasquecriaraprimeiraversãodeumaaplicaçãousandoJava,mesmoutilizandoIDEseferramentaspoderosas,serámaistrabalhosoquemuitas linguagens script ou de alta produtividade. Porém, comuma linguagemorientada a objetos emaduracomooJava,seráextremamentemaisfácilerápidofazeralteraçõesnosistema,desdequevocêsigaasboaspráticaserecomendaçõessobredesignorientadoaobjetos.
Alémdisso, a quantidade enormede bibliotecas gratuitas para realizar osmais diversos trabalhos(tais como relatórios, gráficos, sistemas de busca, geração de código de barra,manipulação deXML,tocadores de vídeo, manipuladores de texto, persistência transparente, impressão, etc) é um pontofortíssimoparaadoçãodoJava:vocêpodecriarumaaplicaçãosofisticada,usandodiversosrecursos,semprecisarcomprarumcomponenteespecífico,quecostumasercaro.OecossistemadoJavaéenorme.
Cada linguagemtemseuespaçoeseumelhoruso.OusodoJavaé interessanteemaplicaçõesquevirãoacrescer,emquealegibilidadedocódigoéimportante,ondetemosmuitaconectividadeesehámuitas plataformas (ambientes e sistemas operacionais) heterogêneas (Linux,Unix,OSX eWindowsmisturados).
VocêpodeverissopelaquantidadeenormedeofertasdeempregoprocurandodesenvolvedoresJavaparatrabalharcomsistemaswebeaplicaçõesdeintegraçãonoservidor.
Apesardisto,aSunempenhou-seemtentarpopularizarousodoJavaemaplicaçõesdesktop,mesmocom o fracomarketshare do Swing/AWT/SWT em relação às tecnologias concorrentes (em especialMicrosoft.NET).AatualtentativaéoJavaFX,ondeaOracleteminvestidobastante.
2.7ONDEUSAREOSOBJETIVOSDOJAVA
.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
Outro ponto importante: quando falamos de Java Virtual Machine, estamos falando de umaespecificação.EladizcomoobytecodedeveserinterpretadopelaJVM.QuandofazemosodownloadnositedaOracle,oquevemjuntoéaOracleJVM.Emoutraspalavras,existemoutrasJVMsdisponíveis,comoaJRockitdaBEA(tambémadquiridapelaOracle),aJ9daIBM,entreoutras.
Esseéoutroponto interessanteparaasempresas.CasonãoestejamgostandodealgumdetalhedaJVMdaOracleouprefiramtrabalharcomoutraempresa,pagandoporsuporte,elaspodemtrocardeJVMcomagarantiaabsolutadequetodoosistemacontinuaráfuncionando.IssoporquetodaJVMdeveser certificada pela Oracle, provando a sua compatibilidade. Não há nem necessidade de recompilarnenhumadesuasclasses.
Além de independência de hardware e sistema operacional, você tem a independência de vendor(fabricante):graçasaideiadaJVMserumaespecificaçãoenãoumsoftware.
Javaéumalinguagemsimples:existempoucasregras,muitobemdefinidas.
Porém quebrar o paradigma procedural para mergulhar na orientação a objetos não é simples.QuebraroparadigmaeganharfluênciacomalinguagemeAPIsãoosobjetivosdoFJ-11.
Ocomeçopode serumpouco frustrante: exemplos simples, controlede fluxocomoif,for,whileecriaçãodepequenosprogramasquenemaomenoscaptamdadosdoteclado.Apesardeissotudosernecessário,ésónos20%finaisdocursoqueutilizaremosbibliotecaspara,nofinal,criarmosumchat entre duas máquinas que transferem Strings por TCP/IP. Neste ponto, teremos tudo que énecessárioparaentendercompletamentecomoaAPIfunciona,quemestendequem,eoporquê.
Seuslivrosdetecnologiaparecemdoséculopassado?
2.8ESPECIFICAÇÃOVERSUSIMPLEMENTAÇÃO
2.9COMOOFJ-11ESTÁORGANIZADO
.
Depois desse capítulo no qual o Java, a JVM e primeiros conceitos são passados, veremos oscomandosbásicosdojavaparacontroledefluxoeutilizaçãodevariáveisdotipoprimitivo.Criaremosclassespara testar essepequenoaprendizado, semsaberexatamenteoqueéuma classe. Issodificultaaindamais a curva de aprendizado, porém cada conceito será introduzido nomomento consideradomaisapropriadopelosinstrutores.
Passamos para o capítulo de orientação a objetos básico,mostrando os problemas do paradigmaprocedural e a necessidade de algo diferente para resolvê-los. Atributos, métodos, variáveis do tiporeferênciaeoutros.
Os capítulos de modificadores de acesso, herança, classes abstratas e interfaces demonstram oconceitofundamentalqueocursoquerpassar:encapsule,exponhaomínimodesuasclasses,foquenoque elas fazem, no relacionamento entre elas. Com um bom design, a codificação fica fácil e amodificaçãoeexpansãodosistematambém.
No decorrer desses capítulos, o Eclipse é introduzido de forma natural, evitando-se ao máximowizardsemenus,priorizandomostraroschamadoscodeassistsequickfixes.IssofazcomqueoEclipsetrabalhedeformasimbióticacomodesenvolvedor,semseintrometer,semfazermágica.
Pacotes,javadoc,jarsejava.langapresentamosúltimosconceitosfundamentaisdoJava,dandotodaafundaçãopara,então,passarmosaestudarasprincipaisemaisutilizadasAPIsdoJavaSE.
AsAPIsestudadasserãojava.utilejava.io.Todaselasusameabusamdosconceitosvistosnodecorrerdocurso,ajudandoasedimentá-los.Juntamente,temososconceitosbásicosdousodeThreads,eosproblemaseperigosdaprogramaçãoconcorrentequandodadossãocompartilhados.
Resumindo: o objetivo do curso é apresentar o Java ao mesmo tempo que os fundamentos daorientaçãoaobjetossãointroduzidos.Bateremosmuitonopontodedizerqueoimportanteécomoasclasses se relacionamequal éopapelde cadauma, enão emcomoelas realizamas suasobrigações.Programevoltadoàinterface,enãoàimplementação.
Vamosparaonossoprimeirocódigo!Oprogramaqueimprimeumalinhasimples.
Paramostrarumalinha,podemosfazer:
System.out.println("MinhaprimeiraaplicaçãoJava!");
Masessecódigonãoseráaceitopelocompiladorjava.OJavaéumalinguagembastanteburocrática,eprecisademaisdoqueissoparainiciarumaexecução.Veremososdetalheseosporquêsduranteospróximoscapítulos.Omínimoqueprecisaríamosescreveréalgocomo:
classMeuPrograma{publicstaticvoidmain(String[]args){
2.10COMPILANDOOPRIMEIROPROGRAMA
.
System.out.println("MinhaprimeiraaplicaçãoJava!");}}
NOTAÇÃO
Todososcódigosapresentadosnaapostilaestãoformatadoscomrecursosvisuaisparaauxiliaraleituraecompreensãodosmesmos.Quandofordigitaroscódigosnocomputador,trateoscódigoscomotextosimples.
Anumeraçãodaslinhasnãofazpartedocódigoenãodeveserdigitada;éapenasumrecursodidático.OJavaécasesensitive:tomecuidadocommaiúsculaseminúsculas.
Apósdigitarocódigoacima,grave-ocomoMeuPrograma.javaemalgumdiretório.Paracompilar,você deve pedir para que o compilador de Java da Oracle, chamado javac , gere o bytecodecorrespondenteaoseucódigoJava.
Depoisdecompilar,obytecodefoigerado.Quandoosistemaoperacionallistarosarquivoscontidosnodiretórioatual,vocêpoderáverqueumarquivo.classfoigerado,comomesmonomedasuaclasseJava.
ASSUSTADOCOMOCÓDIGO?
ParaquemjátemumaexperiênciacomJava,esseprimeirocódigoémuitosimples.Mas,seéseu primeiro código em Java, pode ser umpouco traumatizante.Nãodeixe de ler o prefácio docurso, que deixará você mais tranquilo em relação a curva de aprendizado da linguagem,conhecendocomoocursoestáorganizado.
.
PRECISOSEMPREPROGRAMARUSANDOONOTEPADOUSIMILAR?
NãoénecessáriodigitarsempreseuprogramaemumsimplesaplicativocomooNotepad.Vocêpodeusarumeditorquetenhasyntaxhighlightingeoutrosbenefícios.
Mas,nocomeço,éinteressantevocêusaralgoquenãopossuaferramentas,paraquevocêpossaseacostumarcomoserrosdecompilação,sintaxeeoutros.Depoisdocapítulodepolimorfismoeherança sugerimos a utilização do Eclipse (http://www.eclipse.org), a IDE líder no mercado, egratuita.ExisteumcapítuloaparteparaousodoEclipsenestaapostila.
NoLinux,recomendamosousodogedit,kateevi.NoWindows,vocêpodeusaroNotepad++ouoTextPad.NoMac,TextMate,Sublimeoumesmoovi.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
Osprocedimentosparaexecutarseuprogramasãomuitosimples.OjavacéocompiladorJava,eojavaéoresponsávelporinvocaramáquinavirtualparainterpretaroseuprograma.
Aoexecutar,podeserqueaacentuaçãoresultantesaiaerradadevidoaalgumasconfiguraçõesquedeixamosdefazer.Semproblemas.
Agoraéamelhorhoraderespirarmaistecnologia!
2.11EXECUTANDOSEUPRIMEIROPROGRAMA
2.12OQUEACONTECEU?
.
classMeuPrograma{publicstaticvoidmain(String[]args){
//miolodoprogramacomeçaaqui!System.out.println("MinhaprimeiraaplicaçãoJava!!");//fimdomiolodoprograma
}}
Omiolodoprogramaéoqueseráexecutadoquandochamamosamáquinavirtual.Porenquanto,todasaslinhasanteriores,ondeháadeclaraçãodeumaclasseeadeummétodo,nãoimportamparanósnessemomento.Masdevemossaberque todaaplicação Javacomeçaporumpontodeentrada,eestepontodeentradaéométodomain.
Aindanãosabemosoqueémétodo,masveremosnocapítulo4.Atélá,nãosepreocupecomessasdeclarações.Semprequeumexercícioforfeito,ocódigoquenosimportasempreestaránessemiolo.
Nocasodonossocódigo,alinhadoSystem.out.printlnfazcomqueoconteúdoentreaspassejacolocadonatela.
OMeuPrograma.classgeradonãoélegívelporsereshumanos(nãoquesejaimpossível).Eleestáescritonoformatoqueavirtualmachinesabeentenderequefoiespecificadoqueelaentendesse.
É como um assembly, escrito para esta máquina em específico. Podemos ler os mnemônicosutilizandoaferramentajavapqueacompanhaoJDK:
javap-cMeuPrograma
Easaída:
MeuPrograma();Code:0:aload_01:invokespecial#1;//Methodjava/lang/Object."<init>":()V4:return
publicstaticvoidmain(java.lang.String[]);Code:0:getstatic#2;//Fieldjava/lang/System.out:Ljava/io/PrintStream;3:ldc#3;//StringMinhaprimeiraaplicaçãoJava!!5:invokevirtual#4;//Methodjava/io/PrintStream.println:(Ljava/lang/String;)V8:return
}
Éocódigoacima,queaJVMsabeler.Éo"códigodemáquina",damáquinavirtual.
Um bytecode pode ser revertido para o .java original (com perda de comentários e nomes de
2.13PARASABERMAIS:COMOÉOBYTECODE?
.
variáveislocais).Casoseusoftwarevávirarumprodutodeprateleira,éfundamentalusarumofuscadorno seu código, que vai embaralhar classes, métodos e um monte de outros recursos (indicamos ohttp://proguard.sf.net).
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
1. Altereseuprogramaparaimprimirumamensagemdiferente.2. AltereseuprogramaparaimprimirduaslinhasdetextousandoduaslinhasdecódigoSystem.out.3. Sabendoqueoscaracteres\n representamumaquebrade linhas, imprimaduas linhasde texto
usandoumaúnicalinhadecódigoSystem.out.
Muitos errospodemocorrernomomentoquevocê rodar seuprimeirocódigo.Vamosveralgunsdeles:
Código:
classX{publicstaticvoidmain(String[]args){System.out.println("Faltapontoevírgula")}}
Erro:
X.java:4:';'expected}^1error
Esseéoerrodecompilaçãomaiscomum:aqueleondeumpontoevírgula foraesquecido.Repare
EditoraCasadoCódigocomlivrosdeumaformadiferente
2.14EXERCÍCIOS:MODIFICANDOOHELLOWORLD
2.15OQUEPODEDARERRADO?
.
queocompiladoréexplícitoemdizerquealinha4éacomproblemas.Outroserrosdecompilaçãopodemocorrersevocêescreveupalavraschaves(asquecolocamosemnegrito)emmaiúsculas,esqueceudeabrirefecharas{},etc.
Duranteaexecução,outroserrospodemaparecer:
SevocêdeclararaclassecomoX,compilá-laedepoistentarusá-lacomoxminúsculo(javax),oJavateavisa:
Exceptioninthread"main"java.lang.NoClassDefFoundError:X(wrongname:x)
Se tentar acessar uma classe no diretório ou classpath errado, ou se o nome estiver errado,ocorreráoseguinteerro:
Exceptioninthread"main"java.lang.NoClassDefFoundError:X
SeesquecerdecolocarstaticouoargumentoString[]argsnométodomain:
Exceptioninthread"main"java.lang.NoSuchMethodError:main
Porexemplo:
classX{publicvoidmain(String[]args){System.out.println("Faltouostatic,tenteexecutar!");}}
Senãocolocarométodomaincomopublic:
Mainmethodnotpublic.
Porexemplo:
classX{staticvoidmain(String[]args){System.out.println("Faltouopublic");}}
Procureumcolega,oualgumconhecido,queestejaemumprojetoJava.DescubraporqueJavafoiescolhidocomotecnologia.OqueéimportanteparaesseprojetoeoqueacaboufazendodoJavaamelhorescolha?
2.16UMPOUCOMAIS...
.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
1. UmarquivofonteJavadevesempreteraextensão.java,ouocompiladororejeitará.Alémdisso,existemalgumasoutras regrasnahoradedar onomedeumarquivo Java.Experimente gravar ocódigodestecapítulocomOutroNome.javaoualgosimilar.
Compileeverifiqueonomedoarquivogerado.Comoexecutarasuaaplicação?
JáconheceoscursosonlineAlura?
2.17EXERCÍCIOSADICIONAIS
.
CAPÍTULO3
"Péssimaideia,adequenãosepodemudar"--Montaigne
AprenderemosatrabalharcomosseguintesrecursosdalinguagemJava:
declaração,atribuiçãodevalores,castingecomparaçãodevariáveis;controledefluxoatravésdeifeelse;instruçõesdelaçoforewhile,controledefluxocombreakecontinue.
Dentrodeumbloco,podemosdeclararvariáveiseusá-las.EmJava,todavariáveltemumtipoquenãopodesermudado,umavezquedeclarado:
tipoDaVariavelnomeDaVariavel;
Porexemplo,épossívelterumaidadequeguardaumnúmerointeiro:
intidade;
Comisso,vocêdeclaraavariávelidade, quepassa a existir apartirdaquela linha.Ela édo tipoint,queguardaumnúmerointeiro.Apartirdaí,vocêpodeusá-la,primeiramenteatribuindovalores.
Alinhaaseguiréatraduçãode:"idadedevevalerquinze".
idade=15;
COMENTÁRIOSEMJAVA
Parafazerumcomentárioemjava,vocêpodeusaro//paracomentaratéofinaldalinha,ouentãousaro/**/paracomentaroqueestiverentreeles.
/*comentáriodaqui,ateaqui*/
//umalinhadecomentáriosobreaidadeintidade;
VARIÁVEISPRIMITIVASECONTROLEDEFLUXO
3.1DECLARANDOEUSANDOVARIÁVEIS
.
Além de atribuir, você pode utilizar esse valor. O código a seguir declara novamente a variávelidadecomvalor15eimprimeseuvalornasaídapadrãoatravésdachamadaaSystem.out.println.
//declaraaidadeintidade;idade=15;
//imprimeaidadeSystem.out.println(idade);
Por fim, podemos utilizar o valor de uma variável para algum outro propósito, como alterar oudefinirumasegundavariável.OcódigoaseguircriaumavariávelchamadaidadeNoAnoQueVem comvalordeidademaisum.
//calculaaidadenoanoseguinteintidadeNoAnoQueVem;idadeNoAnoQueVem=idade+1;
Nomesmomomentoquevocêdeclaraumavariável,tambémépossívelinicializá-laporpraticidade:
intidade=15;
Vocêpodeusarosoperadores+,-,/eparaoperarcomnúmeros,sendoelesresponsáveispelaadição,subtração, divisão e multiplicação, respectivamente. Além desses operadores básicos, há o operador %(módulo)quenadamaiséqueo*restodeumadivisãointeira.Vejaalgunsexemplos:
intquatro=2+2;inttres=5-2;
intoito=4*2;intdezesseis=64/4;
intum=5%2;//5divididopor2dá2etemresto1;//ooperador%pegaorestodadivisãointeira
.
COMORODARESSESCÓDIGOS?
Vocêdevecolocaressestrechosdecódigodentrodoblocomainquevimosnocapítuloanterior.Isto é, isso deve ficar nomiolo doprograma.Use bastanteSystem.out.println, dessa formavocêpodeveralgumresultado,casocontrário,aoexecutaraaplicação,nadaaparecerá.
Porexemplo,paraimprimiraidade eaidadeNoAnoQueVem podemos escrever o seguinteprogramadeexemplo:
classTestaIdade{
publicstaticvoidmain(String[]args){//imprimeaidadeintidade=20;System.out.println(idade);
//geraumaidadenoanoseguinteintidadeNoAnoQueVem;idadeNoAnoQueVem=idade+1;
//imprimeaidadeSystem.out.println(idadeNoAnoQueVem);}}
Representarnúmerosinteiroséfácil,mascomoguardarvaloresreais,taiscomofraçõesdenúmerosinteiroseoutros?Outrotipodevariávelmuitoutilizadoéodouble,quearmazenaumnúmerocompontoflutuante(equetambémpodearmazenarumnúmerointeiro).
doublepi=3.14;doublex=5*10;
O tipo boolean armazena um valor verdadeiro ou falso, e só: nada de números, palavras ouendereços,comoemalgumasoutraslinguagens.
booleanverdade=true;
trueefalse sãopalavras reservadasdo Java.É comumqueumboolean seja determinadoatravés de uma expressãobooleana, isto é, um trecho de código que retorna um booleano, como oexemplo:
intidade=30;booleanmenorDeIdade=idade<18;
Otipocharguardaum,eapenasum,caractere.Essecaracteredeveestarentreaspassimples.Nãoseesqueçadessasduascaracterísticasdeumavariáveldotipochar!Porexemplo,elanãopodeguardarumcódigocomo''poisovazionãoéumcaractere!
charletra='a';System.out.println(letra);
.
Variáveisdotipocharsãopoucousadasnodiaadia.VeremosmaisafrenteousodasStrings,queusamosconstantemente,porémestasnãosãodefinidasporumtipoprimitivo.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
EssestiposdevariáveissãotiposprimitivosdoJava:ovalorqueelasguardamsãoorealconteúdodavariável.Quandovocêutilizarooperadordeatribuição=ovalorserácopiado.
inti=5;//irecebeumacópiadovalor5intj=i;//jrecebeumacópiadovalordeii=i+1;//ivira6,jcontinua5
Aqui,ificacomovalorde6.Masej?Nasegundalinha,jestávalendo5.Quandoipassaavaler6,seráquejtambémmudadevalor?Não,poisovalordeumtipoprimitivosempreécopiado.
Apesardalinha2fazerj=i,apartirdessemomentoessasvariáveisnãotemrelaçãonenhuma:oqueacontececomuma,nãorefleteemnadacomaoutra.
OUTROSTIPOSPRIMITIVOS
Vimos aqui os tipos primitivos que mais aparecem. O Java tem outros, que são o byte,short,longefloat.
Cada tipo possui características especiais que, para um programador avançado, podem fazermuitadiferença.
SaberinglêsémuitoimportanteemTI
3.2TIPOSPRIMITIVOSEVALORES
.
1. Naempresaondetrabalhamos,hátabelascomoquantofoigastoemcadamês.Parafecharobalançodoprimeirotrimestre,precisamossomarogastototal.Sabendoque,emJaneiro,foramgastos15000reais,emFevereiro,23000reaiseemMarço,17000reais,façaumprogramaquecalculeeimprimaogastototalnotrimestre.Sigaessespassos:
Crie uma classe chamada BalancoTrimestral com um bloco main, como nos exemplosanteriores;Dentrodomain(omiolodoprograma),declareumavariávelinteirachamadagastosJaneiroeinicialize-acom15000;Crie também as variáveis gastosFevereiro e gastosMarco, inicializando-as com 23000 e17000,respectivamente,utilizeumalinhaparacadadeclaração;
CrieumavariávelchamadagastosTrimestreeinicialize-acomasomadasoutras3variáveis:
intgastosTrimestre=gastosJaneiro+gastosFevereiro+gastosMarco;
ImprimaavariávelgastosTrimestre.
2. Adicione código (sem alterar as linhas que já existem) na classe anterior para imprimir a médiamensal de gasto, criando uma variável mediaMensal junto com uma mensagem. Para isso,concateneaStringcomovalor,usando"Valordamédiamensal="+mediaMensal.
DiscutacomoinstrutoreseuscolegassobreconvençõesdecódigoJava.Porqueexistem?Porquesãoimportantes?
Discutatambémasvantagensdeseescrevercódigofácildelereseevitarcomentáriosemexcesso.(Dica:procureporjavacodeconventions).
3.3EXERCÍCIOS:VARIÁVEISETIPOSPRIMITIVOS
3.4 DISCUSSÃO EM AULA: CONVENÇÕES DE CÓDIGO E CÓDIGOLEGÍVEL
.
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
Algunsvaloressãoincompatíveissevocêtentarfazerumaatribuiçãodireta.Enquantoumnúmerorealcostumaserrepresentadoemumavariáveldotipodouble,tentaratribuireleaumavariávelintnão funciona porque é um código que diz: "i deve valerd",mas não se sabe sed realmente é umnúmerointeiroounão.
doubled=3.1415;inti=d;//nãocompila
Omesmoocorrenoseguintetrecho:
inti=3.14;
Omaisinteressante,équenemmesmooseguintecódigocompila:
doubled=5;//ok,odoublepodeconterumnúmerointeirointi=d;//nãocompila
Apesarde5serumbomvalorparaumint,ocompiladornãotemcomosaberquevalorestarádentro desse double no momento da execução. Esse valor pode ter sido digitado pelo usuário, eninguémvaigarantirqueessaconversãoocorrasemperdadevalores.
Jánocasoaseguir,éocontrário:
inti=5;doubled2=i;
Ocódigoacimacompilasemproblemas,jáqueumdoublepodeguardarumnúmerocomousempontoflutuante.Todososinteirosrepresentadosporumavariáveldotipointpodemserguardadosemumavariáveldouble,entãonãoexistemproblemasnocódigoacima.
AprendasedivertindonaAluraStart!
3.5CASTINGEPROMOÇÃO
.
Às vezes, precisamos que um número quebrado seja arredondado e armazenado num númerointeiro.Para fazer issosemquehajaoerrodecompilação,éprecisoordenarqueonúmeroquebradosejamoldado(casted)comoumnúmerointeiro.Esseprocessorecebeonomedecasting.
doubled3=3.14;inti=(int)d3;
Ocastingfoifeitoparamoldaravariáveld3comoumint.Ovalordeiagoraé3.
Omesmoocorreentrevaloresintelong.
longx=10000;inti=x;//nãocompila,poispodeestarperdendoinformação
E,sequisermosrealmentefazerisso,fazemosocasting:
longx=10000;inti=(int)x;
CASOSNÃOTÃOCOMUNSDECASTINGEATRIBUIÇÃO
Algunscastingsaparecemtambém:
floatx=0.0;
O código acima não compila pois todos os literais com ponto flutuante são consideradosdoublepeloJava.Efloatnãopodereceberumdoublesemperdadeinformação,parafazerissofuncionarpodemosescreveroseguinte:
floatx=0.0f;
Aletraf,quepodesermaiúsculaouminúscula,indicaqueaqueleliteraldevesertratadocomofloat.
Outrocaso,queémaiscomum:
doubled=5;floatf=3;
floatx=f+(float)d;
VocêprecisadocastingporqueoJavafazascontasevaiarmazenandosemprenomaiortipoqueapareceuduranteasoperações,nocasoodouble.
E,umaobservação:nomínimo,oJavaarmazenaoresultadoemumint,nahoradefazerascontas.
Atécastingcomvariáveisdotipocharpodemocorrer.Oúnicotipoprimitivoquenãopodeseratribuídoanenhumoutrotipoéoboolean.
.
CASTINGSPOSSÍVEIS
Abaixoestãorelacionados todososcastspossíveisna linguagemJava,mostrandoaconversãodeumvalorparaoutro.AindicaçãoImpl.querdizerqueaquelecastéimplícitoeautomático,ouseja, vocênãoprecisa indicaro cast explicitamente (lembrandoqueo tipobooleannãopode serconvertidoparanenhumoutrotipo).
TAMANHODOSTIPOS
Natabelaabaixo,estãoostamanhosdecadatipoprimitivodoJava.
AsintaxedoifnoJavaéaseguinte:
if(condicaoBooleana){codigo;}
3.6OIFEOELSE
.
Umacondiçãobooleanaéqualquerexpressãoqueretornetrueoufalse.Paraisso,vocêpodeusarosoperadores<,>,<=,>=eoutros.Umexemplo:
intidade=15;if(idade<18){System.out.println("Nãopodeentrar");}
Alémdisso,vocêpodeusaracláusulaelseparaindicarocomportamentoquedeveserexecutadonocasodaexpressãobooleanaserfalsa:
intidade=15;if(idade<18){System.out.println("Nãopodeentrar");}else{System.out.println("Podeentrar");}
Você pode concatenar expressões booleanas através dos operadores lógicos "E" e "OU". O "E" érepresentadopelo&&eo"OU"érepresentadopelo||.
Umexemploseriaverificarseeletemmenosde18anoseseelenãoéamigododono:
intidade=15;booleanamigoDoDono=true;if(idade<18&&amigoDoDono==false){System.out.println("Nãopodeentrar");}else{System.out.println("Podeentrar");}
Esse código poderia ficar ainda mais legível, utilizando-se o operador de negação, o ! . Esseoperadortransformaoresultadodeumaexpressãobooleanadefalseparatrueeviceversa.
intidade=15;booleanamigoDoDono=true;if(idade<18&&!amigoDoDono){System.out.println("Nãopodeentrar");}else{System.out.println("Podeentrar");}
Reparenalinha3queotrechoamigoDoDono==falsevirou!amigoDoDono.Elestêmomesmovalor.
Para comparar se uma variável tem o mesmo valor que outra variável ou valor, utilizamos ooperador==.Reparequeutilizarooperador=dentrodeumifvairetornarumerrodecompilação,jáqueooperador=éodeatribuição.
intmes=1;if(mes==1){System.out.println("Vocêdeveriaestardeférias");}
.
Owhile é um comando usado para fazer um laço (loop), isto é, repetir um trecho de códigoalgumasvezes.Aideiaéqueessetrechodecódigosejarepetidoenquantoumadeterminadacondiçãopermanecerverdadeira.
intidade=15;while(idade<18){System.out.println(idade);idade=idade+1;}
Otrechodentrodoblocodowhileseráexecutadoatéomomentoemqueacondiçãoidade<18passeaserfalsa.Eissoocorreráexatamentenomomentoemqueidade==18,oquenãoofaráimprimir18.
inti=0;while(i<10){System.out.println(i);i=i+1;}
Jáowhileacimaimprimede0a9.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
Outrocomandodeloopextremamenteutilizadoéofor.Aideiaéamesmadowhile:fazerumtrechode código ser repetido enquantouma condição continuar verdadeira.Mas alémdisso, oforisola tambémumespaçopara inicializaçãodevariáveiseomodificadordessasvariáveis. Isso fazcomquefiquemmaislegíveis,asvariáveisquesãorelacionadasaoloop:
for(inicializacao;condicao;incremento){codigo;}
3.7OWHILE
Seuslivrosdetecnologiaparecemdoséculopassado?
3.8OFOR
.
Umexemploéoaseguir:
for(inti=0;i<10;i=i+1){System.out.println("olá!");}
Reparequeesseforpoderiasertrocadopor:
inti=0;while(i<10){System.out.println("olá!");i=i+1;}
Porém,ocódigodofor indicaclaramentequeavariáveli serve,emespecial,paracontrolaraquantidadedelaçosexecutados.Quandousarofor?Quandousarowhile?Dependedogostoedaocasião.
PÓSINCREMENTO++
i=i+1poderealmentesersubstituídopori++quandoisolado,porém,emalgunscasos,temosessainstruçãoenvolvidaem,porexemplo,umaatribuição:
inti=5;intx=i++;
Qualéovalordex?Odei,apósessalinha,é6.
O operador ++, quando vem após a variável, retorna o valor antigo, e incrementa (pósincremento),fazendoxvaler5.
Sevocêtivesseusadoo++antesdavariável(préincremento),oresultadoseria6:
inti=5;intx=++i;//aquixvalera6
Apesardetermoscondiçõesbooleanasnosnossoslaços,emalgummomento,podemosdecidirpararoloopporalgummotivoespecialsemqueorestodolaçosejaexecutado.
for(inti=x;i<y;i++){if(i%19==0){System.out.println("Acheiumnúmerodivisívelpor19entrexey");break;}}
Ocódigoacimavaipercorrerosnúmerosdexayepararquandoencontrarumnúmerodivisívelpor19,umavezquefoiutilizadaapalavrachavebreak.
3.9CONTROLANDOLOOPS
.
Damesmamaneira,épossívelobrigaroloopaexecutaropróximolaço.Paraissousamosapalavrachavecontinue.
for(inti=0;i<100;i++){if(i>50&&i<60){continue;}System.out.println(i);}
Ocódigoacimanãovaiimprimiralgunsnúmeros.(Quaisexatamente?)
No Java, podemos declarar variáveis a qualquer momento. Porém, dependendo de onde você asdeclarou,elavaivalerdeumdeterminadopontoaoutro.
//aquiavariávelinãoexisteinti=5;//apartirdaquielaexiste
Oescopoda variável é onomedado ao trechode código emque aquela variável existe e onde épossívelacessá-la.
Quandoabrimosumnovoblococomaschaves,asvariáveisdeclaradasalidentrosóvalematéofimdaquelebloco.
//aquiavariávelinãoexisteinti=5;//apartirdaquielaexistewhile(condicao){//oiaindavaleaquiintj=7;//ojpassaaexistir}//aquiojnãoexistemais,masoicontinuadentrodoescopo
Noblocoacima,avariáveljpáradeexistirquandoterminaoblocoondeelafoideclarada.Sevocêtentaracessarumavariávelforadeseuescopo,ocorreráumerrodecompilação.
Omesmovaleparaumif:
if(algumBooleano){inti=5;}else{
3.10ESCOPODASVARIÁVEIS
.
inti=10;}System.out.println(i);//cuidado!
Aquiavariávelinãoexisteforadoifedoelse!Sevocêdeclararavariávelantesdoif,vaihaveroutroerrodecompilação:dentrodoifedoelseavariávelestásendoredeclarada!Entãoocódigoparacompilarefazersentidofica:
inti;if(algumBooleano){i=5;}else{i=10;}System.out.println(i);
Umasituaçãoparecidapodeocorrercomofor:
for(inti=0;i<10;i++){System.out.println("olá!");}System.out.println(i);//cuidado!
Nestefor,avariávelimorreaoseutérmino,nãopodendoseracessadadeforadofor,gerandoumerrodecompilação.Sevocêrealmentequeracessarocontadordepoisdoloopterminar,precisadealgocomo:
inti;for(i=0;i<10;i++){System.out.println("olá!");}System.out.println(i);
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
Umblocotambémpodeserdeclaradodentrodeoutro.Istoé,umifdentrodeumfor,ouumfordentrodeumfor,algocomo:
Agoraéamelhorhoraderespirarmaistecnologia!
3.11UMBLOCODENTRODOOUTRO
.
while(condicao){for(inti=0;i<10;i++){//código}}
Vimos apenas os comandos mais usados para controle de fluxo. O Java ainda possui odo..whileeoswitch.Pesquisesobreelesedigaquandoéinteressanteusarcadaumdeles.
Algumasvezes,temosvárioslaçosencadeados.Podemosutilizarobreakparaquebrarolaçomaisinterno.Mas,sequisermosquebrarumlaçomaisexterno,teremosdeencadeardiversosifs e seu código ficará uma bagunça. O Java possui um artifício chamado labeled loops;pesquisesobreeles.
Oqueacontecesevocêtentardividirumnúmerointeiropor0?Epor0.0?
Existe um caminho entre os tipos primitivos que indicam se há a necessidade ou não decastingentreostipos.Porexemplo,int->long->double(umintpodesertratadocomoumdouble, mas não o contrário). Pesquise (ou teste), e posicione os outros tiposprimitivosnessefluxo.
Alémdosoperadoresde incremento,existemosdedecremento,como--i ei--.Alémdesses,vocêpodeusarinstruçõesdotipoi+=xei-=x,oqueessasinstruçõesfazem?Teste.
Mais exercícios de fixação de sintaxe. Para quem já conhece um pouco de Java, pode ser muitosimples;mas recomendamos fortemente que você faça os exercícios para se acostumar com erros decompilação,mensagensdojavac,convençãodecódigo,etc...
Apesardeextremamentesimples,precisamospraticarasintaxequeestamosaprendendo.Paracadaexercício,crieumnovoarquivocomextensão.java,edeclareaqueleestranhocabeçalho,dandonomeaumaclasseecomumblocomaindentrodele:
classExercicioX{publicstaticvoidmain(String[]args){//seuexercíciovaiaqui}}
Nãocopieecoledeumexercíciojáexistente!Aproveiteparapraticar.
1. Imprimatodososnúmerosde150a300.
3.12PARASABERMAIS
3.13EXERCÍCIOS:FIXAÇÃODESINTAXE
.
2. Imprimaasomade1até1000.
3. Imprimatodososmúltiplosde3,entre1e100.
4. Imprimaosfatoriaisde1a10.
Ofatorialdeumnúmeronén*(n-1)*(n-2)*...*1.Lembre-sedeutilizarosparênteses.
Ofatorialde0é1
Ofatorialde1é(0!)*1=1
Ofatorialde2é(1!)*2=2
Ofatorialde3é(2!)*3=6
Ofatorialde4é(3!)*4=24
Façaumforqueinicieumavariáveln(número)como1efatorial(resultado)como1evariande1até10:
intfatorial=1;for(intn=1;n<=10;n++){
}
5. Nocódigodoexercícioanterior,aumenteaquantidadedenúmerosqueterãoosfatoriaisimpressos,até20,30,40.Emumdeterminadomomento,alémdessecálculodemorar, vai começaramostrarrespostascompletamenteerradas.Porquê?
Mudedeintparalongparaveralgumamudança.
6. (opcional) Imprima os primeiros números da série de Fibonacci até passar de 100. A série deFibonacciéaseguinte:0,1,1,2,3,5,8,13,21,etc...Paracalculá-la,oprimeiroelementovale0,osegundovale1,daípordiante,on-ésimoelementovaleo(n-1)-ésimoelementosomadoao(n-2)-ésimoelemento(ex:8=5+3).
7. (opcional)Escrevaumprogramaque, dadaumavariávelx com algum valor inteiro, temosumnovoxdeacordocomaseguinteregra:
sexépar,x=x/2sexéimpar,x=3*x+1imprimex
Oprogramadevepararquandoxtiverovalorfinalde1.Porexemplo,parax=13,asaídaserá:
40->20->10->5->16->8->4->2->1
.
IMPRIMINDOSEMPULARLINHA
Umdetalhe importanteéqueumaquebrade linhaé impressa todavezquechamamosprintln.Paranãopularumalinha,usamosocódigoaseguir:
System.out.print(variavel);
8. (opcional)Imprimaaseguintetabela,usandoforsencadeados:
124369481216nn*2n*3....n*n
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
1. FaçaoexercíciodasériedeFibonacciusandoapenasduasvariáveis.
EditoraCasadoCódigocomlivrosdeumaformadiferente
3.14DESAFIOS:FIBONACCI
.
CAPÍTULO4
"Programação orientada a objetos é uma péssima ideia, que só poderia ter nascido na Califórnia." --EdsgerDijkstra
Aotérminodestecapítulo,vocêserácapazde:
dizeroqueéeparaqueserveorientaçãoaobjetos;conceituarclasses,atributosecomportamentos;entenderosignificadodevariáveiseobjetosnamemória.
Orientação a objetos é uma maneira de programar que ajuda na organização e resolve muitosproblemasenfrentadospelaprogramaçãoprocedural.
ConsideremosoclássicoproblemadavalidaçãodeumCPF.Normalmente, temosumformulário,noqualrecebemosessainformação,edepoistemosqueenviaressescaracteresparaumafunçãoquevaivalidá-lo,comonopseudocódigoabaixo:
cpf=formulario->campo_cpfvalida(cpf)
AlguémteobrigaasemprevalidaresseCPF?Vocêpode, inúmerasvezes,esquecerdechamaressevalidador.Mais: considerequevocê tem50 formulárioseprecisevalidaremtodoselesoCPF.Se suaequipetem3programadorestrabalhandonessesformulários,quemficaresponsávelporessavalidação?Todos!
Asituaçãopodepiorar:naentradadeumnovodesenvolvedor,precisaríamosavisá-loquesempredevemosvalidarocpfdeumformulário.Énessemomentoquenascemaquelesguiasdeprogramaçãopara o desenvolvedor que for entrar nesse projeto - às vezes, é um documento enorme. Em outraspalavras,tododesenvolvedorprecisaficarsabendodeumaquantidadeenormedeinformações,que,namaioriadasvezes,nãoestárealmenterelacionadoàsuapartenosistema,maseleprecisa lertudoisso,resultandoumentravemuitogrande!
Outra situação onde ficam claros os problemas da programação procedural, é quando nosencontramosnanecessidadedelerocódigoquefoiescritoporoutrodesenvolvedoredescobrircomoele funciona internamente.Um sistemabemencapsuladonãodeveria gerar essanecessidade.Emum
ORIENTAÇÃOAOBJETOSBÁSICA
4.1MOTIVAÇÃO:PROBLEMASDOPARADIGMAPROCEDURAL
.
sistemagrande,simplesmentenãotemostempodelertodoocódigoexistente.
Considerandoquevocênãoerrenessepontoequesuaequipetenhaumacomunicaçãomuitoboa(percebaquecomunicaçãoexcessivapodeserprejudicialeatrapalharoandamento),aindatemosoutroproblema:imagineque,emtodoformulário,vocêtambémquerqueaidadedoclientesejavalidada-oclienteprecisatermaisde18anos.Vamosterdecolocarumif...masonde?Espalhadoportodoseucódigo... Mesmo que se crie outra função para validar, precisaremos incluir isso nos nossos 50formuláriosjáexistentes.Qualéachancedeesquecermosemumdeles?Émuitogrande.
Aresponsabilidadedeverificarseoclientetemounãotem18anosficouespalhadaportodooseucódigo.Seriainteressantepoderconcentraressaresponsabilidadeemumlugarsó,paranãoterchancesdeesquecerisso.
Melhor ainda seria se conseguíssemos mudar essa validação e os outros programadores nemprecisassemficarsabendodisso.Emoutraspalavras,elescriariamformulárioseumúnicoprogramadorseriaresponsávelpelavalidação:osoutrosnemsabemdaexistênciadessetrechodecódigo.Impossível?Não,oparadigmadaorientaçãoaobjetosfacilitatudoisso.
Oproblemadoparadigmaprocedural é quenão existeuma forma simplesde criar conexão forteentredadosefuncionalidades.Noparadigmaorientadoaobjetosémuitofácilteressaconexãoatravésdosrecursosdapróprialinguagem.
QUAISASVANTAGENS?
Orientação a objetos vai te ajudar em muito em se organizar e escrever menos, além deconcentrar as responsabilidades nos pontos certos, flexibilizando sua aplicação, encapsulando alógicadenegócios.
Outra enorme vantagem, onde você realmente vai economizar montanhas de código, é opolimorfismodasreferências,queveremosemumposteriorcapítulo.
Nos próximos capítulos, conseguiremos enxergar toda essa vantagem, mas, primeiramente énecessárioconhecerumpoucomaisdasintaxeedacriaçãodetiposereferênciasemJava.
.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
Considere um programa para um banco, é bem fácil perceber que uma entidade extremamenteimportante para o nosso sistema é a conta. Nossa ideia aqui é generalizarmos alguma informação,juntamentecomfuncionalidadesquetodacontadeveter.
Oquetodacontatemeéimportanteparanós?
númerodacontanomedotitulardacontasaldo
Oquetodacontafazeéimportanteparanós?Istoé,oquegostaríamosde"pediràconta"?
sacaumaquantidadexdepositaumaquantidadeximprimeonomedotitulardacontadevolveosaldoatualtransfereumaquantidadexparaumaoutracontaydevolveotipodeconta
Comisso,temosoprojetodeumacontabancária.Podemospegaresseprojetoeacessarseusaldo?Não.Oquetemosaindaéoprojeto.Antes,precisamosconstruirumaconta,parapoderacessaroqueelatem,epediraelaquefaçaalgo.
JáconheceoscursosonlineAlura?
4.2CRIANDOUMTIPO
.
Reparenafigura:apesardopapeldoladoesquerdoespecificarumaConta,essaespecificaçãoéumaConta?Nósdepositamosesacamosdinheirodessepapel?Não.UtilizamosaespecificaçãodaContaparapodercriarinstânciasquerealmentesãocontas,ondepodemosrealizarasoperaçõesquecriamos.
Apesardedeclararmosquetodacontatemumsaldo,umnúmeroeumaagêncianopedaçodepapel(comoàesquerdanafigura),sãonasinstânciasdesseprojetoquerealmenteháespaçoparaarmazenaressesvalores.
Aoprojetodaconta,istoé,adefiniçãodaconta,damosonomedeclasse.Aoquepodemosconstruirapartirdesseprojeto,ascontasdeverdade,damosonomedeobjetos.
Apalavraclassevemdataxonomiadabiologia.Todososseresvivosdeumamesmaclassebiológicatêm uma série de atributos e comportamentos em comum, mas não são iguais, podem variar nosvaloresdessesatributosecomorealizamessescomportamentos.
HomoSapiensdefineumgrupodeseresquepossuemcaracterísticasemcomum,porémadefinição(a ideia, o conceito)deumHomoSapiens é um serhumano?Não.Tudo está especificadonaclasseHomoSapiens,massequisermosmandaralguémcorrer,comer,pular,precisaremosdeumainstânciadeHomoSapiens,ouentãodeumobjetodotipoHomoSapiens.
Umoutroexemplo:umareceitadebolo.Aperguntaécerteira:vocêcomeumareceitadebolo?Não.
.
Precisamos instanciá-la, criar um objeto bolo a partir dessa especificação (a classe) para utilizá-la.Podemos criar centenas de bolos a partir dessa classe (a receita, no caso), eles podem ser bemsemelhantes,algunsatéidênticos,massãoobjetosdiferentes.
Podemos fazer milhares de analogias semelhantes. A planta de uma casa é uma casa?Definitivamentenão.Nãopodemosmorardentrodaplantadeumacasa,nempodemosabrirsuaportaou pintar suas paredes. Precisamos, antes, construir instâncias a partir dessa planta. Essas instâncias,sim,podemospintar,decoraroumorardentro.
Pode parecer óbvio,mas a dificuldade inicial do paradigma da orientação a objetos é justo saberdistinguiroque é classe eoqueéobjeto.É comumo inicianteutilizar,obviamentede formaerrada,essasduaspalavrascomosinônimos.
Vamoscomeçar apenas comoqueumaConta tem, enão comoque ela faz (veremos logo emseguida).
Umtipodesses,comooespecificadodeContaacima,podeserfacilmentetraduzidoparaJava:
classConta{intnumero;Stringtitular;doublesaldo;
//..}
STRING
StringéumaclasseemJava.Elaguardaumacadeiadecaracteres,umafrasecompleta.Comoestamosaindaaprendendooqueéumaclasse,entenderemoscomdetalhesaclasseStringapenasemcapítulosposteriores.
Porenquanto,declaramosoquetodacontadeveter.Estessãoosatributosquetodaconta,quandocriada,vaiter.Reparequeessasvariáveisforamdeclaradasforadeumbloco,diferentedoquefazíamosquandotinhaaquelemain.Quandoumavariávelédeclaradadiretamentedentrodoescopodaclasse,échamadadevariáveldeobjeto,ouatributo.
JátemosumaclasseemJavaqueespecificaoquetodoobjetodessaclassedeveter.Mascomousá-la?Alémdessaclasse,aindateremosoPrograma.javaeapartirdeleéquevamosutilizaraclasseConta.
4.3UMACLASSEEMJAVA
4.4CRIANDOEUSANDOUMOBJETO
.
Paracriar (construir, instanciar)umaConta, bastausar apalavra chavenew.Devemosutilizartambémosparênteses,quedescobriremosoquefazemexatamenteemumcapítuloposterior:
classPrograma{publicstaticvoidmain(String[]args){newConta();}}
Bem,ocódigoacimacriaumobjetodotipoConta,mascomoacessaresseobjetoquefoicriado?Precisamosteralgumaformadenosreferenciarmosaesseobjeto.Precisamosdeumavariável:
classPrograma{publicstaticvoidmain(String[]args){ContaminhaConta;minhaConta=newConta();}}
PodeparecerestranhoescrevermosduasvezesConta:umaveznadeclaraçãodavariáveleoutraveznousodonew.Masháummotivo,queembreveentenderemos.
AtravésdavariávelminhaConta,podemosacessaroobjetorecémcriadoparaalterarseutitular,seusaldo,etc:
classPrograma{publicstaticvoidmain(String[]args){ContaminhaConta;minhaConta=newConta();
minhaConta.titular="Duke";minhaConta.saldo=1000.0;
System.out.println("Saldoatual:"+minhaConta.saldo);}}
É importante fixarqueoponto foiutilizadopara acessar algo emminhaConta.AminhaContapertenceaoDuke,etemsaldodemilreais.
.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
Dentro da classe, também declararemos o que cada conta faz e como isto é feito - oscomportamentosquecadaclassetem,istoé,oqueelafaz.Porexemplo,dequemaneiraqueumaContasacadinheiro?EspecificaremosissodentrodaprópriaclasseConta,enãoemumlocaldesatreladodasinformações da própria Conta. É por isso que essas "funções" são chamadas de métodos. Pois é amaneiradefazerumaoperaçãocomumobjeto.
Queremos criar um método que saca uma determinada quantidade e não devolve nenhumainformaçãoparaquemacionaressemétodo:
classConta{doublesalario;//...outrosatributos...
voidsaca(doublequantidade){doublenovoSaldo=this.saldo-quantidade;this.saldo=novoSaldo;}}
A palavra chave void diz que, quando você pedir para a conta sacar uma quantia, nenhumainformaçãoseráenviadadevoltaaquempediu.
Quando alguém pedir para sacar, ele também vai dizer quanto quer sacar. Por isso precisamosdeclararométodocomalgodentrodosparênteses-oquevaiaídentroéchamadodeargumento dométodo(ouparâmetro).Essavariáveléumavariávelcomum,chamadatambémdetemporáriaoulocal,pois,aofinaldaexecuçãodessemétodo,eladeixadeexistir.
SaberinglêsémuitoimportanteemTI
4.5MÉTODOS
.
Dentrodométodo,estamosdeclarandoumanovavariável.Essavariável,assimcomooargumento,vaimorrernofimdométodo,poisesteéseuescopo.Nomomentoquevamosacessarnossoatributo,usamos a palavra chave this para mostrar que esse é um atributo, e não uma simples variável.(veremosdepoisqueéopcional)
Repare que, nesse caso, a conta poderia estourar um limite fixado pelo banco.Mais para frente,evitaremosessasituação,edeumamaneiramuitoelegante.
Damesmaforma,temosométodoparadepositaralgumaquantia:
classConta{//...outrosatributosemétodos...
voiddeposita(doublequantidade){this.saldo+=quantidade;}}
Observequenãousamosumavariávelauxiliare,alémdisso,usamosaabreviação+=paradeixarométodobemsimples.O+= somaquantidade aovalor antigodo saldo e guardanopróprio saldo, ovalorresultante.
Paramandarumamensagemaoobjetoepedirqueeleexecuteummétodo,tambémusamosoponto.Otermousadoparaissoéinvocaçãodemétodo.
Ocódigoaseguirsacadinheiroedepoisdepositaoutraquantiananossaconta:
classTestaAlgunsMetodos{publicstaticvoidmain(String[]args){//criandoacontaContaminhaConta;minhaConta=newConta();
//alterandoosvaloresdeminhaContaminhaConta.titular="Duke";minhaConta.saldo=1000;
//saca200reaisminhaConta.saca(200);
//deposita500reaisminhaConta.deposita(500);System.out.println(minhaConta.saldo);}}
Uma vez que seu saldo inicial é 1000 reais, se sacarmos 200 reais, depositarmos 500 reais eimprimirmosovalordosaldo,oqueseráimpresso?
Ummétodosempretemquedefiniroqueretorna,nemquedefinaquenãoháretorno,comonos
4.6MÉTODOSCOMRETORNO
.
exemplosanterioresondeestávamosusandoovoid.
Ummétodopoderetornarumvalorparaocódigoqueochamou.Nocasodonossométodosaca,podemosdevolverumvalorbooleanoindicandoseaoperaçãofoibemsucedida.
classConta{//...outrosmétodoseatributos...
booleansaca(doublevalor){if(this.saldo<valor){returnfalse;}else{this.saldo=this.saldo-valor;returntrue;}}}
Adeclaraçãodométodomudou!Ométodosacanãotemvoidna frente. Istoquerdizerque,quando é acessado, ele devolve algum tipo de informação.No caso, umboolean. A palavra chavereturnindicaqueométodovaiterminarali,retornandotalinformação.
Exemplodeuso:
minhaConta.saldo=1000;booleanconsegui=minhaConta.saca(2000);if(consegui){System.out.println("Conseguisacar");}else{System.out.println("Nãoconseguisacar");}
Ouentão,possoeliminaravariáveltemporária,sedesejado:
minhaConta.saldo=1000;if(minhaConta.saca(2000)){System.out.println("Conseguisacar");}else{System.out.println("Nãoconseguisacar");}
Maisadiante,veremosquealgumasvezesémaisinteressantelançarumaexceção(exception)nessescasos.
.
Meuprogramapodemanternamemórianãoapenasumaconta,comomaisdeuma:
classTestaDuasContas{publicstaticvoidmain(String[]args){
ContaminhaConta;minhaConta=newConta();minhaConta.saldo=1000;
ContameuSonho;meuSonho=newConta();meuSonho.saldo=1500000;}}
Quandodeclaramosumavariávelparaassociaraumobjeto,naverdade,essavariávelnãoguardaoobjeto,esimumamaneiradeacessá-lo,chamadadereferência.
Épor essemotivoque,diferentedos tipos primitivos comoint elong, precisamosdarnewdepoisdedeclaradaavariável:
publicstaticvoidmain(String[]args){Contac1;c1=newConta();
Contac2;c2=newConta();}
Ocorretoaqui,édizerquec1serefereaumobjeto.Nãoécorretodizerquec1éumobjeto,poisc1éumavariávelreferência,apesarde,depoisdeumtempo,osprogramadoresJavafalarem"TenhoumobjetocdotipoConta",masapenasparaencurtarafrase"TenhoumareferênciacaumobjetodotipoConta".
Basta lembrar que, em Java,umavariávelnunca éumobjeto.Nãohá, no Java, umamaneiradecriarmosoqueéconhecidocomo"objetopilha"ou"objetolocal",poistodoobjetoemJava,semexceção,éacessadoporumavariávelreferência.
Essecódigonosdeixanaseguintesituação:
Contac1;c1=newConta();
Contac2;c2=newConta();
4.7OBJETOSSÃOACESSADOSPORREFERÊNCIAS
.
Internamente,c1ec2vãoguardarumnúmeroqueidentificaemqueposiçãodamemóriaaquelaContaseencontra.Dessamaneira,aoutilizarmoso"."paranavegar,oJavavaiacessaraContaqueseencontranaquelaposiçãodememória,enãoumaoutra.
Para quem conhece, é parecido com um ponteiro, porém você não podemanipulá-lo como umnúmeroenemutilizá-loparaaritmética,elaétipada.
Umoutroexemplo:
classTestaReferencias{publicstaticvoidmain(String[]args){Contac1=newConta();c1.deposita(100);
Contac2=c1;//linhaimportante!c2.deposita(200);
System.out.println(c1.saldo);System.out.println(c2.saldo);}}
Qualéoresultadodocódigoacima?Oqueapareceaorodar?
Oqueaconteceaqui?Ooperador=copiaovalordeumavariável.Masqualéovalordavariávelc1? É o objeto?Não.Na verdade, o valor guardado é a referência (endereço) de onde o objeto seencontranamemóriaprincipal.
Namemória,oqueacontecenessecaso:
Contac1=newConta();Contac2=c1;
.
Quandofizemosc2=c1,c2passaafazerreferênciaparaomesmoobjetoquec1 referencianesseinstante.
Então,nessecódigoemespecífico,quandoutilizamosc1ouc2estamosnosreferindoexatamenteaomesmoobjeto!Elassãoduasreferênciasdistintas,porémapontamparaomesmoobjeto!Compará-lascom"=="vainosretornartrue,poisovalorqueelascarregaméomesmo!
Outraformadeperceber,équedemosapenasumnew,entãosópodehaverumobjetoContanamemória.
Atenção:nãoestamosdiscutindoaquiautilidadedefazerumareferênciaapontarpromesmoobjetoque outra. Essa utilidade ficará mais clara quando passarmos variáveis do tipo referência comoargumentoparamétodos.
NEW
Oqueexatamentefazonew?
Onewexecutaumasériedetarefas,queveremosmaisadiante.
Mas,paramelhorentenderasreferênciasnoJava,saibaqueonew,depoisdealocaramemóriaparaesseobjeto,devolveuma "flecha", istoé,umvalorde referência.Quandovocêatribui issoaumavariável,essavariávelpassaasereferirparaessemesmoobjeto.
Podemosentãoveroutrasituação:
publicstaticvoidmain(String[]args){Contac1=newConta();c1.titular="Duke";c1.saldo=227;
Contac2=newConta();c2.titular="Duke";c2.saldo=227;
if(c1==c2){System.out.println("Contasiguais");}}
Ooperador==comparaoconteúdodasvariáveis,masessasvariáveisnãoguardamoobjeto,esimoendereçoemqueeleseencontra.Comoemcadaumadessasvariáveisguardamosduascontascriadasdiferentemente,elasestãoemespaçosdiferentesdamemória,oquefazotestenoifvalerfalse.Ascontas podem ser equivalentes no nosso critério de igualdade, porém elas não são omesmo objeto.Quandosetratadeobjetos,podeficarmaisfácilpensarqueo==comparaseosobjetos(referências,naverdade)sãoomesmo,enãosesãoiguais.
.
Para saber se dois objetos têm omesmo conteúdo, você precisa comparar atributo por atributo.Veremosumasoluçãomaiseleganteparaissotambém.
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
Esequisermosterummétodoquetransferedinheiroentreduascontas?Podemosficartentadosacriarummétodoquerecebedoisparâmetros:conta1econta2dotipoConta.Mascuidado:assimestamospensandodemaneiraprocedural.
Aideiaéque,quandochamarmosométodotransfere,játeremosumobjetodotipoConta(othis),portantoométodo recebeapenasum parâmetrodo tipoConta, aContadestino (alémdovalor):
classConta{
//atributosemétodos...
voidtransfere(Contadestino,doublevalor){
AprendasedivertindonaAluraStart!
4.8OMÉTODOTRANSFERE()
.
this.saldo=this.saldo-valor;destino.saldo=destino.saldo+valor;}}
Para deixar o código mais robusto, poderíamos verificar se a conta possui a quantidade a sertransferidadisponível.Paraficaraindamais interessante,vocêpodechamarosmétodosdeposita esacajáexistentesparafazeressatarefa:
classConta{
//atributosemétodos...
booleantransfere(Contadestino,doublevalor){booleanretirou=this.saca(valor);if(retirou==false){//nãodeuprasacar!returnfalse;}else{destino.deposita(valor);returntrue;}}}
QuandopassamosumaContacomoargumento,oqueseráqueacontecenamemória?Seráqueoobjetoéclonado?
No Java, a passagem de parâmetro funciona como uma simples atribuição como no uso do "=".Então,esseparâmetrovaicopiarovalordavariáveldotipoContaqueforpassadocomoargumento.Equaléovalordeumavariáveldessas?Seuvaloréumendereço,umareferência,nuncaumobjeto.Porissonãohácópiadeobjetosaqui.
.
Esseúltimocódigopoderiaserescritocomumasintaxemuitomaissucinta.Como?
TRANSFEREPARA
PercebaqueonomedestemétodopoderiasertransfereParaaoinvésdesótransfere.Achamadadométodo ficamuitomaisnatural, épossível lera fraseemportuguêsqueela temumsentido:
conta1.transferePara(conta2,50);
Aleituradestecódigoseria"Conta1transfereparaconta250reais".
As variáveis do tipo atributo, diferentemente das variáveis temporárias (declaradas dentro de ummétodo),recebemumvalorpadrão.Nocasonumérico,valem0,nocasodeboolean,valemfalse.
Vocêtambémpodedarvaloresdefault,comosegue:
classConta{intnumero=1234;Stringtitular="Duke";doublesaldo=1000.0;}
Nesse caso, quando você criar uma conta, seus atributos já estão "populados" com esses valorescolocados.
ImaginequecomecemosaaumentarnossaclasseContaeadicionarnome,sobrenomeecpfdotitulardaconta.Começaríamosatermuitosatributos...e,sevocêpensardireito,umaContanãotemnome,nemsobrenomenemcpf,quemtemessesatributoséumCliente.Entãopodemoscriarumanovaclasseefazerumacomposição
Seus atributos também podem ser referências para outras classes. Suponha a seguinte classeCliente:
classCliente{Stringnome;Stringsobrenome;Stringcpf;}
classConta{intnumero;doublesaldo;Clientetitular;//..}
4.9CONTINUANDOCOMATRIBUTOS
.
Edentrodomaindaclassedeteste:
classTeste{publicstaticvoidmain(String[]args){ContaminhaConta=newConta();Clientec=newCliente();minhaConta.titular=c;//...}}
Aqui,simplesmentehouveumaatribuição.Ovalordavariávelcécopiadoparaoatributotitulardoobjeto aoqualminhaConta se refere. Emoutras palavras,minhaConta tem uma referência aomesmoClientequecserefere,epodeseracessadoatravésdeminhaConta.titular.
Vocêpoderealmentenavegarsobretodaessaestruturadeinformação,sempreusandooponto:
ClienteclienteDaMinhaConta=minhaConta.titular;clienteDaMinhaConta.nome="Duke";
Ouainda,podefazerissodeumaformamaisdiretaeatémaiselegante:
minhaConta.titular.nome="Duke";
Umsistemaorientadoaobjetoséumgrandeconjuntodeclassesquevaisecomunicar,delegandoresponsabilidadesparaquemformaisaptoarealizardeterminadatarefa.AclasseBancousaaclasseContaqueusaaclasseCliente,queusaaclasseEndereco.Dizemosqueessesobjetoscolaboram,trocandomensagensentresi.Porissoacabamostendomuitasclassesemnossosistema,eelascostumamterumtamanhorelativamentecurto.
Mas,esedentrodomeucódigoeunãodessenewemClienteetentasseacessá-lodiretamente?
classTeste{publicstaticvoidmain(String[]args){ContaminhaConta=newConta();
minhaConta.titular.nome="Manoel";//...}}
Quando damos new em um objeto, ele o inicializa com seus valores default, 0 para números,falseparabooleanenullparareferências.nulléumapalavrachaveemjava,queindicaumareferênciaparanenhumobjeto.
Se,emalgumcaso,vocêtentaracessarumatributooumétododealguémqueestásereferenciando
.
paranull,vocêreceberáumerroduranteaexecução(NullPointerException,queveremosmaisàfrente).Daparaperceber,então,queonewnãotrazumefeitocascata,amenosquevocêdêumvalordefault(ouuseconstrutores,quetambémveremosmaisafrente):
classConta{intnumero;doublesaldo;Clientetitular=newCliente();//quandochamaremnewConta,//haveraumnewClienteparaele.}
Comessecódigo,todanovaContacriadajáteráumnovoClienteassociado,semnecessidadedeinstanciá-lologoemseguidadainstanciaçãodeumaConta.Qualalternativavocêdeveusar?Dependedo caso: para todanovaConta você precisa de umnovoCliente? É essa pergunta que deve serrespondida.Nessenossocasoarespostaénão,masdependedonossoproblema.
Atenção:paraquemnãoestáacostumadocomreferências,podeserbastanteconfusopensarsempreem como os objetos estão namemória para poder tirar as conclusões de o que ocorrerá ao executardeterminado código, por mais simples que ele seja. Com tempo, você adquire a habilidade derapidamente saber o efeito de atrelar as referências, sem ter de gastar muito tempo para isso. Éimportante,nessecomeço,vocêestarsemprepensandonoestadodamemória.Erealmentelembrarque,noJava"umavariávelnuncacarregaumobjeto,esimumareferênciaparaele"facilitamuito.
AlémdoBancoqueestamoscriando,vamosvercomoficariamcertasclassesrelacionadasaumafábrica de carros. Vamos criar uma classe Carro , com certos atributos, que descrevem suascaracterísticas,ecomcertosmétodos,quedescrevemseucomportamento.
classCarro{Stringcor;Stringmodelo;doublevelocidadeAtual;doublevelocidadeMaxima;
//ligaocarrovoidliga(){System.out.println("Ocarroestáligado");}
//aceleraumacertaquantidadevoidacelera(doublequantidade){doublevelocidadeNova=this.velocidadeAtual+quantidade;this.velocidadeAtual=velocidadeNova;}
//devolveamarchadocarrointpegaMarcha(){if(this.velocidadeAtual<0){return-1;}if(this.velocidadeAtual>=0&&this.velocidadeAtual<40){
4.10PARASABERMAIS:UMAFÁBRICADECARROS
.
return1;}if(this.velocidadeAtual>=40&&this.velocidadeAtual<80){return2;}return3;}}
VamostestarnossoCarroemumnovoprograma:
classTestaCarro{publicstaticvoidmain(String[]args){CarromeuCarro;meuCarro=newCarro();meuCarro.cor="Verde";meuCarro.modelo="Fusca";meuCarro.velocidadeAtual=0;meuCarro.velocidadeMaxima=80;
//ligaocarromeuCarro.liga();
//aceleraocarromeuCarro.acelera(20);System.out.println(meuCarro.velocidadeAtual);}}
NossocarropodecontertambémumMotor:
classMotor{intpotencia;Stringtipo;}
classCarro{Stringcor;Stringmodelo;doublevelocidadeAtual;doublevelocidadeMaxima;Motormotor;
//..}
Podemos, criar diversos Carros e mexer com seus atributos e métodos, assim como fizemos noexemplodoBanco.
.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
Quando declaramos uma classe, um método ou um atributo, podemos dar o nome quequisermos,seguindoumaregra.Porexemplo,onomedeummétodonãopodecomeçarcomumnúmero.Pesquisesobreessasregras.
Comovocêpodeterreparado,sempredamosnomesàsvariáveiscomletrasminúsculas.Équeexistemconvençõesdecódigo,dadaspelaOracle,parafacilitaralegibilidadedocódigoentreprogramadores. Essa convenção émuito seguida. Leia sobre ela pesquisando por "java codeconventions".
Énecessáriousar a palavra chavethis quando for acessar um atributo? Para que, então,utilizá-la?
Existe um padrão para representar suas classes em diagramas, que é amplamente utilizado,chamadoUML.Pesquisesobreele.
Omodelodacontaaseguirseráutilizadoparaosexercíciosdospróximoscapítulos.
O objetivo aqui é criar um sistema para gerenciar as contas de umBanco.Os exercícios dessecapítulosãoextremamenteimportantes.
1. Modele uma conta. A ideia aqui é apenas modelar, isto é, só identifique que informações sãoimportantes.DesenhenopapeltudooqueumaContatemetudooqueelafaz.Eladeveteronomedotitular(String),onúmero(int), a agência (String), o saldo (double) e umadatadeabertura (String).Alémdisso, ela deve fazer as seguintes ações: saca, para retirar um valor do
Seuslivrosdetecnologiaparecemdoséculopassado?
4.11UMPOUCOMAIS...
4.12EXERCÍCIOS:ORIENTAÇÃOAOBJETOS
.
saldo;deposita,paraadicionarumvaloraosaldo;calculaRendimento,paradevolverorendimentomensaldessaconta.
2. Transforme o modelo acima em uma classe Java. Teste-a, usando uma outra classe que tenha omain.Vocêdeve criar a classeda conta comonomeConta,maspodenomear comoquiser aclassedetestes,contudo,eladevepossuirométodomain.
AclasseContadeveconterpelomenososseguintesmétodos:
sacaquerecebeumvalorcomoparâmetroeretiraessevalordosaldodacontadepositaquerecebeumvalorcomoparâmetroeadicionaessevaloraosaldodaconta
calculaRendimentoquenãorecebeparâmetroalgumedevolveovalordosaldomultiplicadopor0.1
Umesboçodaclasse:
classConta{
doublesaldo;//seusoutrosatributosemétodos
voidsaca(doublevalor){//oquefazeraquidentro?}
voiddeposita(doublevalor){//oquefazeraquidentro?}
doublecalculaRendimento(){//oquefazeraquidentro?}}
Você pode (e deve) compilar seu arquivo java sem que você ainda tenha terminado sua classeConta.Issoevitaráquevocêrecebadezenasdeerrosdecompilaçãodeumavezsó.CrieaclasseConta, coloqueseusatributose,antesdecolocarqualquermétodo,compileoarquivo java.OarquivoConta.classserágerado,masnãopodemos"executá-lo"jáqueessaclassenãotemummain.Dequalquerforma,avantageméqueassimverificamosquenossaclasseConta jáestátomandoformaeestáescritaemsintaxecorreta.
Esseéumprocessoincremental.Procuredesenvolverassimseusexercícios,paranãodescobrirsónofimdocaminhoquealgoestavamuitoerrado.
Umesboçodaclassequepossuiomain:
classTestaConta{
publicstaticvoidmain(String[]args){Contac1=newConta();
.
c1.titular="Hugo";c1.numero=123;c1.agencia="45678-9";c1.saldo=50.0;c1.dataDeAbertura="04/06/2015";
c1.deposita(100.0);System.out.println("saldoatual:"+c1.saldo);System.out.println("rendimentomensal:"+c1.calculaRendimento());}}
Incremente essa classe. Faça outros testes, imprima outros atributos e invoque osmétodos quevocêcriouamais.
Lembre-se de seguir a convenção java, isso é importantíssimo. Isto é, preste atenção nasmaiúsculas e minúsculas, seguindo o seguinte exemplo: nomeDeAtributo, nomeDeMetodo ,nomeDeVariavel,NomeDeClasse,etc...
TODASASCLASSESNOMESMOARQUIVO?
Vocêatépodecolocartodasasclassesnomesmoarquivoeapenascompilaressearquivo.Elevaigerarum.classparacadaclassepresentenele.
Porém, por umaquestãode organização, é boa prática criar um arquivo.java paracadaclasse.Emcapítulosposteriores, veremos tambémdeterminadoscasosnosquaisvocêseráobrigadoadeclararcadaclasseemumarquivoseparado.
Essa separação não é importante nesse momento do aprendizado, mas se quiser irpraticandosemterquecompilarclasseporclasse,vocêpodedizerparaojavaccompilartodososarquivosjavadeumavez:
javac*.java
3. CrieummétodorecuperaDadosParaImpressao(),quenãorecebeparâmetromasdevolveotextocomtodasasinformaçõesdanossacontaparaefetuarmosaimpressão.
Dessamaneira,vocênãoprecisa ficarcopiandoecolandoummontedeSystem.out.println()paracadamudançaetestequefizercomcadaumdeseusfuncionários,vocêsimplesmentevaifazer:
Contac1=newConta();//brincadeirascomc1....System.out.println(c1.recuperaDadosParaImpressao());
VeremosmaisafrenteométodotoString,queéumasoluçãomuitomaiseleganteparamostrararepresentaçãodeumobjetocomoString,alémdenãojogartudoproSystem.out (sósevocêdesejar).
.
Oesqueletodométodoficariaassim:
classConta{
//seusoutrosatributosemétodos
StringrecuperaDadosParaImpressao(){Stringdados="Titular:"+this.titular;dados+="\nNúmero:"+this.numero;//imprimiraquiosoutrosatributos...//tambémpodeimprimirthis.calculaRendimento()returndados;}}
4. Construaduascontascomonewecompare-oscomo==.Eseelestiveremosmesmosatributos?Paraissovocêvaiprecisarcriaroutrareferência:
Contac1=newConta();c1.titular="Danilo";c1.saldo=100;
Contac2=newConta();c2.titular="Danilo";c2.saldo=100;
if(c1==c2){System.out.println("iguais");}else{System.out.println("diferentes");}
5. Crieduasreferênciasparaamesmaconta,compare-oscomo==.Tiresuasconclusões.Paracriarduasreferênciaspramesmaconta:
Contac1=newConta():c1.titular="Hugo";c1.saldo=100;
Contac2=c1;
Oqueacontececomoifdoexercícioanterior?
6. (opcional)EmvezdeutilizarumaStringpararepresentaradata,crieumaoutraclasse,chamadaData.Elapossui3camposint,paradia,mêseano.Façacomquesuacontapasseausá-la. (éparecidocomoúltimoexemplodaexplicação,emqueaConta passou a ter referênciaparaumCliente).
classConta{DatadataDeAbertura;//qualéovalordefaultaqui?//seusoutrosatributosemétodos}
classData{intdia;intmes;intano;}
.
ModifiquesuaclasseTestaContaparaquevocêcrieumaDataeatribuaelaaConta:
Contac1=newConta();//...Datadata=newData();//ligação!c1.dataDeAbertura=data;
FaçaodesenhodoestadodamemóriaquandocriarmosumConta.
7. (opcional)ModifiqueseumétodorecuperaDadosParaImpressaoparaqueeledevolvaovalordadataDeAberturadaquelaConta:
classConta{
//seusoutrosatributosemétodosDatadataDeAbertura;
StringrecuperaDadosParaImpressao(){Stringdados="\nTitular:"+this.titular;//imprimiraquiosoutrosatributos...
dados+="\nDia:"+this.dataDeAbertura.dia;dados+="\nMês:"+this.dataDeAbertura.mes;dados+="\nAno:"+this.dataDeAbertura.ano;returndados;}}
Teste-o. O que acontece se chamarmos o método recuperaDadosParaImpressao antes deatribuirmosumadataparaestaConta?
8. (opcional) O que acontece se você tentar acessar um atributo diretamente na classe? Como, porexemplo:
Conta.saldo=1234;
Essecódigofazsentido?Eeste:
Conta.calculaRendimento();
FazsentidoperguntarparaoesquemadaContaseuvaloranual?
9. (opcional-avançado)CrieummétodonaclasseDataquedevolvaovalorformatadodadata,istoé,devolvaumaStringcom"dia/mes/ano".IssoparaqueométodorecuperaDadosParaImpressaodaclasseContapossaficarassim:
classConta{//atributosemetodos
StringrecuperaDadosParaImpressao(){//imprimeoutrosatributos...dados+="\nDatadeabertura:"+this.dataDeAbertura.formatada();returndados;}}
.
1. Ummétodopode chamar elemesmo.Chamamos issoderecursão.Vocêpoderesolver a série deFibonacciusandoummétodoquechamaelemesmo.Oobjetivoévocêcriarumaclasse,quepossaserusadadaseguintemaneira:
Fibonaccifibonacci=newFibonacci();for(inti=1;i<=6;i++){intresultado=fibonacci.calculaFibonacci(i);System.out.println(resultado);}
AquiimprimiráasequênciadeFibonacciatéasextaposição,istoé:1,1,2,3,5,8.
EstemétodocalculaFibonacci não pode ter nenhum laço, só pode chamar elemesmo comométodo.Pensenelecomoumafunção,queusaaprópriafunçãoparacalcularoresultado.
2. Porqueomodoacimaéextremamentemaislentoparacalcularasériedoqueomodoiterativo(queseusaumlaço)?
3. Escreva o método recursivo novamente, usando apenas uma linha. Para isso, pesquise sobre ooperadorcondicionalternário.(ternaryoperator)
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
Oobjetivodosexercíciosaseguiréfixaroconceitodeclasseseobjetos,métodoseatributos.Dadaaestruturadeumaclasse,bastatraduzi-laparaalinguagemJavaefazerusodeumobjetodamesmaemumprogramasimples.
Sevocêestácomdificuldadeemalgumapartedessecapítulo,aproveiteetreinetudooquevimosnospequenosprogramasabaixo:
Programa1
4.13DESAFIOS
Agoraéamelhorhoraderespirarmaistecnologia!
4.14FIXANDOOCONHECIMENTO
.
Classe:PessoaAtributos:nome,idade.Método:voidfazAniversario()
Crieumapessoa,coloqueseunomee idade iniciais, façaalgunsaniversários(aumentandoaidade)eimprimaseunomeesuaidade.
Programa2
Classe:PortaAtributos:aberta,cor,dimensaoX,dimensaoY,dimensaoZMétodos:voidabre()voidfecha()voidpinta(Strings)booleanestaAberta()
Crieumaporta,abraefecheamesma,pinte-adediversascores,alteresuasdimensõeseuseométodoestaAbertaparaverificarseelaestáaberta.
Programa3
Classe:CasaAtributos:cor,porta1,porta2,porta3Método:voidpinta(Strings),intquantasPortasEstaoAbertas()
Crieumacasaepinte-a.Crietrêsportasecoloque-asnacasa;abraefecheasmesmascomodesejar.UtilizeométodoquantasPortasEstaoAbertasparaimprimironúmerodeportasabertas.
.
CAPÍTULO5
"Amarcadohomem imaturo éque ele quermorrernobrementeporuma causa, enquantoamarcadohomemmaduroéquerervivermodestamenteporuma."--J.D.Salinger
Aotérminodessecapítulo,vocêserácapazde:
controlar o acesso aos seus métodos, atributos e construtores através dos modificadoresprivateepublic;escrevermétodosdeacessoaatributosdotipogettersesetters;escreverconstrutoresparasuasclasses;utilizarvariáveisemétodosestáticos.
Um dos problemasmais simples que temos no nosso sistema de contas é que ométodo sacapermite sacar mesmo que o saldo seja insuficiente. A seguir você pode lembrar como está a classeConta:
classConta{Stringtitular;intnumero;doublesaldo;
//..
voidsaca(doublevalor){this.saldo=this.saldo-valor;}}
Aclasseaseguirmostracomoépossívelultrapassarolimitedesaqueusandoométodosaca:
classTestaContaEstouro1{publicstaticvoidmain(String[]args){ContaminhaConta=newConta();minhaConta.saldo=1000.0;minhaConta.saca(50000);//saldoésó1000!!}}
Podemosincluirumifdentrodonossométodosaca()paraevitarasituaçãoqueresultariaem
MODIFICADORESDEACESSOEATRIBUTOSDECLASSE
5.1CONTROLANDOOACESSO
.
umacontaemestadoinconsistente,comseusaldoabaixode0.Fizemosissonocapítulodeorientaçãoaobjetosbásica.
Apesardemelhorarbastante,aindatemosumproblemamaisgrave:ninguémgarantequeousuárioda classe vai sempre utilizar o método para alterar o saldo da conta. O código a seguir faz issodiretamente:
classTestaContaEstouro2{publicstaticvoidmain(String[]args){ContaminhaConta=newConta();minhaConta.saldo=-200;//saldoestáabaixode0}}
Comoevitarisso?Umaideiasimplesseriatestarsenãoestamossacandoumvalormaiorqueosaldotodavezqueformosalterá-lo:
classTestaContaEstouro3{
publicstaticvoidmain(String[]args){//aContaContaminhaConta=newConta();minhaConta.saldo=100;
//queromudarosaldopara-200doublenovoSaldo=-200;
//testaseonovoSaldoéválidoif(novoSaldo<0){//System.out.println("Nãopossomudarparaessesaldo");}else{minhaConta.saldo=novoSaldo;}}}
Essecódigoiriaserepetirao longodetodanossaaplicaçãoe,pior,alguémpodeesquecerdefazeressacomparaçãoemalgummomento,deixandoacontanasituaçãoinconsistente.AmelhorformaderesolverissoseriaforçarquemusaaclasseContaainvocarométodosacaenãopermitiroacessodiretoaoatributo.ÉomesmocasodavalidaçãodeCPF.
Para fazer issono Java,bastadeclararqueos atributosnãopodemser acessadosde forada classeatravésdapalavrachaveprivate:
classConta{privatedoublesaldo;//...}
privateéummodificadordeacesso(tambémchamadodemodificadordevisibilidade).
Marcandoumatributo comoprivado, fechamoso acesso aomesmo em relação a todas as outrasclasses,fazendocomqueoseguintecódigonãocompile:
classTestaAcessoDireto{
.
publicstaticvoidmain(String[]args){ContaminhaConta=newConta();//nãocompila!vocênãopodeacessaroatributoprivadodeoutraclasseminhaConta.saldo=1000;}}
TesteAcessoDireto.java:5saldohasprivateaccessinContaminhaConta.saldo=1000;^1error
Na orientação a objetos, é prática quase que obrigatória proteger seus atributos com private.(discutiremosoutrosmodificadoresdeacessoemoutroscapítulos).
Cadaclasseéresponsávelporcontrolarseusatributos,portantoeladevejulgarseaquelenovovaloréválido ou não! Esta validação não deve ser controlada por quem está usando a classe e sim por elamesma, centralizando essa responsabilidade e facilitando futurasmudançasno sistema.Muitasoutrasvezes nem mesmo queremos que outras classes saibam da existência de determinado atributo,escondendo-oporcompleto,jáqueeledizrespeitoaofuncionamentointernodoobjeto.
Repareque,queminvocaométodosacanãofazamenorideiadequeexisteumaverificaçãoparaovalordosaque.Paraquemforusaressaclasse,bastasaberoqueométodofazenãocomoexatamenteeleofaz(oqueummétodofazésempremaisimportantedoquecomoelefaz:mudaraimplementaçãoéfácil,jámudaraassinaturadeummétodovaigerarproblemas).
A palavra chave private também pode ser usada para modificar o acesso a um método. Talfuncionalidade é utilizada em diversos cenários: quando existe um método que serve apenas paraauxiliar a própria classe e quando há código repetido dentro de doismétodos da classe são osmaiscomuns. Sempre devemos expôr o mínimo possível de funcionalidades, para criar um baixoacoplamentoentreasnossasclasses.
Damesmamaneira que temosoprivate, temosomodificadorpublic, quepermite a todosacessaremumdeterminadoatributooumétodo:
classConta{//...publicvoidsaca(doublevalor){//possosacaratésaldoif(valor>this.saldo){System.out.println("Nãopossosacarumvalormaiorqueosaldo!");}else{this.saldo=this.saldo-valor;}}}
.
EQUANDONÃOHÁMODIFICADORDEACESSO?
Atéagora,tínhamosdeclaradovariáveisemétodossemnenhummodificadorcomoprivateepublic . Quando isto acontece, o seu método ou atributo fica num estado de visibilidadeintermediárioentreoprivateeopublic,queveremosmaisprafrente,nocapítulodepacotes.
Émuitocomum,efaztodosentido,queseusatributossejamprivateequasetodosseusmétodossejampublic(nãoéumaregra!).Destaforma,todaconversadeumobjetocomoutroéfeitaportrocademensagens,istoé,acessandoseusmétodos.Algomuitomaiseducadoquemexerdiretamenteemumatributoquenãoéseu!
Melhorainda!OdiaemqueprecisarmosmudarcomoérealizadoumsaquenanossaclasseConta,adivinhe onde precisaríamosmodificar? Apenas nométodo saca, o que faz pleno sentido. Comoexemplo,imaginecobrarCPMFdecadasaque:bastavocêmodificarali,enenhumoutrocódigo,foraaclasseConta, precisará ser recompilado.Mais: as classes queusamessemétodonemprecisam ficarsabendode talmodificação!Você precisa apenas recompilar aquela classe e substituir aquele arquivo.class.Ganhamosmuitoemesconderofuncionamentodonossométodonahoradedarmanutençãoefazermodificações.
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
Oquecomeçamosavernessecapítuloéaideiadeencapsular,istoé,escondertodososmembrosdeumaclasse (comovimosacima), alémde esconder como funcionamas rotinas (no casométodos)donossosistema.
EditoraCasadoCódigocomlivrosdeumaformadiferente
5.2ENCAPSULAMENTO
.
Encapsularéfundamentalparaqueseusistemasejasuscetívelamudanças:nãoprecisaremosmudaruma regra de negócio em vários lugares,mas sim em apenas um único lugar, já que essa regra estáencapsulada.(vejaocasodométodosaca)
Oconjuntodemétodospúblicosdeumaclasseétambémchamadodeinterfacedaclasse,poisestaéaúnicamaneiraaqualvocêsecomunicacomobjetosdessaclasse.
PROGRAMANDOVOLTADOPARAAINTERFACEENÃOPARAAIMPLEMENTAÇÃO
É sempre bomprogramarpensandona interface da sua classe, como seus usuários a estarãoutilizando,enãosomenteemcomoelavaifuncionar.
A implementaçãoemsi, o conteúdodosmétodos,não tem tanta importânciaparaousuáriodessaclasse,umavezqueelesóprecisasaberoquecadamétodopretendefazer,enãocomoelefaz,poisistopodemudarcomotempo.
EssafrasevemdolivroDesignPatterns,deEricGammaetal.Umlivrocultuadonomeiodaorientaçãoaobjetos.
Semprequevamosacessarumobjeto,utilizamossuainterface.Existemdiversasanalogiasfáceisnomundoreal:
Quandovocêdirigeumcarro,oqueteimportasãoospedaiseovolante(interface)enãoomotor que você está usando (implementação). É claro que ummotor diferente pode te darmelhoresresultados,masoqueelefazéomesmoqueummotormenospotente,adiferençaestá em como ele faz. Para trocar um carro a álcool para um a gasolina você não precisareaprender a dirigir! (trocar a implementação dos métodos não precisa mudar a interface,
.
fazendocomqueasoutrasclassescontinuemusandoelesdamesmamaneira).
Todos os celulares fazem a mesma coisa (interface), eles possuem maneiras (métodos) dediscar, ligar, desligar, atender, etc. O que muda é como eles fazem (implementação), masreparequeparaefetuarumaligaçãopoucoimportaseocelularéiPhoneouAndroid,issoficaencapsuladonaimplementação(queaquisãooscircuitos).
JátemosconhecimentossuficientespararesolveraqueleproblemadavalidaçãodeCPF:
classCliente{privateStringnome;privateStringendereco;privateStringcpf;privateintidade;
publicvoidmudaCPF(Stringcpf){validaCPF(cpf);this.cpf=cpf;}
privatevoidvalidaCPF(Stringcpf){//sériederegrasaqui,falhacasonãosejaválido}
//..}
SealguémtentarcriarumClienteenãousaromudaCPFparaalterarumcpfdiretamente,vaireceberumerrodecompilação,jáqueoatributoCPFéprivado.EodiaquevocênãoprecisarverificaroCPFdequemtemmaisde60anos?Seumétodoficaoseguinte:
publicvoidmudaCPF(Stringcpf){if(this.idade<=60){validaCPF(cpf);}this.cpf=cpf;}
OcontrolesobreoCPFestácentralizado:ninguémconsegueacessá-losempassarporaí,aclasseClienteéaúnicaresponsávelpelosseusprópriosatributos!
Omodificadorprivate fazcomqueninguémconsigamodificar,nemmesmoler,oatributoemquestão.Comisso,temosumproblema:comofazerparamostrarosaldodeumaConta,jáquenemmesmopodemosacessá-loparaleitura?
Precisamosentãoarranjarumamaneiradefazeresseacesso.Semprequeprecisamosarrumarumamaneiradefazeralgumacoisacomumobjeto,utilizamosdemétodos!Vamosentãocriarummétodo,digamospegaSaldo,pararealizaressasimplestarefa:
classConta{
5.3GETTERSESETTERS
.
privatedoublesaldo;
//outrosatributosomitidos
publicdoublepegaSaldo(){returnthis.saldo;}
//deposita()esaca()omitidos}
Paraacessarmososaldodeumaconta,podemosfazer:
classTestaAcessoComPegaSaldo{publicstaticvoidmain(String[]args){ContaminhaConta=newConta();minhaConta.deposita(1000);System.out.println("Saldo:"+minhaConta.pegaSaldo());}}
Parapermitiroacessoaosatributos(jáqueelessãoprivate)deumamaneiracontrolada,apráticamaiscomumécriardoismétodos,umqueretornaovaloreoutroquemudaovalor.
Aconvençãoparaessesmétodosédecolocarapalavragetousetantesdonomedoatributo.Porexemplo,anossacontacomsaldo,limiteetitularficaassim,nocasodagentedesejardaracessoaleituraeescritaatodososatributos:
classConta{
privateStringtitular;privatedoublesaldo;
publicdoublegetSaldo(){returnthis.saldo;}
publicvoidsetSaldo(doublesaldo){this.saldo=saldo;}
publicStringgetTitular(){returnthis.titular;}
publicvoidsetTitular(Stringtitular){this.titular=titular;}}
Éumamápráticacriarumaclassee,logoemseguida,criargettersesettersparatodosseusatributos.Vocêsódevecriarumgetterousettersetiverarealnecessidade.ReparequenesseexemplosetSaldonãodeveriatersidocriado,jáquequeremosquetodosusemdeposita()esaca().
Outrodetalheimportante,ummétodogetXnãonecessariamenteretornaovalordeumatributoquechamaX doobjeto emquestão. Isso é interessanteparao encapsulamento. Imagine a situação:
.
queremosqueobancosempremostrecomosaldoovalordo limite somadoao saldo (umapráticacomumdosbancosquecostuma iludir seusclientes).Poderíamos semprechamarc.getLimite()+c.getSaldo(),masissopoderiagerarumasituaçãode"replaceall"quandoprecisássemosmudarcomoo saldo é mostrado. Podemos encapsular isso em um método e, porque não, dentro do própriogetSaldo?Repare:
classConta{
privateStringtitular;privatedoublesaldo;privatedoublelimite;//adicionandoumlimiteaconta
publicdoublegetSaldo(){returnthis.saldo+this.limite;}
//deposita()saca()etransfere()omitidos
publicStringgetTitular(){returnthis.titular;}
publicvoidsetTitular(Stringtitular){this.titular=titular;}}
OcódigoacimanempossibilitaachamadadométodogetLimite(), elenãoexiste.Enemdeveexistir enquanto não houver essa necessidade.OmétodogetSaldo() não devolve simplesmente osaldo...esimoquequeremosquesejamostradocomosefosseosaldo.Utilizargettersesettersnãosóajudavocêaprotegerseusatributos,comotambémpossibilita terdemudaralgoemumsó lugar...chamamosissodeencapsulamento,poisescondeamaneiracomoosobjetosguardamseusdados.Éumapráticamuitoimportante.
Nossaclasseestátotalmentepronta?Istoé,existeachancedelaficarcomsaldomenorque0?Podeparecerquenão,mas,esedepositarmosumvalornegativonaconta?Ficaríamoscommenosdinheiroqueopermitido, jáquenãoesperávamospor isso.Paranosprotegerdissobastamudarmosométododeposita()paraqueeleverifiqueseovalorénecessariamentepositivo.
Depois disso precisaríamos mudar mais algum outro código? A resposta é não, graças aoencapsulamentodosnossosdados.
.
CUIDADOCOMOSGETTERSESETTERS!
Comojádito,nãodevemoscriargettersesetterssemummotivoexplicito.NoblogdaCaelumháumartigoqueilustrabemessescasos:
http://blog.caelum.com.br/2006/09/14/nao-aprender-oo-getters-e-setters/
Quandousamosapalavrachavenew,estamosconstruindoumobjeto.Semprequandoonew échamado,eleexecutaoconstrutordaclasse.Oconstrutordaclasseéumblocodeclaradocomomesmonomequeaclasse:
classConta{Stringtitular;intnumero;doublesaldo;
//construtorConta(){System.out.println("Construindoumaconta.");}
//..}
Então,quandofizermos:
Contac=newConta();
Amensagem"construindoumaconta"aparecerá.Écomoumarotinadeinicializaçãoqueéchamadasemprequeumnovoobjetoécriado.Umconstrutorpodeparecer,masnãoéummétodo.
OCONSTRUTORDEFAULT
Atéagora,asnossasclassesnãopossuíamnenhumconstrutor.Entãocomoéqueerapossíveldarnew,setodonewchamaumconstrutorobrigatoriamente?
Quando você não declara nenhum construtor na sua classe, o Java cria um para você. Esseconstrutoréoconstrutordefault,elenãorecebenenhumargumentoeocorpodeleévazio.
A partir do momento que você declara um construtor, o construtor default não é maisfornecido.
5.4CONSTRUTORES
.
Ointeressanteéqueumconstrutorpodereceberumargumento,podendoassiminicializaralgumtipodeinformação:
classConta{Stringtitular;intnumero;doublesaldo;
//construtorConta(Stringtitular){this.titular=titular;}
//..}
Esse construtor recebe o titular da conta. Assim, quando criarmos uma conta, ela já terá umdeterminadotitular.
Stringcarlos="Carlos";Contac=newConta(carlos);System.out.println(c.titular);
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
Tudoestavafuncionandoatéagora.Paraqueutilizamosumconstrutor?
Aideiaébemsimples.Setodacontaprecisadeumtitular,comoobrigartodososobjetosqueforemcriadosaterumvalordessetipo?BastacriarumúnicoconstrutorquerecebeessaString!
O construtor se resume a isso! Dar possibilidades ou obrigar o usuário de uma classe a passarargumentosparaoobjetoduranteoprocessodecriaçãodomesmo.
Porexemplo,nãopodemosabrirumarquivoparaleiturasemdizerqualéonomedoarquivoquedesejamos ler! Portanto, nadamais natural que passar uma String representando o nome de um
JáconheceoscursosonlineAlura?
5.5ANECESSIDADEDEUMCONSTRUTOR
.
arquivonahoradecriarumobjetodotipodeleituradearquivo,equeissosejaobrigatório.
Vocêpodetermaisdeumconstrutornasuaclassee,nomomentodonew,oconstrutorapropriadoseráescolhido.
CONSTRUTOR:UMMÉTODOESPECIAL?
Umconstrutornão é ummétodo.Algumas pessoas o chamamde ummétodo especial,masdefinitivamentenãoé,jáquenãopossuiretornoesóéchamadoduranteaconstruçãodoobjeto.
CHAMANDOOUTROCONSTRUTOR
Umconstrutor só pode rodar durante a construçãodo objeto, isto é, vocênunca conseguiráchamaroconstrutoremumobjetojáconstruído.Porém,duranteaconstruçãodeumobjeto,vocêpodefazercomqueumconstrutorchameoutro,paranãoterdeficarcopiandoecolando:
classConta{Stringtitular;intnumero;doublesaldo;
//construtorConta(Stringtitular){//fazmaisumasériedeinicializaçõeseconfiguraçõesthis.titular=titular;}
Conta(intnumero,Stringtitular){this(titular);//chamaoconstrutorquefoideclaradoacimathis.numero=numero;}
//..}
Existeumoutromotivo,ooutroladodosconstrutores:facilidade.Àsvezes,criamosumconstrutorquerecebediversosargumentosparanãoobrigarousuáriodeumaclasseachamardiversosmétodosdotipo'set'.
NonossoexemplodoCPF,podemosforçarqueaclasseClienterecebanomínimooCPF,dessamaneiraumClientejáseráconstruídoecomumCPFválido.
.
JAVABEAN
Quando criamos uma classe com todos os atributos privados, seus getters e setters e umconstrutorvazio(padrão),naverdadeestamoscriandoumJavaBean(masnãoconfundacomEJB,queéEnterpriseJavaBeans).
Nosso banco também quer controlar a quantidade de contas existentes no sistema. Comopoderíamosfazeristo?Aideiamaissimples:
Contac=newConta();totalDeContas=totalDeContas+1;
Aqui, voltamos em um problema parecido com o da validação de CPF. Estamos espalhando umcódigo por toda aplicação, e quem garante que vamos conseguir lembrar de incrementar a variáveltotalDeContastodavez?
Tentamosentão,passarparaaseguinteproposta:
classConta{privateinttotalDeContas;//...
Conta(){this.totalDeContas=this.totalDeContas+1;}}
Quandocriarmosduascontas,qualseráovalordototalDeContasdecadaumadelas?Vaiser1.Poiscadaumatemessavariável.Oatributoédecadaobjeto.
Seria interessante então, que essa variável fosse única, compartilhada por todos os objetos dessaclasse.Dessamaneira,quandomudasseatravésdeumobjeto,ooutroenxergariaomesmovalor.Parafazerissoemjava,declaramosavariávelcomostatic.
privatestaticinttotalDeContas;
Quando declaramos um atributo como static, ele passa a não ser mais um atributo de cadaobjeto,esimumatributodaclasse,ainformaçãoficaguardadapelaclasse,nãoémaisindividualparacadaobjeto.
Paraacessarmosumatributoestático,nãousamosapalavrachavethis,massimonomedaclasse:
classConta{privatestaticinttotalDeContas;//...
5.6ATRIBUTOSDECLASSE
.
Conta(){Conta.totalDeContas=Conta.totalDeContas+1;}}
Já que o atributo é privado, como podemos acessar essa informação a partir de outra classe?Precisamosdeumgetterparaele!
classConta{privatestaticinttotalDeContas;//...
Conta(){Conta.totalDeContas=Conta.totalDeContas+1;}
publicintgetTotalDeContas(){returnConta.totalDeContas;}}
Comofazemosentãoparasaberquantascontasforamcriadas?
Contac=newConta();inttotal=c.getTotalDeContas();
Precisamoscriarumacontaantesdechamarométodo!Issonãoélegal,poisgostaríamosdesaberquantascontasexistemsemprecisarteracessoaumobjetoconta.Aideiaaquiéamesma,transformaressemétodoquetodoobjetocontatememummétododetodaaclasse.Usamosapalavrastaticdenovo,mudandoométodoanterior.
publicstaticintgetTotalDeContas(){returnConta.totalDeContas;}
Paraacessaressenovométodo:
inttotal=Conta.getTotalDeContas();
ReparequeestamoschamandoummétodonãocomumareferênciaparaumaConta,esimusandoonomedaclasse.
MÉTODOSEATRIBUTOSESTÁTICOS
Métodoseatributosestáticossópodemacessaroutrosmétodoseatributosestáticosdamesmaclasse,oquefaztodosentidojáquedentrodeummétodoestáticonãotemosacessoàreferênciathis,poisummétodoestáticoéchamadoatravésdaclasse,enãodeumobjeto.
Ostaticrealmentetrazum"cheiro"procedural,porémemmuitasvezesénecessário.
.
Em algumas empresas, o UML é amplamente utilizado. Às vezes, o programador recebe oUML já pronto, completo, e só deve preencher a implementação, devendo seguir à risca oUML.Oquevocêachadessaprática?Quaisasvantagensedesvantagens.
Seumaclassesótematributosemétodosestáticos,queconclusõespodemostirar?Oquelhepareceummétodoestáticoemcasoscomoesses?
Nocasodeatributosbooleanos,pode-seusarnolugardogetosufixois.Dessamaneira,caso tivéssemos um atributo booleano ligado, em vez de getLigado poderíamos terisLigado.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
1. Adicioneomodificadordevisibilidade(private, senecessário)paracadaatributo emétododaclasseConta.TentecriarumaContanomainemodificaroulerumdeseusatributosprivados.Oqueacontece?
2. CrieapenasosgettersesettersnecessáriosdasuaclasseConta.Pensesempreseéprecisocriarcadaumdeles.Porexemplo:
classConta{privateStringtitular;
//...
publicStringgetTitular(){
5.7UMPOUCOMAIS...
SaberinglêsémuitoimportanteemTI
5.8EXERCÍCIOS:ENCAPSULAMENTO,CONSTRUTORESESTATIC
.
returnthis.titular;}
publicvoidsetTitular(Stringtitular){this.titular=titular;}}
Nãocopieecole!Aproveiteparapraticarsintaxe.LogopassaremosausaroEclipseeaísimteremosprocedimentosmaissimplesparaestetipodetarefa.
ReparequeométodocalculaRendimentoparecetambémumgetter.Aliás,seriacomumalguémnomeá-lo de getRendimento . Getters não precisam apenas retornar atributos. Eles podemtrabalharcomessesdados.
3. ModifiquesuasclassesqueacessamemodificamatributosdeumaContaparautilizarosgettersesettersrecémcriados.
Porexemplo,ondevocêencontra:
c.titular="Batman";System.out.println(c.titular);
passapara:
c.setTitular("Batman");System.out.println(c.getTitular());
4. FaçacomquesuaclasseContapossareceber,opcionalmente,onomedotitulardaContaduranteacriaçãodoobjeto.Utilizeconstrutoresparaobteresseresultado.
Dica:utilizeumconstrutorsemargumentos também,paraocasodeapessoanãoquererpassarotitulardaConta.
Seriaalgocomo:
classConta{publicConta(){//construtorsemargumentos}
publicConta(Stringtitular){//construtorquerecebeotitular}}
Porquevocêprecisadoconstrutorsemargumentosparaqueapassagemdonomesejaopcional?
5. (opcional)AdicioneumatributonaclasseContade tipoint que se chama identificador.Esseidentificador deve ter um valor único para cada instância do tipo Conta. A primeira Containstanciada tem identificador 1, a segunda 2, e assim por diante. Você deve utilizar os recursosaprendidosaquipararesolveresseproblema.
.
Crieumgetterparaoidentificador.Devemosterumsetter?
6. (opcional)Comogarantirquedatascomo31/2/2012nãosejamaceitaspelasuaclasseData?
7. (opcional) Suponha que temos a classePessoaFisica que tem um CPF como atributo. Comogarantir que pessoa física alguma tenha CPF invalido, nem seja criada PessoaFisica sem cpfinicial?(Suponhaquejáexisteumalgoritmodevalidaçãodecpf:bastapassarocpfporummétodovalida(Stringx)...)
1. Porqueessecódigonãocompila?
classTeste{intx=37;publicstaticvoidmain(String[]args){System.out.println(x);}}
2. ImaginequetenhaumaclasseFabricaDeCarroequerogarantirquesóexisteumobjetodessetipoemtodaamemória.NãoexisteumapalavrachaveespecialparaistoemJava,entãoteremosdefazernossa classe de tal maneira que ela respeite essa nossa necessidade. Como fazer isso? (pesquise:singletondesignpattern)
5.9DESAFIOS
.
CAPÍTULO6
"Dá-seimportânciaaosantepassadosquandojánãotemosnenhum."--FrançoisChateaubriand
Neste capítulo, você será apresentado aoAmbiente deDesenvolvimento Eclipse e suas principaisfuncionalidades.
OEclipse(http://www.eclipse.org)éumaIDE(integrateddevelopmentenvironment).DiferentedeumaRAD,ondeoobjetivoédesenvolveromaisrápidopossívelatravésdoarrastar-e-soltardomouse,onde montanhas de código são gerados em background, uma IDE te auxilia no desenvolvimento,evitandoseintrometerefazermuitamágica.
OEclipseéaIDElíderdemercado.FormadaporumconsórciolideradopelaIBM,possuiseucódigolivre.
Veremos aqui os principais recursos do Eclipse. Você perceberá que ele evita ao máximo teatrapalhareapenasgeratrechosdecódigosóbvios,sempreaoseucomando.Existemtambémcentenasde plugins gratuitos para gerar diagramasUML, suporte a servidores de aplicação, visualizadores debancodedadosemuitosoutros.
Baixe o Eclipse do site oficial http://www.eclipse.org. Apesar de ser escrito em Java, a bibliotecagráficausadanoEclipse,chamadaSWT,usacomponentesnativosdosistemaoperacional.Porissovocêdevebaixaraversãocorrespondenteaoseusistemaoperacional.
Descompacteoarquivoepronto,bastarodaroexecutável.
OUTRASIDES
UmaoutraIDEopensourcefamosaéoNetbeans,daOracle.(http://www.netbeans.org).
Alémdessas,Oracle,BorlandeaprópriaIBMpossuemIDEscomerciaisealgumasversõesmaisrestritasdeusolivre.
AempresaJetBrainsdesenvolveoIntelliJIDEA,umaIDEpagaquetemganhomuitosadeptos.
ECLIPSEIDE
6.1OECLIPSE
.
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
CliquenoíconedoEclipsenoseuDesktop.
Aprimeiraperguntaqueeletefazéqueworkspacevocêvaiusar.Workspacedefineodiretórioemqueassuasconfiguraçõespessoaiseseusprojetosserãogravados.
Vocêpodedeixarodiretóriopré-definido.
Logoemseguida,uma teladeWelcome seráaberta,ondevocê temdiversos linkspara tutoriais eajuda.CliqueemWorkbench.
AprendasedivertindonaAluraStart!
6.2APRESENTANDOOECLIPSE
.
Feche a tela de Welcome e você verá a tela abaixo. Nesta tela, destacamos as Views (em linhacontínua)easPerspectives(emlinhapontilhada)doEclipse.
6.3VIEWSEPERSPECTIVE
.
Mude para a perspectiva Resource, clicando no ícone ao lado da perspectiva Java, selecionandoOtheredepoisResource.Nestemomento,trabalharemoscomestaperspectiva,antesdadeJava,poiselapossuiumconjuntodeViewsmaissimples.
AViewNavigatormostraaestruturadediretórioassimcomoestánosistemadearquivos.AViewOutlinemostraumresumodasclasses,interfaceseenumeraçõesdeclaradasnoarquivojavaatualmenteeditado(servetambémparaoutrostiposdearquivos).
No menu Window -> Show View -> Other, você pode ver as dezenas de Views que já vem
.
embutidasnoEclipse.Acostume-seasempreprocurarnovasViews,elaspodemteajudaremdiversastarefas.
VáemFile->New->Project.SelecionaJavaProjectecliqueemNext.
6.4CRIANDOUMPROJETONOVO
.
Crieumprojetochamadofj11-contas.
VocêpodechegarnessamesmatelaclicandocomobotãodadiretanoespaçodaViewNavigatoreseguindoomesmomenu.Nestatela,configureseuprojetocomonatelaabaixo:
Isto é, marque "create separate source and output folders", desta maneira seus arquivos java earquivosclassestarãoemdiretóriosdiferentes,paravocêtrabalhardeumamaneiramaisorganizada.
.
CliqueemFinish.OEclipsepediráparatrocaraperspectivaparaJava;escolha"No"parapermaneceremResource.NaViewNavigator,vocêveráonovoprojetoesuaspastasearquivos:
VamosiniciarnossoprojetocriandoaclasseConta.Paraisso,váemFile->New->Other->Class.CliqueemNextecrieaclasseseguindoatelaabaixo:
CliqueemFinish.OEclipsepossuidiversoswizards,masusaremosomínimodeles.Ointeressanteéusarocodeassistequickfixesqueaferramentapossuieveremosemseguida.Nãoseatenteàsmilharesdeopçõesdecadawizard,apartemaisinteressantedoEclipsenãoéessa.
EscrevaométododepositacomoabaixoenotequeoEclipsereclamadeerroemthis.saldopoisesteatributonãoexiste.
.
VamosusarorecursodoEclipsedequickfix.ColoqueocursoremcimadoerroeaperteCtrl+1.
O Eclipse sugerirá possíveis formas de consertar o erro; uma delas é, justamente, criar o camposaldonaclasseConta,queénossoobjetivo.Cliquenestaopção.
Este recurso de quick fixes, acessível pelo Ctrl+1, é uma das grandes facilidades do Eclipse e éextremamentepoderoso.Atravésdele épossível corrigirboapartedos errosnahoradeprogramar e,comofizemos,economizaradigitaçãodecertoscódigosrepetitivos.Nonossoexemplo,nãoprecisamoscriarocampoantes;oEclipsefazissoparanós.Eleatéacertaatipagem,jáqueestamossomandoeleaumdouble.Oprivateécolocadopormotivosquejáestudamos.
VáaomenuFile->Saveparagravar.Control+Stemomesmoefeito.
.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
Seuslivrosdetecnologiaparecemdoséculopassado?
6.5CRIANDOOMAIN
.
CrieumanovaclassechamadaPrincipal.Vamoscolocarummétodomain para testarnossaConta.Emvezdedigitartodoométodomain,vamosusarocodeassistdoEclipse.EscrevasómaineaperteCtrl+Espaçologoemseguida.
OEclipsesugeriráacriaçãodométodomaincompleto;selecioneestaopção.Ocontrol+espaçoéchamadodecodeassist.Assim comoos quick fixes sãode extrema importância.Experimenteusar ocodeassistemdiversoslugares.
Dentrodométodomain,comeceadigitaroseguintecódigo:
Contaconta=newConta();conta.deposita(100.0);
Observe que, na hora de invocar o método sobre o objeto conta, o Eclipse sugere os métodospossíveis.Esterecursoébastanteútil,principalmentequandoestivermosprogramandocomclassesquenãosãoasnossas,comodaAPIdoJava.OEclipseacionaesterecursoquandovocêdigitaopontologoapósumobjeto(evocêpodeusaroCtrl+Espaçoparaacioná-lo).
Vamos imprimir o saldo com System.out.println. Mas, mesmo nesse código, o Eclipse nosajuda.EscrevasysoeaperteCtrl+EspaçoqueoEclipseescreveráSystem.out.println()paravocê.
Paraimprimir,chameoconta.getSaldo():
System.out.println(conta.getSaldo());
NotequeoEclipseacusaráerroemgetSaldo()porqueestemétodonãoexistenaclasseConta.VamosusarCtrl+1emcimadoerroparacorrigiroproblema:
.
OEclipsesugerecriarummétodogetSaldo()naclasseConta.Selecioneestaopçãoeométodoseráinseridoautomaticamente.
publicObjectgetSaldo(){//TODOAuto-generatedmethodstubreturnnull;}
Elegeraummétodonãoexatamentecomoqueríamos,poisnemsemprehácomooEclipse terdeantemãoinformaçõessuficientesparaqueeleacerteaassinaturadoseumétodo.ModifiqueométodogetSaldocomosegue:
publicdoublegetSaldo(){returnthis.saldo;}
EssespequenosrecursosdoEclipsesãodeextremautilidade.Dessamaneira,vocêpodeprogramarsem sepreocupar commétodosque aindanão existem, jáque aqualquermomento elepodegeraroesqueleto(apartedaassinaturadométodo).
Vamosrodarométodomaindessanossaclasse.NoEclipse,cliquecomobotãodireitonoarquivoPrincipal.javaeváemRunas...JavaApplication.
6.6EXECUTANDOOMAIN
.
OEclipseabriráumaViewchamadaConsoleondeseráapresentadaasaídadoseuprograma:
Quando você precisar rodar de novo, basta clicar no ícone verde de play na toolbar, que roda oprogramaanterior.Aoladodesseíconetemumasetinhaondesãolistadosos10últimosexecutados.
OEclipse possuimuitos atalhos úteis para o programador. Semdúvida os 3mais importantes deconheceredepraticarsão:
Ctrl+1Acionaoquickfixescomsugestõesparacorreçãodeerros.
Ctrl+EspaçoCompletacódigos
Ctrl+ 3Acionamododedescobertademenu.ExperimentedigitarCtrl+3 e depois digitarggaseenter.OuentãodeCtrl+3edigitenewclass.
Você pode ler muito mais detalhes sobre esses atalhos no blog da Caelum:http://blog.caelum.com.br/as-tres-principais-teclas-de-atalho-do-eclipse/
6.7PEQUENOSTRUQUES
.
Existemdezenasdeoutros.DentreosmaisutilizadospelosdesenvolvedoresdaCaelum,escolhemososseguintesparacomentar:
Ctrl+F11 roda a última classe que você rodou.É omesmoque clicar no ícone verde quepareceumbotãodeplaynabarradeferramentas.
Ctrl+PgUpeCtrl+PgDownNaveganasabasabertas.Útilquandoestivereditandováriosarquivosaomesmotempo.
Ctrl+Shift+FFormataocódigosegundoasconvençõesdoJava
Ctrl+MExpandeaViewatualparaatelatoda(mesmoefeitodedardoiscliquesnotítulodaView)
Ctrl+Shift+LExibetodososatalhospossíveis.
Ctrl+OExibeumoutlinepararápidanavegação
Alt+Shift+XedepoisJRodaomaindaclasseatual.Péssimoparapressionar!MaisfácilvocêdigitarControl+3edepoisdigitarRun!.AbusedesdejádoControl+3
Veremosmaisnodecorrerdocurso,emespecialquandovirmospacotes.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
1. Crieoprojetofj11-contas.Vocêpodeusaroatalhocontrol+nouentãoirnomenuFile->New->Project...->JavaProject.
2. Dentro do projeto fj11-contas , crie a classe Conta . Uma conta deve ter as seguintesinformações:saldo (double),titular(String),numero (int) eagencia (String).Na classeConta, crie osmétodosdeposita esaca comonos capítulos anteriores.Crie tambémuma
Agoraéamelhorhoraderespirarmaistecnologia!
6.8EXERCÍCIOS:ECLIPSE
.
classeTesteDaConta comomain e instancieuma conta.Desta vez, tente abusardo control+espaçoecontrol+1.
Porexemplo:
publ<ctrlespaco>v<ctrlespaco>deposita(do<ctrlespaço>valor){
Reparequeatémesmonomesdevariáveis,elecriaparavocê!Acompanheasdicasdoinstrutor.
Muitasvezes,aocriarmosumobjeto,nemmesmodeclaramosavariável:
newConta();
Vánessalinhaedêcontrol+1.Elevaisugeriredeclararáavariávelpravocê.
3. Imaginequequeremoscriarumsetterdo titularparaaclasseConta.Dentroda classeConta,digite:
setTit<ctrl+espaco>
OutraformaparacriarosgetterseossettersparaosatributosdaclasseConta,éutilizaroatalhocontrol+3enacaixadeseleçãodigiteggas,iniciaisdeGenerateGettersandSetters!
OBS:Nãocrieumsetterparaoatributosaldo!
4. Váparaaclasseque temomain e segureoCONTROLapertado enquanto vocêpassa omousesobreoseucódigo.Reparequetudovirouhyperlink.CliqueemummétodoquevocêestáinvocandonaclasseConta.
Vocêpodeconseguiromesmoefeito,deabriroarquivonoqualométodo foideclarado, deumamaneira ainda mais prática: sem usar o mouse, quando o cursor estiver sobre o que você queranalisar,simplesmentecliqueF3.
5. Dêumcliquedadireitaemumarquivononavigator.EscolhaCompareWith->LocalHistory.Oqueéestatela?
.
6. UseoControl+Shift+Fparaformataroseucódigo.Dessamaneira,elevaiarrumarabagunçadeespaçamentoeentersdoseucódigo.
7. (opcional)Oquesãoosarquivos.projecte.classpath?Leiaoconteúdodeles.
8. (opcional)Cliquedadireitanoprojeto,propriedades.ÉumadastelasmaisimportantesdoEclipse,onde você pode configurar diversas informações para o seu projeto, como compilador, versões,formatadoreoutros.
.
ExisteummenunoEclipsechamadoRefactor.Eletemopçõesbastanteinteressantesparaauxiliarnaalteraçãodecódigoparamelhorarorganizaçãoouclareza.Porexemplo,umadesuasfuncionalidadesétornarpossívelmudaronomedeumavariável,métodooumesmoclassedeformaqueumaalteração(emumlugarsódosistema)atualizetodasasoutrasvezesqueusavamonomeantigo.
Usar bons nomes no seu código é um excelente começo para mantê-lo legível e fácil de darmanutenção! Mas o assunto "Refatoração" não para por aí: quebrar métodos grandes em menores,dividirclassesgrandesemalgumaspequenasemaisconcisas,melhoraroencapsulamento...todasessassãoformasderefatoração.EessemenudoEclipsenosajudaafazerváriasdelas.
6.9DISCUSSÃOEMAULA:REFACTORING
.
CAPÍTULO7
"Umadiscussãoprolongadasignificaqueambasaspartesestãoerradas"--Voltaire
Aotérminodessecapítulo,vocêserácapazde:
separarsuasclassesempacotes;preparararquivossimplesparadistribuição.
Quando um programador utiliza as classes feitas por outro, surge um problema clássico: comoescreverduasclassescomomesmonome?
Porexemplo:podeserqueaminhaclassedeDatafuncionedeumcertojeito,eaclasseDatadeumcolega,deoutro jeito.Pode serquea classedeData deumabiblioteca funcione aindadeumaterceiramaneiradiferente.
Comopermitirque tudo isso realmente funcione?Comocontrolarquemquerusarqual classedeData?
Pensando um pouco mais, notamos a existência de um outro problema e da própria solução: osistema operacional não permite a existência de dois arquivos com o mesmo nome sob o mesmodiretório,portantoprecisamosorganizarnossasclassesemdiretóriosdiferentes.
Osdiretóriosestãodiretamenterelacionadosaoschamadospacotesecostumamagruparclassesdefuncionalidadessimilaresourelacionadas.
Por exemplo, no pacote java.util temos as classes Date , SimpleDateFormat eGregorianCalendar;todaselastrabalhamcomdatasdeformasdiferentes.
PACOTES-ORGANIZANDOSUASCLASSESEBIBLIOTECAS
7.1ORGANIZAÇÃO
.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
SeaclasseCliente estánopacotecontas, eladeverá estarnodiretório comomesmonome:contas . Se ela se localiza no pacote br.com.caelum.contas , significa que está no diretóriobr/com/caelum/contas.
AclasseCliente,queselocalizanesseúltimodiretóriomencionado,deveserescritadaseguinteforma:
packagebr.com.caelum.contas;
classCliente{//...}
Ficafácilnotarqueapalavrachavepackageindicaqualopacote/diretóriocontémestaclasse.
Umpacotepodeconternenhumoumaissubpacotese/ouclassesdentrodele.
Agoraéamelhorhoraderespirarmaistecnologia!
7.2DIRETÓRIOS
.
PADRÃODANOMENCLATURADOSPACOTES
Opadrãodasunparadarnomeaospacotesérelativoaonomedaempresaquedesenvolveuaclasse:
br.com.nomedaempresa.nomedoprojeto.subpacotebr.com.nomedaempresa.nomedoprojeto.subpacote2br.com.nomedaempresa.nomedoprojeto.subpacote2.subpacote3
Ospacotessópossuemletrasminúsculas,nãoimportaquantaspalavrasestejamcontidasnele.Essepadrãoexisteparaevitaraomáximooconflitodepacotesdeempresasdiferentes.
As classesdopacotepadrãodebibliotecasnão seguemessanomenclatura,que foidadaparabibliotecasdeterceiros.
Para usar uma classe do mesmo pacote, basta fazer referência a ela como foi feito até agorasimplesmenteescrevendoopróprionomedaclasse.SequisermosqueaclasseBancofiquedentrodopacotebr.com.caelum.contas,eladeveserdeclaradaassim:
packagebr.com.caelum.contas;
classBanco{Stringnome;}
ParaaclasseClienteficarnomesmopacote,seguimosamesmafórmula:
packagebr.com.caelum.contas;
classCliente{Stringnome;Stringendereco;}
AnovidadechegaaotentarutilizaraclasseBanco(ouCliente)emumaoutraclassequeestejaforadessepacote,porexemplo,nopacotebr.com.caelum.contas.main:
packagebr.com.caelum.contas.main;
classTesteDoBanco{
publicstaticvoidmain(String[]args){br.com.caelum.contas.BancomeuBanco=newbr.com.caelum.contas.Banco();meuBanco.nome="BancodoBrasil";System.out.println(meuBanco.nome);}
}
7.3IMPORT
.
ReparequeprecisamosreferenciaraclasseBancocomtodoonomedopacotenasuafrente.EsseéoconhecidoFullyQualifiedNamedeumaclasse.Emoutraspalavras,esseéoverdadeironomedeumaclasse,porissoduasclassescomomesmonomeempacotesdiferentesnãoconflitam.
Mesmoassim,aotentarcompilaraclasseanterior,surgeumerroreclamandoqueaclasseBanconãoestávisível.
Acontecequeasclasses só sãovisíveisparaoutrasnomesmopacote e,parapermitirqueaclasseTesteDoBanco veja e acesse a classe Banco em outro pacote, precisamos alterar essa última etransformá-laempública:
packagebr.com.caelum.contas;
publicclassBanco{Stringnome;}
Apalavra chavepublic libera o acesso para classes de outros pacotes. Domesmo jeito que ocompilador reclamou que a classe não estava visível, ele reclama que o atributo/variável membrotambém não está. É fácil deduzir como resolver o problema: utilizando novamente o modificadorpublic:
packagebr.com.caelum.contas;
publicclassBanco{publicStringnome;}
Podemos testar nosso exemplo anterior, lembrando que utilizar atributos como público não trazencapsulamentoeestáaquicomoilustração.
VoltandoaocódigodoTesteDoBanco, é necessário escrever todoopacotepara identificar qualclassequeremosusar?Oexemploqueusamosficoubemcomplicadodeler:
br.com.caelum.contas.BancomeuBanco=newbr.com.caelum.contas.Banco();
Existe umamaneiramais simples de se referenciar a classe Banco: basta importá-la do pacotebr.com.caelum.contas:
packagebr.com.caelum.contas.main;
//parapodermosreferenciar//aBancodiretamenteimportbr.com.caelum.contas.Banco;
publicclassTesteDoBanco{
publicstaticvoidmain(String[]args){BancomeuBanco=newBanco();meuBanco.nome="BancodoBrasil";}
}
.
Issofazcomquenãoprecisemosnosreferenciarutilizandoofullyqualifiedname,podendoutilizarBancodentrodonossocódigoemvezdeescreverolongobr.com.caelum.contas.Banco.
PACKAGE,IMPORT,CLASS
Émuito importantemanteraordem!Primeiro,apareceuma(ounenhuma)vezopackage;depois,podeaparecerumoumaisimports;e,porúltimo,asdeclaraçõesdeclasses.
IMPORTX.Y.Z.*;
É possível "importar um pacote inteiro" (todas as classes do pacote, exceto os subpacotes)atravésdocoringa*:
importjava.util.*;
Importar todas as classes de umpacotenão implica emperdade performance em tempodeexecução,maspodetrazerproblemascomclassesdemesmonome!Alémdisso,importardeumemuméconsideradoboaprática,poisfacilitaaleituraparaoutrosprogramadores.UmaIDEcomooEclipsejávaifazerissoporvocê,assimcomoaorganizaçãoemdiretórios.
Osmodificadoresdeacessoexistentes emJava sãoquatro, e atéomomento jávimos três,mas sóexplicamosdois.
public -Todospodemacessaraquiloque fordefinidocomopublic.Classes, atributos,construtoresemétodospodemserpublic.
protected -Aquiloqueéprotected pode ser acessadopor todas as classesdomesmopacoteeportodasasclassesqueoestendam,mesmoqueessasnãoestejamnomesmopacote.Somenteatributos,construtoresemétodospodemserprotected.
padrão(semnenhummodificador) -Senenhummodificadorforutilizado, todasasclassesdomesmopacotetêmacessoaoatributo,construtor,métodoouclasse.
private-Aúnicaclassecapazdeacessarosatributos,construtoresemétodosprivadoséaprópria classe. Classes, como conhecemos, não podem ser private , mas atributos,construtoresemétodossim.
7.4ACESSOAOSATRIBUTOS,CONSTRUTORESEMÉTODOS
.
CLASSESPÚBLICAS
Paramelhororganizarseucódigo,oJavanãopermitemaisdeumaclassepúblicaporarquivoeoarquivodeveserNomeDaClasse.java.
Umavezqueoutrosprogramadoresirãoutilizaressaclasse,quandoprecisaremolharocódigodamesma,ficamaisfácilencontrá-lasabendoqueelaestánoarquivodemesmonome.
Classesaninhadaspodemserprotectedouprivate,masesseéumtópicoavançadoquenãoseráestudadonessemomento.
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
VocêpodeusaraperspectivaJavadoEclipse.AviewprincipaldenavegaçãoéoPackageExplorer,queagrupaclassespelospacotesemvezdediretórios(vocêpodeusá-laemconjuntocomaNavigator,bastatambémabri-lapeloWindow/ShowView/PackageExplorer).
EditoraCasadoCódigocomlivrosdeumaformadiferente
7.5USANDOOECLIPSECOMPACOTES
.
Antes de movermos nossas classes, declare-as como públicas e coloque-as em seus respectivosarquivos:umarquivoparacadaclasse.
Vocêpodemoverumaclassedepacotearrastando-aparaodestinodesejado.ReparequeoEclipsejádeclarapackageseimportsnecessários:
.
NoEclipsenuncaprecisamosdeclararumimport,poiselesemprevaisugeririssoquandousarmosoCtrl+Espaçononomedeumaclasse.
VocêtambémpodeusaroCtrl+1nocasodadeclaraçãodepacotepossuiralgumerro.
Atenção: utilize os recursos do Eclipse para realizar essas mudanças. Use a view package-
explorer,quevaiauxiliarbastanteamanipulaçãodosarquivosediretórios.TambémutilizeosquickfixesquandooEclipsereclamardosdiversosproblemasdecompilaçãoqueaparecerão.Épossívelfazeresse exercício inteiro semmodificar uma linha de códigomanualmente. Aproveite para praticar edescobriroEclipse,eviteusá-loapenascomoumeditordetexto.
Por exemplo, com o Eclipse nunca precisamos nos preocupar com os imports: ao usar o autocomplete,elejájogaoimportláemcima.E,sevocênãofezisso,elesugerecolocaroimport.
1. Selecionandoosrcdoseuprojeto,façactrl+NeescrevaPackageparaoseusistemadeContascomeçar a utilizar pacotes. Na janela de criação de pacotes escreva o nome completo do pacoteseguindoaconvençãodecódigodaSun,desdeobr,eoEclipsetratarádefazeraseparaçãodaspastascorretamente.Cuidado:paraessecurso,osnomesdospacotesprecisamserosseguintes:
br.com.caelum.contas.main:colocaraclassecomométodomainaqui(oTeste)
7.6EXERCÍCIOS:PACOTES
.
br.com.caelum.contas.modelo:colocaraclasseConta
Antesdecorrigirqualquererrodecompilação,primeiromovatodasassuasclasses,semdeixarnenhumanopacotedefault.
2. Sevocêaindanãotiverseparadocadaclasseemumarquivo,essaéahorademudarisso.Coloquecadaclasseemseurespectivoarquivo.java.Façaissoindependentedeelaserpública:éumaboaprática.
3. Casoocódigonãocompileprontamente, reparequepelomenosalgummétodoquedeclaramosépackage-privatequando,naverdade,precisamosqueelesejapublic.Omesmovaleparaasclasses:algumasdelasprecisarãoserpúblicas.
Se houver algum erro de compilação, use o recurso de quick fix do Eclipse aqui: elemesmo vaisugerirqueomodificadordeacessodeveserpúblico.Paraisso,useoctrl+1emcadaumdoserros,escolhendooquickfixmaisadequadoparaseuproblema.
4. (Opcional)AbraaviewNavigatorparavercomoficouosarquivosnosistemadearquivosdoseusistemaoperacional.Paraisso,usectrl+3,comeceadigitarNavigatoreescolhaaopçãodeabriressaview..
.
CAPÍTULO8
"Perder tempo em aprender coisas que não interessam, priva-nos de descobrir coisas interessantes" --CarlosDrummonddeAndrade
Aotérminodessecapítulo,vocêserácapazde:
criaroJARdoseuaplicativo;colocarumJARnobuildpathdoseuprojeto;lerumjavadoc;criarojavadocdoseuaplicativo.
Assimqueumprogramaficapronto,émeiocomplicadoenviardezenasoucentenasdeclassesparacadaclientequequerutilizá-lo.
Ojeitomaissimplesdetrabalharcomumconjuntodeclassesécompactá-losemumarquivosó.OformatodecompactaçãopadrãoéoZIPcomaextensãodoarquivocompactadoJAR.
OARQUIVO.JAR
Oarquivo jarouJavaARchive, possui umconjuntode classes (e arquivosde configurações)compactados, no estilo de um arquivo zip. O arquivo jar pode ser criado com qualquercompactadorzipdisponívelnomercado,inclusiveoprogramajarquevemjuntocomoJDK.
Paracriarumarquivojardonossoprogramadebanco,bastairaodiretórioondeestãocontidasasclasses eusaro comandoa seguirpara criaroarquivobanco.jar com todas as classesdospacotesbr.com.caelum.utilebr.com.caelum.banco:
jar-cvfbanco.jarbr/com/caelum/util/*.classbr/com/caelum/banco/*.class
Parausaressearquivobanco.jarpararodaroTesteDoBancobastarodarojavacomoarquivojarcomoargumento:
java-classpathbanco.jarbr.com.caelum.contas.main.TesteDoBanco
FERRAMENTAS:JAREJAVADOC
8.1ARQUIVOS,BIBLIOTECASEVERSÕES
.
Paraadicionarmaisarquivos.jar,quepodemserbibliotecas,aoprogramabastarodarojavadaseguintemaneira:
java-classpathbiblioteca1.jar;biblioteca2.jarNomeDaClasse
Vale lembrarqueopontoevírgulautilizadosóéválidoemambienteWindows.EmLinux,MaceoutrosUnix,éodoispontos(variadeacordocomosistemaoperacional).
Hátambémumarquivodemanifestoquecontéminformaçõesdoseujarcomo,porexemplo,qualclasseelevairodarquandoojarforchamado.Masnãosepreocupepois,comoEclipse,essearquivoégeradoautomaticamente.
BIBLIOTECAS
Diversas bibliotecas podem ser controladas de acordo com a versão por estarem semprecompactadasemumarquivo.jar.Basta verificaronomedabiblioteca (por exemplolog4j-1.2.13.jar)paradescobriraversãodela.
Então é possível rodar dois programas aomesmo tempo, cadaumutilizandouma versãodabibliotecaatravésdoparâmetro-classpathdojava.
CRIANDOUM.JARAUTOMATICAMENTE
Existemdiversasferramentasqueservemparaautomatizaroprocessodedeploy,queconsisteemcompilar,gerardocumentação,bibliotecasetc.AsduasmaisfamosassãooANTeoMAVEN,ambossãoprojetosdogrupoApache.
OEclipsepodegerarfacilmenteumjar,porém,seoseubuildécomplexoeprecisaprepararecopiar uma série de recursos, as ferramentas indicadas acima possuem sofisticadasmaneiras derodarumscriptbatch.
.
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
Nesteexemplo,vamosgeraroarquivoJARdonossoprojetoapartirdoEclipse:
CliquecomobotãodireitoemcimadonomedoseuprojetoeselecioneaopçãoExport.
Na telaExport (comomostraa figuraabaixo), selecioneaopção "JAR file" e aperteobotão
AprendasedivertindonaAluraStart!
8.2GERANDOOJARPELOECLIPSE
.
"Next".
Naopção"JARfile:",selecioneolocalquevocêdesejasalvaroarquivoJAR.Eaperte"Next".
Napróximatela,simplesmentecliqueemnext,poisnãohánenhumaconfiguraçãoaserfeita.
.
Na tela abaixo,naopção "select theclassof theapplicationentrypoint", vocêdeveescolherqualclasseseráaclassequevairodarautomaticamentequandovocêexecutaroJAR.
Entrenalinhadecomando:java-jarbanco.jar
É comum dar um nome mais significativo aos JARs, incluindo nome da empresa, do projeto eversão,comocaelum-banco-1.0.jar.
ComovamossaberoquecadaclassetemnoJava?Quaissãoseusmétodos,oqueelesfazem?
E, a partir da Internet, você pode acessar através do link:http://download.java.net/jdk8/docs/api/index.html
NositedaOracle,vocêpode(edeve)baixaradocumentaçãodasbibliotecasdoJava,frequentementereferidacomo"javadoc"ouAPI(sendonaverdadeadocumentaçãodaAPI).
8.3JAVADOC
.
Nesta documentação, no quadro superior esquerdo, você encontra os pacotes e, no inferioresquerdo,estáalistagemdasclasseseinterfacesdorespectivopacote(oudetodos,casonenhumtenhasidoespecificado).Clicando-seemumaclasseou interface,oquadrodadireitapassaadetalhar todosatributosemétodos.
Reparequemétodoseatributosprivadosnãoestãoaí.Oimportanteédocumentaroquesuaclassefaz,enãocomoelafaz:detalhesdeimplementação,comoatributosemétodosprivados,nãointeressamaodesenvolvedorqueusaráasuabiblioteca(ou,aomenos,nãodeveriaminteressar).
Vocêtambémconseguegeraressejavadocapartirdalinhadecomando,comocomando:javadoc.
ParageraroJavadocapartirdoEclipseémuitosimples,sigaospassosabaixo:
Na barra demenu, selecione omenuProject, depois a opção "Generate Javadoc...". (apenasdisponívelseestivernaperspectivaJava,masvocêpodeacessaromesmowizardpeloexportdoprojeto).
8.4GERANDOOJAVADOC
.
Emseguida,aparecerãoasopçõesparageraradocumentaçãodoseusistema,selecionetodasas classes do seu sistema e deixe as outras opções como estão. Não esqueça de marcar ocaminhodaopção"Destination",poiséláqueestarásuadocumentação.
.
Abraadocumentaçãoatravésdocaminhoquevocêmarcoueabraoarquivoindex.html,quevaichamarumapáginasemelhanteaessadafiguraabaixo.
Para colocarmos comentários na documentação, devemos adicionar ao código, sob forma decomentário,abrindootextocom/**efechandocom*/e,nasoutraslinhas,apenascolocando*.Tambémpodemosdefiniroutrasinformaçõesnestetexto,como:autor,versão,parâmetros,retorno,etc.Adicionealgunscomentáriosaoseuprojetocomoabaixo:
/***ClasseresponsávelpormoldarasContasdoBanco**@authorManoelSantosdaSilva*/
publicclassConta{...}
Ouadicionealgunscomentáriosemalgummétodoseu:
/***Metodoqueincrementaosaldo.*@paramvalor*/
publicvoiddeposita(doublevalor){...
.
}
Vejacomoficou:
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
Seuslivrosdetecnologiaparecemdoséculopassado?
8.5EXERCÍCIOS:JAREJAVADOC
.
1. Gereumjardoseusistemacomoarquivodemanifesto.Execute-ocomjava-jar:
java-jarcaelum-banco-1.0.jar
SeoWindowsouoLinux foi configuradopara trabalhar coma extensão .jar, basta você dar umduplo clique no arquivo, que ele será "executado": o arquivo Manifest será lido para que eledescubraqualéaclassecommainqueoJavadeveprocessar.
2. GereoJavadocdoseusistema.Para isso,váaomenuProject,depoisàopçãoGenerateJavadoc, seestivernaperspectivaJava.Senão,dêumcliquecomobotãodireitonoseuprojeto,escolhaExportedepoisjavadocesigaoprocedimentodescritonaúltimaseçãodestecapítulo.
IndependentedaperspectivaquevocêusanoEclipse,vocêtambémpodeusaroctrl+3ecomeçaraescreverJavaDoc,atéqueaopçãodeexportaroJavaDocapareça.
INTERFACEVERSUSIMPLEMENTAÇÃONOVAMENTE!
Repare que a documentação gerada não mostra o conteúdo dos métodos, nem atributos emétodosprivados!Issofazpartedaimplementação,eoqueimportaparaquemusaumabibliotecaéainterface:oqueelafaz.
Jásabemoscomodocumentarnossoprojetoegerarumjarparadistribuí-lomaselaaindanãotemumainterfacegráficadousuário.Sequisermosrodaronossosistematemosqueexecutá-lopeloterminalcomosvaloreshard-coded.Seriamaisinteressantequetivéssemosumainterfacemaisamigávelparaqueousuáriopudesseinteragircomonossosistema.Aomesmotempo,nãoqueremosnospreocuparnessemomentoemcriartodasasclassespararepresentaressainterfacegráfica,queremosapenasutilizaralgojápronto.
Para isso, vamos importar uma biblioteca externa. O próprio Eclipse já nos dá suporte para aimportaçãodejars.Parafazerisso,bastairnomenuProject->Properties,selecionaraopçãoJavaBuildPath,depois selecionara abaLibraries e, finalmente, clicarnobotãoAddExternal Jars... .Agora é sóselecionar o jar a ser importado e clicar emOpen.Clique emOknovamente para fechar a janela deimportaçãoepronto!Nossabibliotecajáestáprontaparaserutilizada.
1. Vamosimportarumjarquecontémainterfacegráficadousuárioparaonossosistemadecontas.
VánomenuProject->Properties
8.6IMPORTANDOUMJAREXTERNO
8.7EXERCÍCIOS:IMPORTANDOUMJAR
.
SelecioneaopçãoJavaBuildPath
SelecioneaabaLibraries
CliquenobotãoAddExternalJars...
Selecioneoarquivofj11-lib-contas.jarlocalizadonapastadosarquivosdoscursos/11
CliquenobotãoOkparafecharajaneladeimportação
2. Para verificarmosque a importaçãodeu certo, vamos chamaruma classedabiblioteca importadaparaexibirumajaneladeboas-vindas.
CrieumaclasseTestaJarnopacotebr.com.caelum.contas.main.
Crietambémométodomain.
3. Dentrodométodocriado,vamos invocarométodomaindaclasseOlaMundo que existeno jarimportado.Seucódigodeveficardessamaneira:
packagebr.com.caelum.contas.main;
importbr.com.caelum.javafx.api.main.OlaMundo;
publicclassTestaJar{
publicstaticvoidmain(String[]args){OlaMundo.main(args);}}
NãoesqueçadeimportaraclasseOlaMundodopacotebr.com.caelum.javafx.api.main.Useoatalhoctrl+shift+O.
4. Executeasuaaplicaçãoevejaseapareceuumajaneladeboas-vindascomoaseguir:
.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
AgoraquejáimportamosoJarquecontémainterfacegráfica,vamosdarumaolhadanaprimeirateladonossosistema:
Agoraéamelhorhoraderespirarmaistecnologia!
8.8MANIPULANDOACONTAPELAINTERFACEGRÁFICA
.
Nestatela,podemosperceberquetemosbotõesparaasaçõesdecriaçãodeconta,saqueedepósito,quedevemutilizaraimplementaçãoexistenteemnossaclasseConta.
Se quisermos visualizar a tela, podemos criar um main que chamará a classe TelaDeContasresponsávelpelasuaexibição:
packagebr.com.caelum.contas.main;
importbr.com.caelum.javafx.api.main.TelaDeContas;
publicclassTestaContas{
publicstaticvoidmain(String[]args){TelaDeContas.main(args);}}
.
Aoexecutarmosaaplicaçãoocorreráumerro:
Masporqueesteerroocorreu?Acontecequeatelaprecisaconheceralguémquesaibaexecutarasaçõesdesaqueedepósitonaconta,queconsigabuscarosdadosdatelaparapopularaconta.Comonãotemosninguémquesaibafazeristoainda,ocorreuoerro.
VamosentãocriaraclasseManipuladorDeContasqueseráresponsávelporfazeresta"ponte"entreatelaeaclassedeConta:
packagebr.com.caelum.contas;
publicclassManipuladorDeContas{
}
Agora,aoexecutarmosaaplicação,veremosqueatelaaparececomsucesso:
.
Esetentarmosclicarnobotãodecriaçãodeconta?Tambémocorreumerro!
.
DestavezoerroindicaquefaltaométodocriaContadentrodaclasseManipuladorDeContas.Vamosentãocriá-lo:
publicclassManipuladorDeContas{
publicvoidcriaConta(){Contaconta=newConta();conta.setAgencia("1234");conta.setNumero(56789);conta.setTitular("Batman");}}
Paraconseguirmosobterasinformaçõesdatela,todososmétodosquecriaremosprecisamreceberumparâmetrodotipoEventoqueconteráasinformaçõesdigitadas.Mesmoquenãoutilizemosesteparâmetro,precisamosrecebê-lo.
importbr.com.caelum.javafx.api.util.Evento;
publicclassManipuladorDeContas{
publicvoidcriaConta(Eventoevento){Contaconta=newConta();conta.setAgencia("1234");conta.setNumero(56789);conta.setTitular("Batman");}}
Se tentarmos executar a aplicação e clicarnobotãocria conta, vemosque agoranãoocorremaisnenhumerromasaomesmotempoosdadosdacontanãosãopopuladosnatela.Istoacontecepoisavariávelconta é apenas local, ou seja, ela só existe dentro dométodocriaConta. Além disso sequiséssemosdepositarumvalornaconta,emqualcontadepositaríamos?Elanãoévisívelparanenhum
.
outrométodo!
PrecisamosqueestavariávelsejaumatributodoManipuladorDeContas.Vamosalterar:
importbr.com.caelum.javafx.api.util.Evento;
publicclassManipuladorDeContas{
privateContaconta;
publicvoidcriaConta(Eventoevento){this.conta=newConta();this.conta.setAgencia("1234");this.conta.setNumero(56789);this.conta.setTitular("Batman");}}
Testandoagoraconseguimosverosdadosdacontanatela!
.
Só falta criarmos os métodos saca e deposita. Vamos começar implementando o métododeposita. Nele precisamos do valor digitado pelo usuário na tela e é pra isto que serve a classeEvento. Se quisermos buscar um valor do tipo double, podemos invocar o método doublepassandoonomedocampoquequeremosrecuperarcomoparâmetro.Comovaloremmãos,podemosentãopassá-loparaométododesejado.Nossométodofica:
importbr.com.caelum.javafx.api.util.Evento;
publicclassManipuladorDeContas{
//...
publicvoiddeposita(Eventoevento){doublevalorDigitado=evento.getDouble("valor");this.conta.deposita(valorDigitado);}}
Podemosfazeromesmoparaométodosaca:
importbr.com.caelum.javafx.api.util.Evento;
publicclassManipuladorDeContas{
//...
publicvoiddeposita(Eventoevento){doublevalorDigitado=evento.getDouble("valor");this.conta.deposita(valorDigitado);}
publicvoidsaca(Eventoevento){doublevalorDigitado=evento.getDouble("valor");this.conta.saca(valorDigitado);}}
Agoraconseguimosrodaraaplicaçãoechamarasaçõesdesaqueedepósitoqueosaldoéatualizadocomsucesso!
.
1. CrieaclasseManipuladorDeContas dentrodopacotebr.com.caelum.contas.Reparequeospacotes br.com.caelum.contas.main e br.com.caelum.contas.modelo são subpacotes dopacotebr.com.caelum.contas,portantoopacotebr.com.caelum.contasjáexiste.Paracriaraclassenestepacote,bastaselecioná-lonajaneladecriaçãodaclasse:
8.9EXERCÍCIOS:MOSTRANDOOSDADOSDACONTANATELA
.
AclasseManipuladorDeContasfaráaligaçãodaContacomatela,porissoprecisaremosdeclararumatributodotipoConta.
2. CrieométodocriaContaquerecebecomoparâmetroumobjetodotipoEvento.Instancieumacontaparaoatributocontaecoloqueosvaloresdenumero,agenciaetitular.Algocomo:
publicvoidcriaConta(Eventoevento){this.conta=newConta();this.conta.setTitular("Batman");//façaomesmoparaosoutrosatributos}
3. Comacontainstanciada,agorapodemosimplementarasfuncionalidadesdesaqueedepósito.CrieométododepositaquerecebeumEvento,queéaclassequeretornaosdadosdatelanostiposqueprecisamos.Porexemplo,sequisermosovaloradepositarsabemosqueeleédotipodoubleequeonomedocamponatelaévalorentãopodemosfazer:
publicvoiddeposita(Eventoevento){doublevalorDigitado=evento.getDouble("valor");this.conta.deposita(valorDigitado);}
4. Crie agora o método saca. Ele também deve receber um Evento nos mesmos moldes do
.
deposita.
5. Precisamos agora testar nossa aplicação, crie a classe TestaContas dentro do pacotebr.com.caelum.contascomummain.NelavamoschamaromaindaclasseTelaDeContasquemostraráateladenossosistema.Nãoseesqueçadefazeroimportdestaclasse!
importbr.com.caelum.javafx.api.main.TelaDeContas;
publicclassTestaContas{
publicstaticvoidmain(String[]args){TelaDeContas.main(args);}}
Rodeaaplicação,crieacontaetentefazerasoperaçõesdesaqueedepósito.Tudodevefuncionarnormalmente.
.
CAPÍTULO9
"Ohomemabsurdoéaquelequenuncamuda."--GeorgesClemenceau
Aotérminodessecapítulo,vocêserácapazde:
dizeroqueéherançaequandoutilizá-la;reutilizarcódigoescritoanteriormente;criarclassesfilhasereescrevermétodos;usartodoopoderqueopolimorfismodá.
Comotodaempresa,nossoBancopossuifuncionários.VamosmodelaraclasseFuncionario:
publicclassFuncionario{privateStringnome;privateStringcpf;privatedoublesalario;//métodosdevemviraqui}
Alémdeumfuncionáriocomum,hátambémoutroscargos,comoosgerentes.Osgerentesguardama mesma informação que um funcionário comum, mas possuem outras informações, além de terfuncionalidadesumpoucodiferentes.Umgerentenonossobancopossuitambémumasenhanuméricaquepermiteoacessoaosistemainternodobanco,alémdonúmerodefuncionáriosqueelegerencia:
publicclassGerente{privateStringnome;privateStringcpf;privatedoublesalario;privateintsenha;privateintnumeroDeFuncionariosGerenciados;
publicbooleanautentica(intsenha){if(this.senha==senha){System.out.println("AcessoPermitido!");returntrue;}else{System.out.println("AcessoNegado!");returnfalse;}}
//outrosmétodos
HERANÇA,REESCRITAEPOLIMORFISMO
9.1REPETINDOCÓDIGO?
.
}
PRECISAMOSMESMODEOUTRACLASSE?
PoderíamosterdeixadoaclasseFuncionariomaisgenérica,mantendonelasenhadeacesso,eonúmerodefuncionáriosgerenciados.Casoofuncionárionãofosseumgerente,deixaríamosestesatributosvazios.
Essaéumapossibilidade,porémpodemoscomeçara termuitoatributosopcionais,eaclasseficariaestranha.Eemrelaçãoaosmétodos?AclasseGerentetemométodoautentica,quenãofazsentidoexistiremumfuncionárioquenãoégerente.
Se tivéssemos um outro tipo de funcionário que tem características diferentes do funcionáriocomum,precisaríamoscriarumaoutraclasseecopiarocódigonovamente!
Além disso, se um dia precisarmos adicionar uma nova informação para todos os funcionários,precisaremospassarportodasasclassesdefuncionárioeadicionaresseatributo.Oproblemaacontecenovamentepornãocentralizarmosasinformaçõesprincipaisdofuncionárioemumúnicolugar!
Existeumjeito,emJava,derelacionarmosumaclassedetalmaneiraqueumadelasherdatudoqueaoutratem.Istoéumarelaçãodeclassemãeeclassefilha.Nonossocaso,gostaríamosdefazercomqueoGerente tivesse tudo que um Funcionario tem, gostaríamos que ela fosse uma extensão deFuncionario.Fazemosistoatravésdapalavrachaveextends.
publicclassGerenteextendsFuncionario{privateintsenha;privateintnumeroDeFuncionariosGerenciados;
publicbooleanautentica(intsenha){if(this.senha==senha){System.out.println("AcessoPermitido!");returntrue;}else{System.out.println("AcessoNegado!");returnfalse;}}
//setterdasenhaomitido}
Em todomomento que criarmos um objeto do tipo Gerente, este objeto possuirá também osatributosdefinidosnaclasseFuncionario,poisumGerenteéumFuncionario:
.
publicclassTestaGerente{publicstaticvoidmain(String[]args){Gerentegerente=newGerente();
//podemoschamarmétodosdoFuncionario:gerente.setNome("JoãodaSilva");
//etambémmétodosdoGerente!gerente.setSenha(4231);}}
DizemosqueaclasseGerenteherdatodososatributosemétodosdaclassemãe,nonossocaso,aFuncionario.Para sermaispreciso, ela tambémherdaosatributosemétodosprivados,porémnãoconsegue acessá-los diretamente. Para acessar um membro privado na filha indiretamente, serianecessárioqueamãeexpusesseumoutrométodovisívelqueinvocasseesseatributooumétodoprivado.
SUPERESUBCLASSE
A nomenclatura mais encontrada é que Funcionario é a superclasse de Gerente , eGerente é a subclasse de Funcionario . Dizemos também que todo Gerente é umFuncionário.OutraformaédizerqueFuncionarioéclassemãedeGerenteeGerenteéclassefilhadeFuncionario.
E se precisamos acessar os atributos que herdamos? Não gostaríamos de deixar os atributos deFuncionario,public,poisdessamaneiraqualquerumpoderiaalterarosatributosdosobjetosdestetipo.Existeumoutromodificadordeacesso,oprotected,queficaentreoprivateeopublic.Umatributoprotected só pode ser acessado (visível) pela própria classe, por suas subclasses, e pelasclassesqueseencontramnomesmopacote.
publicclassFuncionario{protectedStringnome;protectedStringcpf;protecteddoublesalario;//métodosdevemviraqui}
.
SEMPREUSARPROTECTED?
Entãoporqueusarprivate?Depoisdeumtempoprogramandoorientadoaobjetos,vocêvaicomeçarasentirquenemsempreéumaboaideiadeixarqueaclassefilhaacesseosatributosdaclasse mãe, pois isso quebra um pouco a ideia de que só aquela classe deveria manipular seusatributos.Essaéumadiscussãoumpoucomaisavançada.
Alémdisso,nãosóas subclasses,mas tambémasoutrasclassesqueseencontramnomesmopacote, podem acessar os atributos protected. Veja outras alternativas ao protected noexercíciodediscussãoemsaladeaulajuntamentecomoinstrutor.
Da mesma maneira, podemos ter uma classe Diretor que estenda Gerente e a classePresidentepodeestenderdiretamentedeFuncionario.
Fique claro que essa é uma decisão de negócio. Se Diretor vai estender de Gerente ou não, vaidependerse,paravocê,DiretoréumGerente.
Umaclassepodetervárias filhas,maspodeterapenasumamãe,éachamadaherançasimplesdojava.
.
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
Todo fim de ano, os funcionários do nosso banco recebem uma bonificação. Os funcionárioscomunsrecebem10%dovalordosalárioeosgerentes,15%.
VamosvercomoficaaclasseFuncionario:
publicclassFuncionario{protectedStringnome;protectedStringcpf;protecteddoublesalario;
publicdoublegetBonificacao(){returnthis.salario*0.10;}//métodos}
SedeixarmosaclasseGerentecomoelaestá,elavaiherdarométodogetBonificacao.
Gerentegerente=newGerente();gerente.setSalario(5000.0);System.out.println(gerente.getBonificacao());
Oresultadoaquiserá500.Nãoqueremosessaresposta,poisogerentedeveriater750debônusnessecaso.Paraconsertarisso,umadasopçõesseriacriarumnovométodonaclasseGerente,chamado,porexemplo, getBonificacaoDoGerente. O problema é que teríamos dois métodos em Gerente ,confundindobastantequemforusaressaclasse,alémdequecadaumdaumarespostadiferente.
NoJava,quandoherdamosummétodo,podemosalterarseucomportamento.Podemosreescrever(reescrever,sobrescrever,override)estemétodo:
publicclassGerenteextendsFuncionario{intsenha;intnumeroDeFuncionariosGerenciados;
EditoraCasadoCódigocomlivrosdeumaformadiferente
9.2REESCRITADEMÉTODO
.
publicdoublegetBonificacao(){returnthis.salario*0.15;}//...}
AgoraométodoestácorretoparaoGerente.Refaçaotesteevejaqueovalorimpressoéocorreto(750):
Gerentegerente=newGerente();gerente.setSalario(5000.0);System.out.println(gerente.getBonificacao());
AANOTAÇÃO@OVERRIDE
Hácomodeixarexplícitonoseucódigoquedeterminadormétodoéareescritadeummétododa sua classemãe. Fazemos isso colocando @Override em cima do método. Isso é chamadoanotação.Existemdiversasanotaçõesecadaumavaiterumefeitodiferentesobreseucódigo.
@OverridepublicdoublegetBonificacao(){returnthis.salario*0.15;}
Repare que, por questões de compatibilidade, isso não é obrigatório. Mas caso ummétodoestejaanotadocom@Override,elenecessariamenteprecisaestarreescrevendoummétododaclassemãe.
Depoisde reescrito,nãopodemosmais chamarométodoantigoque foraherdadoda classemãe:realmente alteramos o seu comportamento. Mas podemos invocá-lo no caso de estarmos dentro daclasse.
Imagine que para calcular a bonificação de umGerente devemos fazer igual ao cálculo de umFuncionarioporémadicionandoR$1000.Poderíamosfazerassim:
publicclassGerenteextendsFuncionario{intsenha;intnumeroDeFuncionariosGerenciados;
publicdoublegetBonificacao(){returnthis.salario*0.10+1000;}//...}
Aquiteríamosumproblema:odiaqueogetBonificacaodoFuncionariomudar,precisaremos
9.3INVOCANDOOMÉTODOREESCRITO
.
mudar o método do Gerente para acompanhar a nova bonificação. Para evitar isso, ogetBonificacaodoGerentepodechamarodoFuncionarioutilizandoapalavrachavesuper.
publicclassGerenteextendsFuncionario{intsenha;intnumeroDeFuncionariosGerenciados;
publicdoublegetBonificacao(){returnsuper.getBonificacao()+1000;}//...}
Essa invocação vai procurar o método com o nome getBonificacao de uma super classe deGerente.NocasoelelogovaiencontraressemétodoemFuncionario.
Essaéumapráticacomum,poismuitoscasosométodoreescritogeralmentefaz"algoamais"queométododaclassemãe.Chamarounãoométododecimaéumadecisãosuaedependedoseuproblema.Algumasvezesnãofazsentidoinvocarométodoquereescrevemos.
OqueguardaumavariáveldotipoFuncionario?UmareferênciaparaumFuncionario,nuncaoobjetoemsi.
Naherança,vimosquetodoGerenteéumFuncionario,poiséumaextensãodeste.Podemosnos referir a um Gerente como sendo um Funcionario . Se alguém precisa falar com umFuncionariodobanco,podefalarcomumGerente!Porque?PoisGerenteéumFuncionario.Essaéasemânticadaherança.
Gerentegerente=newGerente();Funcionariofuncionario=gerente;funcionario.setSalario(5000.0);
Polimorfismo é a capacidade de um objeto poder ser referenciado de várias formas. (cuidado,polimorfismonãoquerdizerqueoobjetoficasetransformando,muitopelocontrário,umobjetonascedeumtipoemorredaqueletipo,oquepodemudaréamaneiracomonosreferimosaele).
Atéaquitudobem,maseseeutentar:
9.4POLIMORFISMO
.
funcionario.getBonificacao();
Qualéoretornodessemétodo?500ou750?NoJava,ainvocaçãodemétodosemprevaiserdecididaemtempodeexecução.OJavavaiprocuraroobjetonamemóriae,aísim,decidirqualmétododeveserchamado, sempre relacionando com sua classe de verdade, e não com a que estamos usando parareferenciá-lo.ApesardeestarmosnosreferenciandoaesseGerentecomosendoumFuncionario,ométodoexecutadoéodoGerente.Oretornoé750.
Parece estranho criar um gerente e referenciá-lo como apenas um funcionário. Por que faríamosisso?Naverdade,asituaçãoquecostumaapareceréaquetemosummétodoquerecebeumargumentodotipoFuncionario:
classControleDeBonificacoes{privatedoubletotalDeBonificacoes=0;
publicvoidregistra(Funcionariofuncionario){this.totalDeBonificacoes+=funcionario.getBonificacao();}
publicdoublegetTotalDeBonificacoes(){returnthis.totalDeBonificacoes;}}
E,emalgumlugardaminhaaplicação(ounomain,seforapenasparatestes):
ControleDeBonificacoescontrole=newControleDeBonificacoes();
Gerentefuncionario1=newGerente();funcionario1.setSalario(5000.0);controle.registra(funcionario1);
Funcionariofuncionario2=newFuncionario();funcionario2.setSalario(1000.0);controle.registra(funcionario2);
System.out.println(controle.getTotalDeBonificacoes());
ReparequeconseguimospassarumGerenteparaummétodoquerecebeumFuncionariocomoargumento. Pense comonuma porta na agência bancária como seguinte aviso: "Permitida a entradaapenas de Funcionários". Um gerente pode passar nessa porta? Sim, pois Gerente é umFuncionario.
Qual será o valor resultante? Não importa que dentro do método registra doControleDeBonificacoesrecebaFuncionario.QuandoelereceberumobjetoquerealmenteéumGerente,oseumétodoreescritoseráinvocado.Reafirmando:nãoimportacomonosreferenciamosaumobjeto,ométodoqueseráinvocadoésempreoqueédele.
No dia em que criarmos uma classe Secretaria, por exemplo, que é filha de Funcionario,precisaremos mudar a classe de ControleDeBonificacoes ? Não. Basta a classe Secretariareescrever os métodos que lhe parecerem necessários. É exatamente esse o poder do polimorfismo,
.
juntamentecomareescritademétodo:diminuiroacoplamentoentreasclasses,paraevitarquenovoscódigosresultememmodificaçõeseminúmeroslugares.
ReparequequemcriouControleDeBonificacoespodenunca ter imaginadoacriaçãodaclasseSecretaria ouEngenheiro. Contudo, não será necessário reimplementar esse controle em cadanovaclasse:reaproveitamosaquelecódigo.
HERANÇAVERSUSACOPLAMENTO
Notequeousodeherançaaumentaoacoplamentoentreasclasses,istoé,oquantoumaclassedependedeoutra.Arelaçãoentreclassemãeefilhaémuitoforteeissoacabafazendocomqueoprogramadordas classes filhas tenhaqueconhecera implementaçãodaclassemãeevice-versa -ficadifícilfazerumamudançapontualnosistema.
Por exemplo, imagine se tivermos quemudar algo na nossa classeFuncionario, mas nãoquiséssemosquetodososfuncionáriossofressemamesmamudança.Precisaríamospassarporcadauma das filhas de Funcionario verificando se ela se comporta como deveria ou se devemossobrescreverotalmétodomodificado.
Esse éumproblemadaherança, enãodopolimorfismo,que resolveremosmais tardecomaajudadeInterfaces.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
Imaginequevamosmodelarumsistemaparaafaculdadequecontroleasdespesascomfuncionárioseprofessores.Nossofuncionárioficaassim:
JáconheceoscursosonlineAlura?
9.5UMOUTROEXEMPLO
.
publicclassEmpregadoDaFaculdade{privateStringnome;privatedoublesalario;publicdoublegetGastos(){returnthis.salario;}publicStringgetInfo(){return"nome:"+this.nome+"comsalário"+this.salario;}//métodosdeget,seteoutros}
Ogastoquetemoscomoprofessornãoéapenasseusalário.Temosdesomarumbônusde10reaisporhora/aula.Oquefazemosentão?Reescrevemosométodo.AssimcomoogetGastosédiferente,ogetInfotambémserá,poistemosdemostrarashoras/aulatambém.
publicclassProfessorDaFaculdadeextendsEmpregadoDaFaculdade{privateinthorasDeAula;publicdoublegetGastos(){returnthis.getSalario()+this.horasDeAula*10;}publicStringgetInfo(){StringinformacaoBasica=super.getInfo();Stringinformacao=informacaoBasica+"horasdeaula:"+this.horasDeAula;returninformacao;}//métodosdeget,seteoutrosqueforemnecessários}
Anovidade,aqui, éapalavrachavesuper.Apesardométodo ter sido reescrito, gostaríamosdeacessar ométodo da classemãe, para não ter de copiar e colocar o conteúdo dessemétodo e depoisconcatenarcomainformaçãodashorasdeaula.
Comotiramosproveitodopolimorfismo?Imaginequetemosumaclassederelatório:
publicclassGeradorDeRelatorio{publicvoidadiciona(EmpregadoDaFaculdadef){System.out.println(f.getInfo());System.out.println(f.getGastos());}}
Podemos passar para nossa classe qualquer EmpregadoDaFaculdade! Vai funcionar tanto paraprofessor,quantoparafuncionáriocomum.
Umcertodia,muitodepoisdeterminaressaclassederelatório,resolvemosaumentarnossosistema,e colocar uma classe nova, que representa o Reitor . Como ele também é umEmpregadoDaFaculdade, seráquevamosprecisaralteraralgonanossaclassedeRelatorio?Não.Essa é a ideia!Quem programou a classe GeradorDeRelatorio nunca imaginou que existiria umaclasseReitore,mesmoassim,osistemafunciona.
publicclassReitorextendsEmpregadoDaFaculdade{//informaçõesextraspublicStringgetInfo(){
.
returnsuper.getInfo()+"eeleéumreitor";}//nãosobrescrevemosogetGastos!!!}
SenãohouvesseherançaemJava,comovocêpoderiareaproveitarocódigodeoutraclasse?
Umadiscussãomuitoatualésobreoabusonousodaherança.Algumaspessoasusamherançaapenasparareaproveitarocódigo,quandopoderiamterfeitoumacomposição.Procuresobreherançaversuscomposição.
Mesmo depois de reescrever ummétodo da classemãe, a classe filha ainda pode acessar ométodoantigo.Istoéfeitoatravésdapalavrachavesuper.método().Algoparecidoocorreentreosconstrutoresdasclasses,oque?
MAISSOBREOMAUUSODAHERANÇA
NoblogdaCaelumexisteumartigointeressanteabordandoessetópico:
http://blog.caelum.com.br/2006/10/14/como-nao-aprender-orientacao-a-objetos-heranca/
JamesGosling,umdoscriadoresdoJava,éumcríticodomauusodaherança.Nestaentrevistaelediscuteapossibilidadedeseutilizarapenasinterfacesecomposição,eliminandoanecessidadedaherança:
http://www.artima.com/intv/gosling3P.html
1. Vamostermaisdeumtipodecontanonossosistemaentãovamosprecisardeumanovatelaparacadastrarosdiferentestiposdeconta.Essatelajáestáprontaeparautilizá-lasóprecisamosalteraraclassequeestamoschamandonométodomain()noTestaContas.java:
packagebr.com.caelum.contas.main;
importbr.com.caelum.javafx.api.main.SistemaBancario;
publicclassTestaContas{
publicstaticvoidmain(String[]args){SistemaBancario.mostraTela(false);//TelaDeContas.main(args);}}
9.6UMPOUCOMAIS...
9.7EXERCÍCIOS:HERANÇAEPOLIMORFISMO
.
2. AorodaraclasseTestaContasagora,teremosatelaabaixo:
Vamosentrarna teladecriaçãodecontasparavermosoqueprecisamos implementarparaqueosistemafuncione.Paraisso,cliquenobotãoNovaConta.Aseguintetelaaparecerá:
Podemos perceber que além das informações que já tínhamos na conta, temos agora o tipo: sequeremos uma conta corrente ou uma conta poupança. Vamos então criar as classescorrespondentes.
CrieaclasseContaCorrentenopacotebr.com.caelum.contas.modelo e faça comque elasejafilhadaclasseContaCrieaclasseContaPoupancanopacotebr.com.caelum.contas.modelo e faça comque elasejafilhadaclasseConta
3. Precisamos pegar os dados da tela para conseguirmos criar a conta correspondente. NoManipuladorDeContas vamos alterar ométodocriaConta. Atualmente, apenas criamosumanovacontacomosdadosdiretonocódigo.Vamosfazercomqueagoraosdadossejamrecuperados
.
datelaparacolocarmosnanovaconta,faremosissoutilizandooobjetoevento:
publicvoidcriaConta(Eventoevento){this.conta=newConta();this.conta.setAgencia(evento.getString("agencia"));this.conta.setNumero(evento.getInt("numero"));this.conta.setTitular(evento.getString("titular"));}
Masprecisamosdizerqual tipode contaquequeremos criar!Devemos então recuperaro tipodacontaescolhidoecriaracontacorrespondente.Paraisso,aoinvésdecriarumobjetodotipo'Conta',vamosusarométodogetSelecionadoNoRadiodoobjetoeventoparapegarotipo,fazerumifparaverificaresse tipoe sódepoiscriaroobjetodo tipocorrespondente.Apósessasmudanças,ométodocriaContaficarácomoabaixo:
publicvoidcriaConta(Eventoevento){Stringtipo=evento.getSelecionadoNoRadio("tipo");if(tipo.equals("ContaCorrente")){this.conta=newContaCorrente();}elseif(tipo.equals("ContaPoupança")){this.conta=newContaPoupanca();}this.conta.setAgencia(evento.getString("agencia"));this.conta.setNumero(evento.getInt("numero"));this.conta.setTitular(evento.getString("titular"));}
4. Apesarde já conseguirmoscriarosdois tiposde contas,nossa listanãoconsegueexibiro tipodecadacontanalistadatelainicial.Pararesolverisso,podemoscriarummétodogetTipoemcadaumadenossascontasfazendocomqueacontacorrentedevolvaastring"ContaCorrente"eacontapoupançadevolvaastring"ContaPoupança":
publicclassContaCorrenteextendsConta{publicStringgetTipo(){return"ContaCorrente";}}
publicclassContaPoupancaextendsConta{publicStringgetTipo(){return"ContaPoupança";}}
5. AltereosmétodossacaedepositaparabuscaremocampovalorOperacaoaoinvésdeapenasvalornaclasseManipuladorDeContas.
6. Vamosmudarocomportamentodaoperaçãodesaquedeacordocomotipodecontaqueestiversendo utilizada.Na classeManipuladorDeContas vamos alterar ométodo saca para tirar 10centavosdecadasaqueemumacontacorrente:
publicvoidsaca(Eventoevento){doublevalor=evento.getDouble("valorOperacao");if(this.conta.getTipo().equals("ContaCorrente")){this.conta.saca(valor+0.10);
.
}else{this.conta.saca(valor);}}
AotentarmoschamarométodogetTipo,oEclipsereclamouqueessemétodonãoexistenaclasseContaapesardeexistirnasclassesfilhas.Comoestamostratandotodasascontasgenericamente,sóconseguimosacessarosmétodosdaclassemãe.Vamosentãocolocá-lonaclasseConta:
publicclassConta{publicStringgetTipo(){return"Conta";}}
7. Agoraocódigocompilamastemosumoutroproblema.AlógicadonossosaquevazouparaaclasseManipuladorDeContas.Sealgumdiaprecisarmosalterarovalorda taxanosaque, teríamosquemudar em todos os lugares onde fazemos uso do método saca . Esta lógica deveria estarencapsuladadentrodométodosacadecadaconta.VamosentãosobrescreverométododentrodaclasseContaCorrente:
publicclassContaCorrenteextendsConta{@Overridepublicvoidsaca(doublevalor){this.saldo-=(valor+0.10);}
//restantedaclasse}
Repare que, para acessar o atributo saldo herdado da classeConta,você vai precisarmudar omodificadordevisibilidadedesaldoparaprotected.
Agora que a lógica está encapsulada, podemos corrigir o método saca da classeManipuladorDeContas:
publicvoidsaca(Eventoevento){doublevalor=evento.getDouble("valorOperacao");this.conta.saca(valor);}
Percebaqueagoratratamosacontadeformagenérica!
8. Rode a classe TestaContas, adicione uma conta de cada tipo e veja se o tipo é apresentadocorretamentenalistadecontasdatelainicial.
Agora,cliquenacontacorrenteapresentadanalistaparaabrirateladedetalhesdecontas.Testeasoperações de saque e depósito e perceba que a conta apresenta o comportamento de uma contacorrenteconformeoesperado.
Esetentarmosrealizarumatransferênciadacontacorrenteparaacontapoupança?Oqueacontece?
.
9. VamoscomeçarimplementandoométodotransferenaclasseConta:
publicvoidtransfere(doublevalor,Contaconta){this.saca(valor);conta.deposita(valor);}
Tambémprecisamos implementarométodotransfere na classeManipuladorDeContas parafazerovínculoentreatelaeaclasseConta:
publicvoidtransfere(Eventoevento){Contadestino=(Conta)evento.getSelecionadoNoCombo("destino");conta.transfere(evento.getDouble("valorTransferencia"),destino);}
Rodedenovoaaplicaçãoetesteaoperaçãodetransferência.
10. Considereocódigoabaixo:
Contac=newConta();ContaCorrentecc=newContaCorrente();ContaPoupancacp=newContaPoupanca();
Semudarmosessecódigopara:
Contac=newConta();Contacc=newContaCorrente();Contacp=newContaPoupanca();
Compila?Roda?Oquemuda?Qualéautilidadedisso?Realmente,essanãoéamaneiramaisútildopolimorfismo.Porémexisteumautilidadededeclararmosumavariáveldeumtipomenosespecíficodoqueoobjetorealmenteé,comofazemosnaclasseManipuladorDeContas.
Éextremamenteimportanteperceberquenãoimportacomonosreferimosaumobjeto,ométodoque será invocado é sempreomesmo!A JVMvaidescobrir em tempodeexecuçãoqualdeve serinvocado,dependendodequetipoéaqueleobjeto,nãoimportandocomonosreferimosaele.
11. (Opcional)AnossaclasseContadevolveapalavra "Conta"nométodogetTipo.Use a palavrachavesupernosmétodosgetTiporeescritosnasclassesfilhas,paranãoterdereescreveapalavra"Conta"aodevolverostipos"ContaCorrente"e"ContaPoupança".
12. (Opcional) Se vocêprecisasse criaruma classeContaInvestimento, e seumétodosaca fossecomplicadíssimo,vocêprecisariaalteraraclasseManipuladorDeContas?
.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
Discuta com o instrutor e seus colegas alternativas ao uso do atributo protected na herança.Preciso realmente afrouxar o encapsulamento do atributo por causa da herança? Como fazer para oatributocontinuarprivatenamãeeasfilhasconseguiremdealgumaformartrabalharcomele?
SaberinglêsémuitoimportanteemTI
9.8 DISCUSSÕES EM AULA: ALTERNATIVAS AO ATRIBUTOPROTECTED
.
CAPÍTULO10
"Dá-seimportânciaaosantepassadosquandojánãotemosnenhum."--FrançoisChateaubriand
Aotérminodessecapítulo,vocêserácapazdeutilizarclassesabstratas,quandonecessário.
Nestecapítulo,aconselhamosquevocêpasseausaroEclipse.VocêjátemconhecimentosuficientedoserrosdecompilaçãodojavaceagorapodeaprenderasfacilidadesqueoEclipsetetrazaoajudarvocênocódigocomoschamadosquickfixesequickassists.
VamosrecordaremcomopodeestarnossaclasseFuncionario:
publicclassFuncionario{
protectedStringnome;protectedStringcpf;protecteddoublesalario;
publicdoublegetBonificacao(){returnthis.salario*1.2;}
//outrosmétodosaqui
}
ConsidereonossoControleDeBonificacao:
publicclassControleDeBonificacoes{
privatedoubletotalDeBonificacoes=0;
publicvoidregistra(Funcionariof){System.out.println("Adicionandobonificaçãodofuncionario:"+f);this.totalDeBonificacoes+=f.getBonificacao();}
publicdoublegetTotalDeBonificacoes(){returnthis.totalDeBonificacoes;}}
Nossométodo registra recebe qualquer referência do tipo Funcionario, isto é, podem serobjetosdo tipoFuncionario e qualquerde seus subtipos:Gerente,Diretor e, eventualmente,
CLASSESABSTRATAS
10.1REPETINDOMAISCÓDIGO?
.
alguma nova subclasse que venha ser escrita, sem prévio conhecimento do autor daControleDeBonificacao.
EstamosutilizandoaquiaclasseFuncionarioparaopolimorfismo.Senãofosseela,teríamosumgrande prejuízo: precisaríamos criar um método registra para receber cada um dos tipos deFuncionario,umparaGerente,umparaDiretor,etc.Reparequeperderessepoderémuitopiordoqueapequenavantagemqueaherançatrazemherdarcódigo.
Porém,emalgunssistemas,comoéonossocaso,usamosumaclassecomapenasessesintuitos:deeconomizar um pouco código e ganhar polimorfismo para criar métodos mais genéricos, que seencaixemadiversosobjetos.
Faz sentido ter uma referência do tipoFuncionario? Essa pergunta é diferente de saber se fazsentidoterumobjetodotipoFuncionario:nessecaso,fazsimeémuitoútil.
ReferenciandoFuncionariotemosopolimorfismodereferência,jáquepodemosreceberqualquerobjetoquesejaumFuncionario.Porém,darnewemFuncionariopodenãofazersentido,istoé,não queremos receber umobjeto do tipoFuncionario,mas sim que aquela referência seja ou umGerente,ouumDiretor,etc.AlgomaisconcretoqueumFuncionario.
ControleDeBonificacoescdb=newControleDeBonificacoes();Funcionariof=newFuncionario();cdb.adiciona(f);//fazsentido?
Vejamosumoutrocasoemquenãofazsentidoterumobjetodaqueletipo,apesardaclasseexistir:imagineaclassePessoa e duas filhas,PessoaFisica ePessoaJuridica.Quandopuxamosumrelatóriodenossosclientes(umaarraydePessoaporexemplo),queremosquecadaumdelessejaouumaPessoaFisica,ouumaPessoaJuridica.A classePessoa, nesse caso, estaria sendousadaapenasparaganharopolimorfismoeherdaralgumascoisas:nãofazsentidopermitirinstanciá-la.
Pararesolveressesproblemas,temosasclassesabstratas.
.
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
Oque,exatamente,vemaseranossaclasseFuncionario?NossaempresatemapenasDiretores,Gerentes, Secretárias, etc. Ela é uma classe que apenas idealiza um tipo, define apenas umrascunho.
Paraonossosistema,éinadmissívelqueumobjetosejaapenasdotipoFuncionario(podeexistirumsistemaemquefaçasentidoterobjetosdotipoFuncionarioouapenasPessoa,mas,nonossocaso,não).
Usamosapalavrachaveabstractparaimpedirqueelapossaserinstanciada.Esseéoefeitodiretodeseusaromodificadorabstractnadeclaraçãodeumaclasse:
publicabstractclassFuncionario{
protecteddoublesalario;
publicdoublegetBonificacao(){returnthis.salario*1.2;}
//outrosatributosemétodoscomunsatodosFuncionarios
}
E,nomeiodeumcódigo:
Funcionariof=newFuncionario();//nãocompila!!!
EditoraCasadoCódigocomlivrosdeumaformadiferente
10.2CLASSEABSTRATA
.
Ocódigoacimanãocompila.Oproblemaé instanciaraclasse-criarreferência,vocêpode.Seelanãopodeserinstanciada,paraqueserve?Serveparaopolimorfismoeherançadosatributosemétodos,quesãorecursosmuitopoderosos,comojávimos.
Vamosentãoherdardessaclasse,reescrevendoométodogetBonificacao:
publicclassGerenteextendsFuncionario{
publicdoublegetBonificacao(){returnthis.salario*1.4+1000;}}
Mas qual é a real vantagem de uma classe abstrata? Poderíamos ter feito isto com uma herançacomum. Por enquanto, a única diferença é que não podemos instanciar um objeto do tipoFuncionario,quejáédegrandevalia,dandomaisconsistênciaaosistema.
FiqueclaroqueanossadecisãodetransformarFuncionarioemumaclasseabstratadependeudonossodomínio.Podeserque,emumsistemacomclassessimilares,façasentidoqueumaclasseanálogaaFuncionariosejaconcreta.
SeométodogetBonificacaonãofossereescrito,eleseriaherdadodaclassemãe,fazendocomquedevolvesseosaláriomais20%.
Levando em consideração que cada funcionário em nosso sistema tem uma regra totalmentediferenteparaserbonificado,fazalgumsentidoteressemétodonaclasseFuncionario?Seráqueexisteumabonificaçãopadrãopara todo tipodeFuncionario?Parecequenão, cada classe filha teráum
10.3MÉTODOSABSTRATOS
.
método diferente de bonificação pois, de acordo com nosso sistema, não existe uma regra geral:queremos que cada pessoa que escreve a classe de um Funcionario diferente (subclasses deFuncionario)reescrevaométodogetBonificacaodeacordocomassuasregras.
Poderíamos,então, jogarforaessemétododaclasseFuncionario?Oproblemaéque, seelenãoexistisse, não poderíamos chamar o método apenas com uma referência a um Funcionario, poisninguém garante que essa referência aponta para um objeto que possui essemétodo. Será que entãodevemosretornarumcódigo,comoumnúmeronegativo?Issonãoresolveoproblema:seesquecermosdereescreveressemétodo,teremosdadoserradossendoutilizadoscomobônus.
ExisteumrecursoemJavaque,emumaclasseabstrata,podemosescreverquedeterminadométodoserásempreescritopelasclassesfilhas.Istoé,ummétodoabstrato.
Ele indicaque todasasclasses filhas (concretas, istoé,quenão foremabstratas)devemreescreveressemétodoounãocompilarão.Écomosevocêherdassearesponsabilidadedeteraquelemétodo.
COMODECLARARUMMÉTODOABSTRATO
Àsvezes,nãoficaclarocomodeclararummétodoabstrato.
Bastaescreverapalavrachaveabstractnaassinaturadomesmoecolocarumpontoevírgulaemvezdeabreefechachaves!
publicabstractclassFuncionario{
publicabstractdoublegetBonificacao();
//outrosatributosemétodos
}
Reparequenãocolocamosocorpodométodoeusamosapalavrachaveabstractparadefiniromesmo. Por que não colocar corpo algum?Porque essemétodo nunca vai ser chamado, sempre quealguémchamarométodogetBonificacao,vaicairemumadassuasfilhas,querealmenteescreveramométodo.
Qualquer classe que estender a classe Funcionario será obrigada a reescrever este método,tornando-o"concreto".Senãoreescreveremessemétodo,umerrodecompilaçãoocorrerá.
OmétododoControleDeBonificacaoestavaassim:
publicvoidregistra(Funcionariof){System.out.println("Adicionandobonificaçãodofuncionario:"+f);this.totalDeBonificacoes+=f.getBonificacao();}
.
ComopossoacessarométodogetBonificacaoseelenãoexistenaclasseFuncionario?
Jáqueométodoéabstrato,comcerteza suas subclasses têmessemétodo,oquegaranteque essainvocação demétodo não vai falhar. Basta pensar que uma referência do tipoFuncionario nuncaapontaparaumobjetoquenão temométodogetBonificacao, poisnão épossível instanciarumaclasse abstrata, apenas as concretas. Ummétodo abstrato obriga a classe em que ele se encontra serabstrata,oquegaranteacoerênciadocódigoacimacompilar.
E se, no nosso exemplo de empresa, tivéssemos o seguinte diagrama de classes com os seguintesmétodos:
Ouseja,tenhoaclasseabstrataFuncionario,comométodoabstratogetBonificacao;asclassesGerenteePresidenteestendendoFuncionarioeimplementandoométodogetBonificacao;e,porfim,aclasseDiretor,queestendeGerente,masnãoimplementaométodogetBonificacao.
Essasclassesvãocompilar?Vãorodar?
Arespostaésim.E,alémdetudo,farãoexatamenteoquenósqueremos,pois,quandoGerenteePresidentepossuemosmétodosperfeitamenteimplementados,aclasseDiretor,quenãopossuiométodoimplementado,vaiusaraimplementaçãoherdadadeGerente.
10.4AUMENTANDOOEXEMPLO
.
E esse diagrama, no qual incluímos uma classe abstrata Secretaria sem o método getBonificacao , que é estendida por mais duas classes ( SecretariaAdministrativa ,SecretariaAgencia)que,porsuavez,implementamométodogetBonificacao,vaicompilar?Vairodar?
Denovo,arespostaésim,poisSecretariaéumaclasseabstratae,porisso,oJavatemcertezadeque ninguém vai conseguir instanciá-la e, muito menos, chamar o método getBonificacao dela.Lembrando que, nesse caso, não precisamos nem ao menos escrever o método abstratogetBonificacaonaclasseSecretaria.
Seeunãoreescreverummétodoabstratodaminhaclassemãe,ocódigonãocompilará.Masposso,emvezdisso,declararaclassecomoabstrata!
JAVA.IO
Classes abstratas nãopossuemnenhum segredono aprendizado,mas quem está aprendendoorientaçãoaobjetospodeterumaenormedificuldadeparasaberquandoutilizá-las,oqueémuitonormal.
Estudaremosopacotejava.io,queusabastantesclassesabstratas,sendoumexemplorealdeusodesserecurso,quevaimelhoraroentendimentodelas.(classeInputStreamesuasfilhas)
.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
Uma classe que estende uma classe normal também pode ser abstrata! Ela não poderá serinstanciada,massuaclassepaisim!
Umaclasseabstratanãoprecisanecessariamenteterummétodoabstrato.
1. ReparequeanossaclasseContaéumaexcelentecandidataparaumaclasseabstrata.Porquê?Quemétodosseriaminteressantescandidatosaseremabstratos?
TransformeaclasseContaemabstrata:
publicabstractclassConta{//...}
2. ComoaclasseContaagoraéabstrata,nãoconseguimosdarnewnelamais.SenãopodemosdarnewemConta,qualéautilidadedeterummétodoquerecebeumareferênciaaContacomoargumento?Aliás,possoterisso?
3. Apenasparaentendermelhoroabstract,comenteométodogetTipo()daContaPoupanca,dessaformaeleherdaráométododiretamentedeConta.
TransformeométodogetTipo()daclasseContaemabstrato.Repareque,aocolocarapalavrachaveabstract ao ladodométodo,oEclipse rapidamentevai sugerirquevocêdeve removerocorpo(body)dométodocomumquickfix.
SuaclasseContadeveficarparecidacom:
JáconheceoscursosonlineAlura?
10.5PARASABERMAIS...
10.6EXERCÍCIOS:CLASSESABSTRATAS
.
publicabstractclassConta{//atributosemétodosquejáexistiam
publicabstractStringgetTipo();}
QualéoproblemacomaclasseContaPoupanca?
4. DescomenteométodogetTipo na classeContaPoupanca, e se necessário altere-o para que aclassepossacompilarnormalmente.
5. (opcional) Existe outramaneira de a classe ContaPoupanca compilar se você não reescrever ométodoabstrato?
6. (opcional)PraqueterométodogetTiponaclasseContaseelenãofaznada?OqueacontecesesimplesmenteapagarmosessemétododaclasseContaedeixarmosométodogetTiponasfilhas?
7. (opcional) Posso chamar ummétodo abstrato de dentro de um outro método da própria classeabstrata?Porexemplo,imaginequeexistaoseguintemétodonaclasseConta:
publicStringrecuperaDadosParaImpressao(){Stringdados="Titular:"+this.titular;dados+="\nNúmero:"+this.numero;dados+="\nAgência:"+this.agencia;dados+="\nSaldo:R$"+this.saldo;returndados;}
PodemosinvocarogetTipodentrodestemétodo?Algocomo:
dados+="\nTipo:"+this.getTipo();
.
CAPÍTULO11
"Umaimagemvalemilpalavras.Umainterfacevalemilimagens."--BenShneiderman
Aotérminodessecapítulo,vocêserácapazde:
dizeroqueéumainterfaceeasdiferençasentreherançaeimplementação;escreverumainterfaceemJava;utilizá-lascomoumpoderosorecursoparadiminuiracoplamentoentreasclasses.
Imagine que umSistemadeControle doBanco pode ser acessado, alémde pelosGerentes, pelosDiretoresdoBanco.Então,teríamosumaclasseDiretor:
publicclassDiretorextendsFuncionario{
publicbooleanautentica(intsenha){//verificaaquiseasenhaconferecomarecebidacomoparametro}
}
EaclasseGerente:
publicclassGerenteextendsFuncionario{
publicbooleanautentica(intsenha){//verificaaquiseasenhaconferecomarecebidacomoparametro//nocasodogerenteverificatambémseodepartamentodele//temacesso}
}
INTERFACES
11.1AUMENTANDONOSSOEXEMPLO
.
ReparequeométododeautenticaçãodecadatipodeFuncionariopodevariarmuito.Masvamosaosproblemas.Considere oSistemaInterno e seu controle: precisamos receber umDiretor ouGerentecomoargumento,verificarseeleseautenticaecolocá-lodentrodosistema.
publicclassSistemaInterno{
publicvoidlogin(Funcionariofuncionario){//invocarométodoautentica?//nãoda!NemtodoFuncionariotem}}
OSistemaInternoaceitaqualquertipodeFuncionario,tendoeleacessoaosistemaounão,masnote que nem todo Funcionario possui ométodo autentica. Isso nos impede de chamar essemétodo com uma referência apenas aFuncionario (haveria um erro de compilação).O que fazerentão?
publicclassSistemaInterno{
publicvoidlogin(Funcionariofuncionario){funcionario.autentica(...);//nãocompila}}
UmapossibilidadeécriardoismétodosloginnoSistemaInterno:umparareceberDiretoreoutroparareceberGerente.Jávimosqueessanãoéumaboaescolha.Porquê?
publicclassSistemaInterno{
//designproblemáticopublicvoidlogin(Diretorfuncionario){funcionario.autentica(...);}
//designproblemáticopublicvoidlogin(Gerentefuncionario){funcionario.autentica(...);}
}
.
Cada vez que criarmos uma nova classe de Funcionario que é autenticável, precisaríamosadicionarumnovométododeloginnoSistemaInterno.
MÉTODOSCOMMESMONOME
EmJava,métodospodemteromesmonomedesdequenãosejamambíguos,istoé,queexistaumamaneiradedistinguirnomomentodachamada.
Issosechamasobrecargademétodo.(Overloading.Nãoconfundircomoverriding,queéumconceitomuitomaispoderoso).
Uma solução mais interessante seria criar uma classe no meio da árvore de herança,FuncionarioAutenticavel:
publicclassFuncionarioAutenticavelextendsFuncionario{
publicbooleanautentica(intsenha){//fazautenticacaopadrão}
//outrosatributosemétodos
}
As classes Diretor e Gerente passariam a estender de FuncionarioAutenticavel , e oSistemaInternoreceberiareferênciasdessetipo,comoaseguir:
publicclassSistemaInterno{
publicvoidlogin(FuncionarioAutenticavelfa){
intsenha=//pegasenhadeumlugar,oudeumscannerdepolegar
//aquieupossochamaroautentica!//PoistodoFuncionarioAutenticaveltembooleanok=fa.autentica(senha);
}}
.
Repare que FuncionarioAutenticavel é uma forte candidata a classe abstrata. Mais ainda, ométodoautenticapoderiaserummétodoabstrato.
O uso de herança resolve esse caso,mas vamos a uma outra situação um poucomais complexa:precisamosquetodososclientestambémtenhamacessoaoSistemaInterno.Oquefazer?UmaopçãoécriaroutrométodologinemSistemaInterno:masjádescartamosessaanteriormente.
Uma outra, que é comum entre os novatos, é fazer uma herança sem sentido para resolver oproblema, por exemplo, fazerClienteextendsFuncionarioAutenticavel. Realmente, resolve oproblema,mastrarádiversosoutros.ClientedefinitivamentenãoéFuncionarioAutenticavel.Sevocê fizer isso,oCliente terá, por exemplo, ummétodogetBonificacao, umatributo salario eoutrosmembrosquenãofazemomenorsentidoparaestaclasse!Nãofaçaherançaquandoarelaçãonãoéestritamente"éum".
.
Como resolver essa situação? Note que conhecer a sintaxe da linguagem não é o suficiente,precisamosestruturar/desenharbemanossaestruturadeclasses.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
O que precisamos para resolver nosso problema? Arranjar uma forma de poder referenciar
SaberinglêsémuitoimportanteemTI
11.2INTERFACES
.
Diretor,GerenteeClientedeumamesmamaneira,istoé,acharumfatorcomum.
Seexistisseuma formanaqual essas classesgarantissemaexistênciadeumdeterminadométodo,atravésdeumcontrato,resolveríamosoproblema.
Todaclassedefine2itens:
oqueumaclassefaz(asassinaturasdosmétodos)comoumaclassefazessastarefas(ocorpodosmétodoseatributosprivados)
Podemos criar um "contrato" que define tudo o que uma classe deve fazer se quiser ter umdeterminadostatus.Imagine:
contratoAutenticavel:
quemquiserserAutenticavelprecisasaberfazer:1.autenticardadaumasenha,devolvendoumbooleano
Quem quiser, pode "assinar" esse contrato, sendo assim obrigado a explicar como será feita essaautenticação.Avantageméque,seumGerenteassinaressecontrato,podemosnosreferenciaraumGerentecomoumAutenticavel.
PodemoscriaressecontratoemJava!
publicinterfaceAutenticavel{
booleanautentica(intsenha);
}
Chama-seinterfacepoiséamaneirapelaqualpoderemosconversarcomumAutenticavel.Interfaceéamaneiraatravésdaqualconversamoscomumobjeto.
Lemosainterfacedaseguintemaneira:"quemdesejarserautenticávelprecisasaberautenticardadoum inteiro e retornando um booleano". Ela é um contrato onde quem assina se responsabiliza porimplementaressesmétodos(cumprirocontrato).
Uma interfacepodedefinirumasériedemétodos,masnuncaconter implementaçãodeles.Ela sóexpõeoqueoobjetodevefazer,enãocomoelefaz,nemoqueeletem.Comoelefazvaiserdefinidoemumaimplementaçãodessainterface.
EoGerentepode"assinar"ocontrato,ouseja,implementarainterface.Nomomentoemqueeleimplementaessainterface,eleprecisaescreverosmétodospedidospelainterface(muitoparecidocomoefeitodeherdarmétodosabstratos,aliás,métodosdeuma interfacesãopúblicoseabstratos, sempre).Paraimplementarusamosapalavrachaveimplementsnaclasse:
publicclassGerenteextendsFuncionarioimplementsAutenticavel{
privateintsenha;
.
//outrosatributosemétodos
publicbooleanautentica(intsenha){if(this.senha!=senha){returnfalse;}//podefazeroutraspossíveisverificações,comosaberseesse//departamentodogerentetemacessoaoSistema
returntrue;}
}
Oimplementspodeserlidodaseguintemaneira:"AclasseGerentesecomprometeasertratadacomoAutenticavel,sendoobrigadaaterosmétodosnecessários,definidosnestecontrato".
Apartirdeagora,podemostratarumGerentecomosendoumAutenticavel.Ganhamosmaispolimorfismo!TemosmaisumaformadereferenciaraumGerente.QuandocrioumavariáveldotipoAutenticavel, estou criando uma referência paraqualquer objeto de uma classe que implementeAutenticavel,diretaouindiretamente:
Autenticavela=newGerente();//possoaquichamarométodoautentica!
Novamente, a utilização mais comum seria receber por argumento, como no nossoSistemaInterno:
publicclassSistemaInterno{
publicvoidlogin(Autenticavela){intsenha=//pegasenhadeumlugar,oudeumscannerdepolegarbooleanok=a.autentica(senha);
//aquieupossochamaroautentica!//nãonecessariamenteéumFuncionario!//Maisainda,eunãoseiqueobjetoa//referência"a"estáapontandoexatamente!Flexibilidade.
.
}
}
Pronto!EjápodemospassarqualquerAutenticavelparaoSistemaInterno.EntãoprecisamosfazercomqueoDiretortambémimplementeessainterface.
publicclassDiretorextendsFuncionarioimplementsAutenticavel{
//métodoseatributos,alémdeobrigatoriamenteteroautentica
}
PodemospassarumDiretor.Nodiaemquetivermosmaisumfuncionáriocomacessoaosistema,bastaqueeleimplementeessainterface,paraseencaixarnosistema.
QualquerAutenticavelpassadoparaoSistemaInternoestábomparanós.Reparequepoucoimporta quem o objeto referenciado realmente é, pois ele tem um método autentica que é onecessário para nosso SistemaInterno funcionar corretamente. Aliás, qualquer outra classe quefuturamenteimplementeessainterfacepoderáserpassadacomoargumentoaqui.
Autenticaveldiretor=newDiretor();Autenticavelgerente=newGerente();
Ou,seachamosqueoFornecedorprecisateracesso,bastaqueeleimplementeAutenticavel.Olhesóotamanhododesacoplamento:quemescreveuoSistemaInternosóprecisasaberqueeleéAutenticavel.
publicclassSistemaInterno{
publicvoidlogin(Autenticavela){//nãoimportaseeleéumgerenteoudiretor//seráqueéumfornecedor?//Eu,oprogramadordoSistemaInterno,nãomepreocupo//Invocareiométodoautentica}
}
.
NãofazdiferençaseéumDiretor,Gerente,Cliente ouqualquer classe que venhapor aí.Basta seguir o contrato! Mais ainda, cada Autenticavel pode se autenticar de uma maneiracompletamentediferentedeoutro.
Lembre-se: a interface define que todos vão saber se autenticar (o que ele faz), enquanto aimplementaçãodefinecomoexatamentevaiserfeito(comoelefaz).
Amaneiracomoosobjetossecomunicamnumsistemaorientadoaobjetosémuitomaisimportantedoquecomoelesexecutam.Oqueumobjetofazémaisimportantedoquecomoelefaz.Aquelesqueseguemessaregra,terãosistemasmaisfáceisdemanteremodificar.Comovocêjápercebeu,estaéumadasideiasprincipaisquequeremospassare,provavelmente,amaisimportantedetodoessecurso.
MAISSOBREINTERFACES:HERANÇAEMÉTODOSDEFAULT
Diferentementedasclasses,umainterfacepodeherdardemaisdeumainterface.Écomoumcontrato que depende que outros contratos sejam fechados antes deste valer. Você não herdamétodoseatributos,massimresponsabilidades.
Um outro recurso em interfaces são os métodos default a partir do Java 8. Você pode simdeclararummétodoconcreto,utilizandoapalavradefaultaolado,esuasimplementaçõesnãoprecisamnecessariamente reescrevê-lo.Veremos que isso acontece, por exemplo, comométodoList.sort,duranteocapítulodecoleções.Éumtruquemuitoutilizadoparapoderevoluirumainterfacesemquebrarcompatibilidadecomasimplementaçõesanteriores.
Interfaces representamuma barreira no aprendizado do Java: parece que estamos escrevendo umcódigoquenão servepranada, jáque teremosessa linha (a assinaturadométodo) escritanasnossasclassesimplementadoras.Essaéumamaneiraerradadesepensar.Oobjetivodousodeumainterfaceédeixarseucódigomaisflexívelepossibilitaramudançadeimplementaçãosemmaiorestraumas.Nãoéapenasumcódigodeprototipação,umcabeçalho!
Os mais radicais dizem que toda classe deve ser "interfaceada", isto é, só devemos nos referir aobjetos através de suas interfaces. Se determinada classe não tem uma interface, ela deveria ter. Osautoresdestematerialachamtalmedidaradicaldemais,porémousodeinterfacesemvezdeherançaéamplamente aconselhado. Você pode encontrar mais informações sobre o assunto nos livrosDesignPatterns,RefactoringeEffectiveJava.
NolivroDesignPatterns,logonoinício,osautorescitam2regras"deouro".Umaé"eviteherança,prefiracomposição"eaoutra,"programevoltadoainterfaceenãoàimplementação".
11.3DIFICULDADENOAPRENDIZADODEINTERFACES
.
Veremosousodeinterfacesnocapítulodecoleções,oquemelhoraoentendimentodoassunto.OexemplodainterfaceComparabletambémémuitoesclarecedor,ondeenxergamosoreaproveitamentodecódigoatravésdasinterfaces,alémdoencapsulamento.ParaométodoCollections.sort(),poucoimporta quem vai ser passado como argumento. Para ele, basta que a coleção seja de objetoscomparáveis.ElepodeordenarElefante,ConexaoouContaCorrente, desdeque implementemComparable.
Comofazercomquetodasaschamadasparabancosdedadosdiferentesrespeitemamesmaregra?Usandointerfaces!
Imagine uma interfaceConexao contendo todos os métodos necessários para a comunicação etroca de dados com um banco de dados. Cada banco de dados fica encarregado de criar a suaimplementaçãoparaessainterface.
QuemforusarumaConexaonãoprecisaseimportarcomqualobjetoexatamenteestátrabalhando,jáqueelevai cumpriropapelque todaConexao deve ter.Não importa se é uma conexão comumOracleouMySQL.
Apesar do java.sql.Connection não trabalhar bem assim, a ideia é muito similar, porém asconexõesvêmdeumafactorychamadaDriverManager.
Conexãoabancodedadosestáforadoescopodessetreinamento,maséumdosprimeirostópicosabordadosnocursoFJ-21,juntamentecomDAO.
11.4EXEMPLOINTERESSANTE:CONEXÕESCOMOBANCODEDADOS
.
UMPOUCOMAIS...
Possosubstituirtodaminhaherançaporinterfaces?Qualéavantagemeadesvantagem?
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
1. Nossobancoprecisatributardinheirodealgunsbensquenossosclientespossuem.Paraissovamoscriarumainterfacenopacotebr.com.caelum.contas.modelodonossoprojetofj11-contasjáexistente:
publicinterfaceTributavel{publicdoublegetValorImposto();publicStringgetTitular();publicStringgetTipo();}
Lemosessainterfacedaseguintemaneira:"todosquequiseremsertributávelprecisamsaberretornarovalordoimposto,devolvendoumdouble".
Algunsbenssãotributáveiseoutrosnão,ContaPoupancanãoétributável,jáparaContaCorrentevocêprecisapagar1%dacontaeoSeguroDeVidatemumataxafixade42reaismais2%dovalordoseguro.
AproveiteoEclipse!QuandovocêescreverimplementsTributavelnaclasseContaCorrente,oquickfixdoEclipsevaisugerirquevocêreescrevaométodo;escolhaessaopçãoe,depois,preenchaocorpodométodoadequadamente:
AprendasedivertindonaAluraStart!
11.5EXERCÍCIOS:INTERFACES
.
publicclassContaCorrenteextendsContaimplementsTributavel{
//outrosatributosemétodos
publicdoublegetValorImposto(){returnthis.getSaldo()*0.01;}}
CrieaclasseSeguroDeVida,aproveitandonovamentedoEclipse,paraobter:
publicclassSeguroDeVidaimplementsTributavel{privatedoublevalor;privateStringtitular;privateintnumeroApolice;
publicdoublegetValorImposto(){return42+this.valor*0.02;}
//gettersesettersparaosatributos}
2. Vamos criar a classeManipuladorDeSeguroDeVida dentro do pacote br.com.caelum.contaspara vincular a classeSeguroDeVida com a tela de criação de seguros. Esta classe deve ter umatributodotipoSeguroDeVida.
Crie também o método criaSeguro que deve receber um parâmetro do tipo Evento paraconseguirobterosdadosda tela.Vocêdevepegarosparâmetros "numeroApolice"do tipoint,"titular"dotipoStringe"valor"dotipodouble.
Ocódigofinaldeveficarparecidocomocódigoabaixo:
packagebr.com.caelum.contas;
importbr.com.caelum.contas.modelo.SeguroDeVida;importbr.com.caelum.javafx.api.util.Evento;
publicclassManipuladorDeSeguroDeVida{
privateSeguroDeVidaseguroDeVida;
publicvoidcriaSeguro(Eventoevento){this.seguroDeVida=newSeguroDeVida();this.seguroDeVida.setNumeroApolice(evento.getInt("numeroApolice"));this.seguroDeVida.setTitular(evento.getString("titular"));this.seguroDeVida.setValor(evento.getDouble("valor"));}}
3. ExecuteaclasseTestaContasetentecadastrarumnovosegurodevida.Osegurocadastradodeveaparecernatabeladesegurosdevida.
4. Queremosagorasaberqualovalortotaldosimpostosdetodosostributáveis.VamosentãocriaraclasseManipuladorDeTributaveis dentrodopacotebr.com.caelum.contas.Crie tambémométodocalculaImpostosquerecebeumparâmetrodotipoEvento:
.
packagebr.com.caelum.contas;
importbr.com.caelum.javafx.api.util.Evento;
publicclassManipuladorDeTributaveis{
publicvoidcalculaImpostos(Eventoevento){//aquicalcularemosototal}}
5. Agora que criamos o tributavel, vamos habilitar a última aba de nosso sistema. Altere a classeTestaContasparapassarovalortruenachamadadométodomostraTela.Observequeagoraque temos o seguro de vida funcionando, a tela de relatório já consegue imprimir o valor dosimpostosindividuaisdecadatipodeTributavel.
6. NométodocalculaImpostosprecisamosbuscarosvaloresdeimpostosdecadaTributavel esomá-los. Para saber a quantidade de tributáveis, a classe Evento possui ummétodo chamadogetTamanhoDaListaquedevereceberonomeda listadesejada,nocaso"listaTributaveis".ExistetambémumoutrométodoqueretornaumTributaveldeumadeterminadaposiçãodeumalista,ondeprecisamospassaronomedalistaeoíndicedoelemento.Precisamospercorreralistainteira,passandoporcadaposiçãoentãoutilizaremosumforparaisto.
packagebr.com.caelum.contas;
importbr.com.caelum.contas.modelo.Tributavel;importbr.com.caelum.javafx.api.util.Evento;
publicclassManipuladorDeTributaveis{
privatedoubletotal;
publicvoidcalculaImpostos(Eventoevento){total=0;inttamanho=evento.getTamanhoDaLista("listaTributaveis");for(inti=0;i<tamanho;i++){Tributavelt=evento.getTributavel("listaTributaveis",i);total+=t.getValorImposto();}}
publicdoublegetTotal(){returntotal;}}
Repare que, de dentro do ManipuladorDeTributaveis , você não pode acessar o métodogetSaldo,porexemplo,poisvocênãotemagarantiadequeoTributavelquevaiserpassadocomo argumento tem esse método. A única certeza que você tem é de que esse objeto tem osmétodosdeclaradosnainterfaceTributavel.
Éinteressanteenxergarqueasinterfaces(comoaqui,nocaso,Tributavel)costumamligarclassesmuito distintas, unindo-as por uma característica que elas tem em comum. No nosso exemplo,
.
SeguroDeVidaeContaCorrentesãoentidadescompletamentedistintas,porémambaspossuemacaracterísticadeseremtributáveis.
SeamanhãogovernocomeçaratributaratémesmoPlanoDeCapitalizacao,bastaqueessaclasseimplemente a interface Tributavel! Repare no grau de desacoplamento que temos: a classeGerenciadorDeImpostoDeRendanemimaginaquevaitrabalharcomoPlanoDeCapitalizacao.Para ela, o único fato que importa é que o objeto respeite o contrato de um tributável, isso é, ainterfaceTributavel.Novamente:programevoltadoàinterface,nãoàimplementação.
Quaisosbenefíciosdemanterocódigocombaixoacoplamento?
7. (opcional)CrieaclasseTestaTributavelcomummétodomainparatestaronossoexemplo:
publicclassTestaTributavel{
publicstaticvoidmain(String[]args){ContaCorrentecc=newContaCorrente();cc.deposita(100);System.out.println(cc.getValorImposto());
//testandopolimorfismo:Tributavelt=cc;System.out.println(t.getValorImposto());}}
TentechamarométodogetSaldoatravésdareferênciat,oqueocorre?Porquê?
AlinhaemqueatribuímosccaumTributaveléapenasparavocêenxergarqueépossívelfazê-lo.Nessenossocaso,issonãotemumautilidade.Essapossibilidadefoiútilnoexercícioanterior.
Atenção: caso você faça esse exercício, faça isso num projeto à parte conta-interface já queusaremosaContacomoclasseemexercíciosfuturos.
1. (Opcional)TransformeaclasseContaemumainterface.
publicinterfaceConta{publicdoublegetSaldo();publicvoiddeposita(doublevalor);publicvoidsaca(doublevalor);publicvoidatualiza(doubletaxaSelic);}
AdapteContaCorrenteeContaPoupancaparaessamodificação:
publicclassContaCorrenteimplementsConta{//...}
publicclassContaPoupancaimplementsConta{//...
11.6EXERCÍCIOSAVANÇADOSOPCIONAIS
.
}
Algumcódigovaiterdesercopiadoecolado?Issoétãoruim?
2. (Opcional)Àsvezes,éinteressantecriarmosumainterfacequeherdadeoutrasinterfaces:essas,sãochamadassubinterfaces.Essas,nadamaissãodoqueumagrupamentodeobrigaçõesparaaclassequeaimplementar.
publicinterfaceContaTributavelextendsConta,Tributavel{}
Dessamaneira, quem for implementar essa nova interface precisa implementar todos osmétodosherdadosdassuassuperinterfaces(etalvezaindanovosmétodosdeclaradosdentrodela):
publicclassContaCorrenteimplementsContaTributavel{//métodos}
Contac=newContaCorrente();Tributavelt=newContaCorrente();
Reparequeocódigopodeparecerestranho,poisainterfacenãodeclaramétodoalgum,sóherdaosmétodosabstratosdeclaradosnasoutrasinterfaces.
Aomesmotempoqueumainterfacepodeherdardemaisdeumaoutrainterface,classessópodempossuirumaclassemãe(herançasimples).
Discuta com o instrutor e seus colegas, alternativas à herança. Falaremos de herança versuscomposiçãoeporquêaherançaémuitasvezesconsideradamaléfica.
Numaentrevista,JamesGosling,"paidojava",falasobreumalinguagempuramentededelegaçãoechegaadizer:
Ratherthansubclassing,justusepureinterfaces.It'snotsomuchthatclassinheritanceisparticularlybad.Itjusthasproblems.
(Tradução livre: "Em vez de fazer subclasses, use simplesmente interfaces. Não é que a herança declassessejaparticularmenteruim.Elasótemproblemas.")
http://www.artima.com/intv/gosling3P.html
No blog da Caelum há também um post sobre o assunto:http://blog.caelum.com.br/2006/10/14/como-nao-aprender-orientacao-a-objetos-heranca/
11.7DISCUSSÃO:FAVOREÇACOMPOSIÇÃOEMRELAÇÃOÀHERANÇA
.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
Seuslivrosdetecnologiaparecemdoséculopassado?
.
CAPÍTULO12
"Quempensapouco,erramuito"--LeonardodaVinci
Aotérminodessecapítulo,vocêserácapazde:
controlarerrosetomardecisõesbaseadasnosmesmos;criarnovostiposdeerrosparamelhorarotratamentodelesemsuaaplicaçãooubiblioteca;assegurarqueummétodofuncionoucomodizemseu"contrato".
Voltando às Contas que criamos no capítulo 6, o que aconteceria ao tentar chamar ométodosacacomumvalorforadolimite?Osistemamostrariaumamensagemdeerro,masquemchamouométodosacanãosaberáqueissoaconteceu.
Comoavisaraquelequechamouométododequeelenãoconseguiufazeraquiloquedeveria?
Em Java, os métodos dizem qual o contrato que eles devem seguir. Se, ao tentar sacar, ele nãoconseguefazeroquedeveria,eleprecisa,aomenos,avisaraousuárioqueosaquenãofoifeito.
Vejanoexemploabaixo:estamosforçandoumaContaaterumvalornegativo, istoé,estarnumestadoinconsistentedeacordocomanossamodelagem.
ContaminhaConta=newConta();minhaConta.deposita(100);minhaConta.setLimite(100);minhaConta.saca(1000);//osaldoé-900?É100?É0?Achamadaaométodosacafuncionou?
Em sistemas de verdade, é muito comum que quem saiba tratar o erro é aquele que chamou ométodo e não a própria classe! Portanto, nada mais natural do que a classe sinalizar que um erroocorreu.
A solução mais simples utilizada antigamente é a de marcar o retorno de um método comobooleaneretornartrue,setudoocorreudamaneiraplanejada,oufalse,casocontrário:
booleansaca(doublequantidade){//possosacaratésaldo+limiteif(quantidade>this.saldo+this.limite){System.out.println("Nãopossosacarforadolimite!");returnfalse;
EXCEÇÕESECONTROLEDEERROS
12.1MOTIVAÇÃO
.
}else{this.saldo=this.saldo-quantidade;returntrue;}}
Umnovoexemplodechamadaaométodoacima:
ContaminhaConta=newConta();minhaConta.deposita(100);minhaConta.setLimite(100);if(!minhaConta.saca(1000)){System.out.println("Nãosaquei");}
Reparequetivemosdelembrardetestaroretornodométodo,masnãosomosobrigadosafazerisso.Esquecerdetestaroretornodessemétodoteriaconsequênciasdrásticas:amáquinadeautoatendimentopoderiaviraliberaraquantiadesejadadedinheiro,mesmoqueosistemanãotivesseconseguidoefetuarométodosacacomsucesso,comonoexemploaseguir:
ContaminhaConta=newConta();minhaConta.deposita(100);
//...doublevalor=5000;minhaConta.saca(valor);//vairetornarfalse,masninguémverifica!caixaEletronico.emite(valor);
Mesmo invocando o método e tratando o retorno de maneira correta, o que faríamos se fossenecessáriosinalizarquandoousuáriopassouumvalornegativocomoquantidade?Umasoluçãoseriaalteraroretornodebooleanparainteretornarocódigodoerroqueocorreu.Issoéconsideradoumamáprática(conhecidatambémcomousode"magicnumbers").
Alémdevocêperderoretornodométodo,ovalordevolvidoé"mágico"esólegívelperanteextensadocumentação,alémdenãoobrigaroprogramadoratrataresseretornoe,nocasodeesquecerisso,seuprogramacontinuarárodandojánumestadoinconsistente.
Repareoqueaconteceriasefossenecessárioretornarumoutrovalor.Oexemploabaixomostraumcasoonde, atravésdo retorno,não serápossíveldescobrir seocorreuumerroounão,poisométodoretornaumcliente.
publicClienteprocuraCliente(intid){if(idInvalido){//avisaométodoquechamouestequeocorreuumerro}else{Clientecliente=newCliente();cliente.setId(id);//cliente.setNome("nomedocliente");returncliente;}}
Poresseseoutrosmotivos,utilizamosumcódigodiferenteemJavaparatrataraquiloquechamamosde exceções: os casos onde acontece algo que, normalmente, não iria acontecer. O exemplo do
.
argumentodosaqueinválidooudoidinválidodeumclienteéumaexceçãoàregra.
EXCEÇÃO
Uma exceção representa uma situação que normalmente não ocorre e representa algo deestranhoouinesperadonosistema.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
Antesderesolvermosonossoproblema,vamosvercomoaJavaVirtualMachineageaosedepararcomsituaçõesinesperadas,comodivisãoporzeroouacessoaumíndicedaarrayquenãoexiste.
1. ParaaprendermososconceitosbásicosdasexceptionsdoJava,testeoseguintecódigovocêmesmo:
classTesteErro{publicstaticvoidmain(String[]args){System.out.println("iniciodomain");metodo1();System.out.println("fimdomain");}
staticvoidmetodo1(){System.out.println("iniciodometodo1");metodo2();System.out.println("fimdometodo1");}
staticvoidmetodo2(){System.out.println("iniciodometodo2");ContaCorrentecc=newContaCorrente();for(inti=0;i<=15;i++){cc.deposita(i+1000);System.out.println(cc.getSaldo());
JáconheceoscursosonlineAlura?
12.2EXERCÍCIOPARACOMEÇARCOMOSCONCEITOS
.
if(i==5){cc=null;}}System.out.println("fimdometodo2");}}
Repareométodomainchamandometodo1eesse,porsuavez,chamandoometodo2.Cadaumdessesmétodospodetersuasprópriasvariáveislocais,istoé:ometodo1nãoenxergaasvariáveisdeclaradasdentrodomaineporaíemdiante.
ComooJava(emuitasdasoutraslinguagens)fazisso?Todainvocaçãodemétodoéempilhadaemuma estrutura de dados que isola a área dememória de cada um. Quando ummétodo termina(retorna), ele volta para ométodoque o invocou.Ele descobre isso através dapilhade execução(stack):bastaremoveromarcadorqueestánotopodapilha:
Porém, o nosso metodo2 propositadamente possui um enorme problema: está acessando umareferêncianulaquandooíndiceforiguala6!
Rodeocódigo.Qualéasaída?Oqueissorepresenta?Oqueelaindica?
Essa saída é o conhecido rastro da pilha (stacktrace). É uma saída importantíssima para oprogramador - tanto que, em qualquer fórum ou lista de discussão, é comum os programadoresenviarem,juntamentecomadescriçãodoproblema,essastacktrace.Masporqueissoaconteceu?
O sistema de exceções do Java funciona da seguinte maneira: quando uma exceção é lançada(throw), a JVMentra em estadode alerta e vai ver se ométodo atual toma algumaprecaução aotentarexecutaressetrechodecódigo.Comopodemosver,ometodo2nãotomanenhumamedidadiferentedoquevimosatéagora.
.
Comoometodo2nãoestátratandoesseproblema,aJVMpáraaexecuçãodeleanormalmente,semesperareleterminar,evoltaumstackframeprabaixo,ondeseráfeitanovaverificação:"ometodo1está se precavendo de um problema chamado NullPointerException?" "Não..." Volta para omain, onde tambémnãoháproteção, então a JVMmorre (na verdade, quemmorre é apenas a Thread corrente; se quiser saber mais sobre, há um apêndice de Threads e ProgramaçãoConcorrentenofinaldaapostila).
Obviamente,aquiestamosforçandoessecasoenãofariasentidotomarmoscuidadocomele.Éfácilarrumar um problema desses: basta verificar antes de chamar osmétodos se a variável está comreferêncianula.
Porém,apenasparaentenderocontroledefluxodeumaException,vamoscolocarocódigoquevaitentar(try)executaroblocoperigosoe,casooproblemasejadotipoNullPointerException,eleserápego(caught).ReparequeéinteressantequecadaexceçãonoJavatenhaumtipo...elapodeteratributosemétodos.
2. Adicioneumtry/catchemvoltadofor,pegandoNullPointerException.Oqueo códigoimprime?
try{for(inti=0;i<=15;i++){cc.deposita(i+1000);System.out.println(cc.getSaldo());if(i==5){cc=null;}}}catch(NullPointerExceptione){System.out.println("erro:"+e);}
3. Emvezdefazerotryemtornodoforinteiro,tenteapenascomoblocodedentrodofor:
for(inti=0;i<=15;i++){try{
.
cc.deposita(i+1000);System.out.println(cc.getSaldo());if(i==5){cc=null;}}catch(NullPointerExceptione){System.out.println("erro:"+e);}}
Qualéadiferença?
4. Retireotry/catchecoloqueeleemvoltadachamadadometodo2.
System.out.println("iniciodometodo1");try{metodo2();}catch(NullPointerExceptione){System.out.println("erro:"+e);}System.out.println("fimdometodo1");
.
5. Façaomesmo,retirandootry/catchnovamenteecolocandoemvoltadachamadadometodo1.Rodeoscódigos,oqueacontece?
System.out.println("iniciodomain");try{metodo1();}catch(NullPointerExceptione){System.out.println("erro:"+e);}System.out.println("fimdomain");
Repareque,apartirdomomentoqueumaexceptionfoicatched(pega,tratada,handled),aexecuçãovoltaaonormalapartirdaqueleponto.
12.3EXCEÇÕESDERUNTIMEMAISCOMUNS
.
Quetaltentardividirumnúmeroporzero?SeráqueaJVMconseguefazeraquiloquenósdefinimosquenãoexiste?
publicclassTestandoADivisao{
publicstaticvoidmain(String[]args){inti=5571;i=i/0;System.out.println("Oresultado"+i);}}
Tenteexecutaroprogramaacima.Oqueacontece?
ReparequeumNullPointerExceptionpoderiaserfacilmenteevitadocomumifquechecariaseareferênciaédiferentedenull.
Outrocasoemquetambémocorretaltipodeexceçãoéquandoumcasterradoéfeito(veremosmaisprafrente).Emtodososcasos,taisproblemasprovavelmentepoderiamserevitadospeloprogramador.Époressemotivoqueojavanãoteobrigaadarotry/catchnessasexceptionsechamamosessasexceçõesdeunchecked.Emoutraspalavras,ocompiladornãochecasevocêestátratandoessasexceções.
ERROS
Oserros em Java sãoum tipode exceçãoque tambémpodemser tratados.Eles representamproblemasnamáquinavirtualenãodevemsertratadosem99%doscasos,jáqueprovavelmenteomelhorasefazerédeixaraJVMencerrar(ouapenasaThreademquestão).
Ficaclaro,comosexemplosdecódigoacima,quenãoénecessáriodeclararquevocêestátentandofazeralgoondeumerropossaocorrer.Osdoisexemplos, comousemotry/catch, compilaramerodaram.Emum,oerroterminouoprogramae,nooutro,foipossíveltratá-lo.
MasnãoésóessetipodeexceçãoqueexisteemJava.Umoutrotipo,obrigaaquemchamaométodoou construtor a tratar essa exceção. Chamamos esse tipo de exceção de checked, pois o compiladorchecaráseelaestásendodevidamentetratada,diferentedasanteriores,conhecidascomounchecked.
12.4OUTROTIPODEEXCEÇÃO:CHECKEDEXCEPTIONS
.
Umexemplointeressanteéodeabrirumarquivoparaleitura,ondepodeocorreroerrodoarquivonãoexistir(veremoscomotrabalharcomarquivosemoutrocapítulo,nãosepreocupecomistoagora):
classTeste{publicstaticvoidmetodo(){newjava.io.FileInputStream("arquivo.txt");}}
O código acima não compila e o compilador avisa que é necessário tratar oFileNotFoundExceptionquepodeocorrer:
Paracompilarefazeroprogramafuncionar,temosduasmaneirasquepodemostrataroproblema.O primeiro, é tratá-lo com otry ecatch domesmo jeito que usamos no exemplo anterior, dereferêncianula:
publicstaticvoidmetodo(){
try{newjava.io.FileInputStream("arquivo.txt");}catch(java.io.FileNotFoundExceptione){System.out.println("Naofoipossívelabriroarquivoparaleitura");}
}
Asegundaformadetrataresseerro,édelegareleparaquemchamouonossométodo,istoé,passarparaafrente.
publicstaticvoidmetodo()throwsjava.io.FileNotFoundException{
newjava.io.FileInputStream("arquivo.txt");
}
NoEclipseébemsimplesfazertantoumtry/catchcomoumthrows:
Tentedigitaressecódigonoeclipse:
publicclassTestaException{publicstaticvoidmain(String[]args){newjava.io.FileInputStream("arquivo.txt");}}
OEclipsevaireclamar:
.
Evocêtemduasopções:
Addthrowsdeclaration,quevaigerar:
publicclassTestaException{publicstaticvoidmain(String[]args)throwsFileNotFoundException{newjava.io.FileInputStream("arquivo.txt");}}
Surroundwithtry/catch,quevaigerar:
publicclassTestaException2{publicstaticvoidmain(String[]args){try{newjava.io.FileInputStream("arquivo.txt");}catch(FileNotFoundExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}
No início, existe uma grande tentação de sempre passar o problema pra frente para outros otratarem.Podeserquefaçasentido,dependendodocaso,masnãoatéomain,porexemplo.Aconteceque quem tenta abrir um arquivo sabe como lidar com um problema na leitura.Quem chamou ummétodonocomeçodoprogramapodenãosaberou,piorainda,tentarabrircincoarquivosdiferentesenãosaberqualdelesteveumproblema!
Não há uma regra para decidir em que momento do seu programa você vai tratar determinadaexceção. Isso vai depender de em que ponto você tem condições de tomar uma decisão em relaçãoàqueleerro.Enquantonãoforomomento,vocêprovavelmentevaipreferirdelegararesponsabilidadeparaométodoqueteinvocou.
.
BOASPRÁTICASNOTRATAMENTODEEXCEÇÕES
NoblogdaCaelumháumextensoartigodiscutindoasboaspráticasemrelaçãoaotratamentodeexceções.
http://blog.caelum.com.br/2006/10/07/lidando-com-exceptions/
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
UmapequenapartedaFamíliaThrowable:
SaberinglêsémuitoimportanteemTI
12.5UMPOUCODAGRANDEFAMÍLIATHROWABLE
.
Épossíveltratarmaisdeumerroquasequeaomesmotempo:
Comotryecatch:
try{objeto.metodoQuePodeLancarIOeSQLException();}catch(IOExceptione){//..}catch(SQLExceptione){//..}
Comothrows:
publicvoidabre(Stringarquivo)throwsIOException,SQLException{//..}
Vocêpode,também,escolhertrataralgumasexceçõesedeclararasoutrasnothrows:
publicvoidabre(Stringarquivo)throwsIOException{try{objeto.metodoQuePodeLancarIOeSQLException();}catch(SQLExceptione){//..}}
Édesnecessáriodeclararnothrowsasexceptionsquesãounchecked,porémépermitidoeàsvezes,facilitaaleituraeadocumentaçãodoseucódigo.
12.6MAISDEUMERRO
.
Lembre-sedométodosacadanossaclasseConta.Eledevolveumbooleancasoconsigaounãosacar:
publicbooleansaca(doublevalor){if(this.saldo<valor){returnfalse;}else{this.saldo-=valor;returntrue;}}
Podemos,também,lançarumaException,oqueéextremamenteútil.Dessamaneira,resolvemosoproblemadealguémpoderesquecerdefazerumifnoretornodeummétodo.
Apalavra chave throw, que está no imperativo, lança umaException. Isto é bem diferente dethrows,queestánopresentedoindicativo,equeapenasavisadapossibilidadedaquelemétodolançá-la,obrigandoooutrométodoqueváutilizardestedesepreocuparcomessaexceçãoemquestão.
publicvoidsaca(doublevalor){if(this.saldo<valor){thrownewRuntimeException();}else{this.saldo-=valor;}}
Nonossocaso, lançaumado tipounchecked.RuntimeException é a exceptionmãede todas asexceptionsunchecked.Adesvantagem,aqui,équeelaémuitogenérica;quemreceberesseerronãosabedizerexatamentequalfoioproblema.PodemosentãousarumaExceptionmaisespecífica:
publicvoidsaca(doublevalor){if(this.saldo<valor){thrownewIllegalArgumentException();}else{this.saldo-=valor;}}
IllegalArgumentExceptiondizumpoucomais:algofoipassadocomoargumentoeseumétodonão gostou. Ela é uma Exception unchecked pois estende de RuntimeException e já faz parte dabibliotecadojava.(IllegalArgumentExceptionéamelhorescolhaquandoumargumentosempreéinválidocomo,porexemplo,númerosnegativos,referênciasnulas,etc).
Parapegaresseerro,nãousaremosumif/elseesimumtry/catch,porquefazmaissentidojáqueafaltadesaldoéumaexceção:
Contacc=newContaCorrente();cc.deposita(100);
try{cc.saca(100);
12.7LANÇANDOEXCEÇÕES
.
}catch(IllegalArgumentExceptione){System.out.println("SaldoInsuficiente");}
Podíamos melhorar ainda mais e passar para o construtor da IllegalArgumentException omotivodaexceção:
publicvoidsaca(doublevalor){if(this.saldo<valor){thrownewIllegalArgumentException("Saldoinsuficiente");}else{this.saldo-=valor;}}
Ométodo getMessage() definido na classe Throwable (mãe de todos os tipos de erros eexceptions)vairetornaramensagemquepassamosaoconstrutordaIllegalArgumentException.
try{cc.saca(100);}catch(IllegalArgumentExceptione){System.out.println(e.getMessage());}
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
Imaginequevamossacardinheirodediversascontas:
Contacc=newContaCorrente();cc.deposita(100);
Contacp=newContaPoupanca();cp.deposita(100);
//sacandodascontas:
AprendasedivertindonaAluraStart!
12.8OQUECOLOCARDENTRODOTRY?
.
cc.saca(50);System.out.println("conseguisacardacorrente!");
cp.saca(50);System.out.println("conseguisacardapoupança!");
Podemosescolhervárioslugaresparacolocartry/catch:
try{cc.saca(50);}catch(IllegalArgumentExceptione){System.out.println(e.getMessage());}System.out.println("conseguisacardacorrente!");
try{cp.saca(50);}catch(IllegalArgumentExceptione){System.out.println(e.getMessage());}System.out.println("conseguisacardapoupança!");
Essa não parece uma opção boa, pois a mensagem "consegui sacar" será impressa mesmo que ocatchsejaacionado.Semprequetemosalgoquedependedalinhadecimaparasercorreto,devemosagrupá-lonotry:
try{cc.saca(50);System.out.println("conseguisacardacorrente!");}catch(IllegalArgumentExceptione){System.out.println(e.getMessage());}
try{cp.saca(50);System.out.println("conseguisacardapoupança!");}catch(IllegalArgumentExceptione){System.out.println(e.getMessage());}
Mas há ainda uma outra opção: imagine que, para o nosso sistema, uma falha ao sacar da contapoupançadevepararoprocessodesaquesenemtentarsacardacontacorrente.Paraisso,agruparíamosmaisainda:
try{cc.saca(50);System.out.println("conseguisacardacorrente!");cp.saca(50);System.out.println("conseguisacardapoupança!");}catch(IllegalArgumentExceptione){System.out.println(e.getMessage());}
Oquevocêvaicolocardentrodotry influenciamuitoaexecuçãodoprograma!Pensedireitonaslinhasquedependemumadaoutraparaaexecuçãocorretadasualógicadenegócios.
.
Ébemcomumcriarumaprópriaclassedeexceçãoparacontrolarmelhorousode suasexceções.Dessamaneira,podemospassarvaloresespecíficosparaelacarregar,quesejamúteisdealgumaforma.Vamoscriaranossa:
Voltamos para o exemplo das Contas , vamos criar a nossa Exceção deSaldoInsuficienteException:
publicclassSaldoInsuficienteExceptionextendsRuntimeException{
publicSaldoInsuficienteException(Stringmessage){super(message);}}
Emvezde lançarumIllegalArgumentException, vamos lançar nossa própria exception, comumamensagemquedirá"SaldoInsuficiente":
publicvoidsaca(doublevalor){if(this.saldo<valor){thrownewSaldoInsuficienteException("SaldoInsuficiente,"+"tenteumvalormenor");}else{this.saldo-=valor;}}
E,paratestar,crieumaclassequedepositeumvaloretentesacarumvalormaior:
publicstaticvoidmain(String[]args){Contacc=newContaCorrente();cc.deposita(10);
try{cc.saca(100);}catch(SaldoInsuficienteExceptione){System.out.println(e.getMessage());}}
PodemostransformaressaExceptiondeuncheckedparachecked, obrigandoaquemchamaessemétodoadartry-catch,outhrows:
publicclassSaldoInsuficienteExceptionextendsException{
publicSaldoInsuficienteException(Stringmessage){super(message);}}
Osblocostryecatchpodemconterumaterceiracláusulachamadafinallyqueindicaoquedeveserfeitoapósotérminodoblocotryoudeumcatchqualquer.
12.9CRIANDOSEUPRÓPRIOTIPODEEXCEÇÃO
12.10PARASABERMAIS:FINALLY
.
Éinteressantecolocaralgoqueéimprescindíveldeserexecutado,casooquevocêqueriafazertenhadado certo, ou não.O casomais comum é o de liberar um recurso no finally, como um arquivo ouconexãocombancodedados,paraquepossamosteracertezadequeaquelearquivo(ouconexão)váserfechado,mesmoquealgotenhafalhadonodecorrerdocódigo.
Noexemploaseguir,oblocofinallyserásempreexecutado,independentementedetudoocorrerbemoudeaconteceralgumproblema:
try{//blocotry}catch(IOExceptionex){//blococatch1}catch(SQLExceptionsqlex){//blococatch2}finally{//blocoqueserásempreexecutado,independente//sehouveounãoexceptioneseelafoitratadaounão}
Hátambém,noJava7,umrecursopoderosoconhecidocomotry-with-resources,quepermiteutilizarasemânticadofinallydeumamaneirabemmaissimples.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
1. Na classe Conta,modifique ométodo deposita(doublex): Ele deve lançar uma exceptionchamadaIllegalArgumentException,quejáfazpartedabibliotecadoJava,semprequeovalorpassadocomoargumentoforinválido(porexemplo,quandofornegativo).
publicvoiddeposita(doublevalor){if(valor<0){thrownewIllegalArgumentException();}else{this.saldo+=valor;}
Seuslivrosdetecnologiaparecemdoséculopassado?
12.11EXERCÍCIOS:EXCEÇÕES
.
}
2. Rodeaaplicação,cadastreumacontaetentedepositarumvalornegativo.Oqueacontece?
3. Ao lançar a IllegalArgumentException, passe via construtor uma mensagem a ser exibida.LembrequeaString recebidacomoparâmetroéacessíveldepoisviaométodogetMessage()herdadoportodasasExceptions.
publicvoiddeposita(doublevalor){if(valor<0){thrownewIllegalArgumentException("Vocêtentoudepositar"+"umvalornegativo");}else{this.saldo+=valor;}}
Rodeaaplicaçãonovamenteevejaqueagoraamensagemaparecenatela.
4. FaçaomesmoparaométodosacadaclasseContaCorrente,afinaloclientetambémnãopodesacarumvalornegativo!
5. Vamosvalidartambémqueoclientenãopodesacarumvalormaiordoqueosaldodisponívelemconta.CriesuaprópriaException,SaldoInsuficienteException.Paraisso,vocêprecisacriarumaclassecomessenomequesejafilhadeRuntimeException.
publicclassSaldoInsuficienteExceptionextendsRuntimeException{
}
NométodosacadaclasseContaCorrentevamosutilizarestanovaException:
@Overridepublicvoidsaca(doublevalor){if(valor<0){thrownewIllegalArgumentException("Vocêtentousacarumvalornegativo");}if(this.saldo<valor){thrownewSaldoInsuficienteException();}this.saldo-=(valor+0.10);}
Atenção:nemsempreéinteressantecriarmosumnovotipodeexception!Dependedocaso.Nesteaqui,seriamelhoraindautilizarmosIllegalArgumentException.AboapráticadizquedevemospreferirusarasjáexistentesdoJavasemprequepossível.
6. (opcional)ColoqueumconstrutornaclasseSaldoInsuficienteExceptionquerecebaovalorqueeletentousacar(istoé,elevaireceberumdoublevalor).
Quandoestendemosumaclasse,nãoherdamosseusconstrutores,maspodemosacessá-losatravésdapalavrachavesuperdedentrodeumconstrutor.Asexceçõesdo Javapossuemumasériedeconstrutores úteis para poder populá-las já com umamensagem de erro. Então vamos criar um
.
construtoremSaldoInsuficienteExceptionquedelegueparaoconstrutordesuamãe.Essavaiguardaressamensagemparapodermostrá-laaoserinvocadoométodogetMessage:
publicclassSaldoInsuficienteExceptionextendsRuntimeException{
publicSaldoInsuficienteException(doublevalor){super("Saldoinsuficienteparasacarovalorde:"+valor);}}
Dessamaneira, na hora de dar o throw new SaldoInsuficienteException você vai precisarpassaressevalorcomoargumento:
if(this.saldo<valor){thrownewSaldoInsuficienteException(valor);}
Atenção: você pode se aproveitar do Eclipse para isso: comece já passando o valor comoargumentoparaoconstrutordaexceptioneoEclipsevaireclamarquenãoexistetalconstrutor.Oquickfix(ctrl+1)vaisugerirqueelesejaconstruindo,poupando-lhetempo!
Eagora,comoficaométodosacadaclasseContaCorrente?
7. (opcional)DeclareaclasseSaldoInsuficienteException comofilhadiretadeException emvezdeRuntimeException.Elapassaaserchecked.Oqueissoresulta?
Vocêvaiprecisaravisarqueoseumétodosaca()throwsSaldoInsuficienteException,poiselaéumacheckedexception.Alémdisso,quemchamaessemétodovaiprecisartomarumadecisãoentretry-catchouthrows.FaçausodoquickfixdoEclipsenovamente!
Depois, retorne a exception para unchecked, isto é, para ser filha de RuntimeException, poisutilizaremoselaassimemexercíciosdoscapítulosposteriores.
1. Oqueaconteceseacabaramemóriadajavavirtualmachine?
ExisteumapéssimapráticadeprogramaçãoemjavaqueéadeescreverocatcheothrowscomException.
ExistemcódigosquesempreusamExceptionpoisissocuidadetodosospossíveiserros.Omaiorproblemadisso é generalizar o erro. Se alguém joga algodo tipoException paraquemo chamou,quemrecebenãosabequalotipoespecíficodeerroocorreuenãovaisabercomotrataromesmo.
Sim,hácasosondeotratamentodemaisdeumaexceptionpodeserfeitodeumamesmamaneira.
12.12DESAFIOS
12.13DISCUSSÃOEMAULA:CATCHETHROWSEMEXCEPTION
.
Por exemplo, se queremos terminar a aplicação tanto no caso de IOException quanto emSQLException.Sefizermoscatch(Exceptione)parapegaressesdoiscasos,teremosumproblema:aaplicaçãovaipararmesmoqueoutraexceçãosejalançada.Asoluçãocorretaseriaterdoiscatches,masaí teríamoscódigorepetido.Paraevitarocódigorepetido,podemosusaromulti-catchdoJava7,quepermite um mesmo catch cuidar de mais de 1 exceção, através da sintaxe catch(IOException |SQLExceptione){...}.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
Agoraéamelhorhoraderespirarmaistecnologia!
.
CAPÍTULO13
"Nossascabeçassãoredondasparaqueospensamentospossammudardedireção."--FrancisPiacaba
Aotérminodessecapítulo,vocêserácapazde:
utilizarasprincipaisclassesdopacotejava.lange leradocumentaçãopadrãodeprojetosjava;usaraclasseSystemparaobterinformaçõesdosistema;utilizaraclasseStringdeumamaneiraeficienteeconhecerseusdetalhes;utilizarosmétodosherdadosdeObjectparageneralizarseuconceitodeobjetos.
Jáusamos,pordiversasvezes,asclassesStringeSystem.VimososistemadepacotesdoJavaenunca precisamos dar um import nessas classes. Isso ocorre porque elas estão dentro do pacotejava.lang,queéautomaticamenteimportadoparavocê.Éoúnicopacotecomestacaracterística.
Vamosverumpoucodesuasprincipaisclasses.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
OPACOTEJAVA.LANG
13.1PACOTEJAVA.LANG
Seuslivrosdetecnologiaparecemdoséculopassado?
13.2UMPOUCOSOBREACLASSESYSTEM
.
A classe System possui uma série de atributos e métodos estáticos. Já usamos o atributoSystem.out,paraimprimir.
Olhandoadocumentação,vocêvaiperceberqueoatributooutédotipoPrintStreamdopacotejava.io. Veremos sobre essa classemais adiante. Já podemos perceber que poderíamos quebrar oSystem.out.printlnemduaslinhas:
PrintStreamsaida=System.out;saida.println("olamundo!");
OSystemcontatambémcomummétodoquesimplesmentedesligaavirtualmachine,retornandoumcódigodeerroparaosistemaoperacional,éoexit.
System.exit(0);
VeremostambémumpoucomaissobreaclasseSystemnospróximoscapítulosenoapêndicedeThreads.ConsulteadocumentaçãodoJavaevejaoutrosmétodosúteisdaSystem.
Todométodoqueprecisamosreceberalgumparâmetro temosquedeclararo tipodomesmo.Porexemplo,nonossométodosacaprecisamospassar comoparâmetroumvalordo tipodouble. Setentarmospassarqualquercoisadiferentedissoteremosumerrodecompilação.
AgoravamosobservaroseguintemétododopróprioJava:
System.out.println("Olámundo!");
Nestecaso,ométodoprintlnestárecebendoumaString epoderíamospensarqueo tipodeparâmetroqueelerecebeéString.Masaomesmo tempopodemospassarparaessemétodocoisascompletamentediferentescomoint,Conta,Funcionario,SeguroDeVida,etc.Comoessemétodoconseguerecebertantosparâmetrosdetiposdiferentes?
Umapossibilidade seria o uso da sobrecarga, declarandoumprintln para cada tipo de objetodiferente. Mas claramente não é isso que acontece já que conseguimos criar uma classe qualquer einvocarométodoprintlnpassandoessanovaclassecomoparâmetroeelefuncionaria!
Paraentenderoqueestáacontecendo,vamosconsiderarummétodoquerecebeumaConta:
publicvoidimprimeDados(Contaconta){System.out.println(conta.getTitular()+"-"+conta.getSaldo());}
Essemétodo pode ser invocado passando como parâmetro qualquer tipo de conta que temos nonossosistema:ContaCorrenteeContaPoupancapoisambassãofilhasdeConta. Se quiséssemosqueonossométodoconseguissereceberqualquertipodeobjetoteríamosqueterumaclassequefossemãedetodosessesobjetos.ÉparaissoqueexisteaclasseObject!
13.3JAVA.LANG.OBJECT
.
Semprequandodeclaramosumaclasse,essaclasseéobrigada aherdardeoutra. Istoé,para todaclassequedeclararmos,existeumasuperclasse.Porém,criamosdiversasclassessemherdardeninguém:
classMinhaClasse{
}
Quandoo Javanãoencontraapalavrachaveextends, ele consideraque você estáherdandodaclasseObject,quetambémseencontradentrodopacotejava.lang.Vocêatémesmopodeescreveressaherança,queéomesmo:
publicclassMinhaClasseextendsObject{
}
Todasasclasses,semexceção,herdamdeObject,sejadiretaouindiretamente,poiselaéamãe,vó,bisavó,etcdequalquerclasse.
Podemos tambémafirmarquequalquerobjetoemJavaéumObject, podendo ser referenciadocomo tal. Então, qualquer objeto possui todos osmétodos declarados na classe Object e veremosalgunsdeleslogoapósocasting.
A habilidade de poder se referir a qualquer objeto como Object nos traz muitas vantagens.Podemos criar ummétodo que recebe um Object como argumento, isto é, qualquer objeto! Porexemplo,ométodoprintlnpoderiaserimplementadodaseguintemaneira:
publicvoidprintln(Objectobj){write(obj.toString());//ométodowriteescreveumastringnoconsole}
Dessaforma,qualquerobjetoquepassarmoscomoparâmetropoderáserimpressonoconsoledesdequeelepossuaométodotoString.ParagarantirquetodososobjetosdoJavapossuamessemétodo,elefoiimplementadonaclasseObject.
Por padrão, o método toString do Object retorna o nome da classe @ um número deidentidade:
Conta@34f5d74a
Masesequisermosimprimiralgodiferente?Nanossateladedetalhesdeconta,temosumacaixadeseleçãoondenossascontasestãosendoapresentadascomovalordopadrãodotoString.Semprequequeremos modificar o comportamento de um método em relação a implementação herdada dasuperclasse,podemossobrescrevê-lonaclassefilha:
publicabstractclassConta{
13.4MÉTODOSDOJAVA.LANG.OBJECT:EQUALSETOSTRING
toString
.
protecteddoublesaldo;//outrosatributos...
@OverridepublicStringtoString(){return"[titular="+titular+",numero="+numero+",agencia="+agencia+"]";}}
Agorapodemosusaressemétodoassim:
ContaCorrentecc=newContaCorrente();System.out.println(cc.toString());
E o melhor, se for apenas para jogar na tela, você nem precisa chamar o toString! Ele já échamadoparavocê:
ContaCorrentecc=newContaCorrente();System.out.println(cc);//OtoStringéchamadopelaclassePrintStream
Geraomesmoresultado!
VocêaindapodeconcatenarStringsemJavacomooperador+.SeoJavaencontraumobjetonomeiodaconcatenação,eletambémchamaotoStringdele.
ContaCorrentecc=newContaCorrente();System.out.println("Conta:"+cc);
Atéagoraestamosignorandoofatoquepodemosmaisdeumacontademesmonúmeroeagêncianonossosistema.Atualmente,quandoinserimosumanovaconta,osistemaverificaseacontainseridaéigualaalgumaoutracontajácadastrada.Masqualcritériodeigualdadeéutilizadoporpadrãoparafazeressaverificação?
Assim comono casodotoString, todos objetos do Java possuem um outrométodo chamadoequalsqueéutilizadoparacompararobjetosdaqueletipo.Porpadrão,essemétodoapenascomparaasreferênciasdosobjetos.Comotodavezque inserimosumanovacontanosistemaestamosfazendonewemalgumtipodeconta,asreferênciasnuncavãoseriguais,mesmoosdados(númeroeagência)sendoiguais.
Mas,esefosseprecisocompararosatributos?Quaisatributoseledeveriacomparar?OJavaporsisónão faz isso,maspodemossobrescreveroequals da classeObject para criarmos esse critériodecomparação.
OequalsrecebeumObjectcomoargumentoedeveverificarseelemesmoéigualaoObjectrecebidopararetornarumboolean.Sevocênãoreescreveressemétodo,ocomportamentoherdadoéfazerum==comoobjetorecebidocomoargumento.
publicabstractclassConta{
equals
.
protecteddoublesaldo;//outrosatributos...
publicbooleanequals(Objectobject){//primeiroverificaseooutroobjectnãoénuloif(object==null){returnfalse;}
if(this.numero==object.numero&&this.agencia.equals(object.agencia)){returntrue;}returnfalse;}}
NomomentoquerecebemosumareferênciaparaumObject,comovamosacessarosmétodoseatributosdesseobjetoqueimaginamosserumaConta?Se estamos referenciando-ocomoObject,nãopodemosacessá-locomosendoConta.Ocódigoacimanãocompila!
PoderíamosentãoatribuiressareferênciadeObjectparaContaparadepoisacessarosatributosnecessários?Tentemos:
ContaoutraConta=object;
Nós temoscertezadequeesseObject se refereaumaConta, já que anossa lista só imprimecontas.Masocompilador Javanão temgarantias sobre isso!Essa linhaacimanãocompila,poisnemtodoObjectéumaConta.
Pararealizaressaatribuição,paraissodevemos"avisar"ocompiladorJavaquerealmentequeremosfazer isso, sabendo do risco que corremos. Fazemos o castingde referências, parecido com de tiposprimitivos:
ContaoutraConta=(Conta)object;
Ocódigopassaa compilar,mas seráque roda?Essecódigo roda semnenhumproblema,pois emtempodeexecuçãoaJVMverificaráseessareferênciarealmenteéparaumobjetodetipoConta,eestá!Senãoestivesse,umaexceçãodotipoClassCastExceptionserialançada.
Comisso,nossométodoequalsficariaassim:
publicabstractclassConta{protecteddoublesaldo;//outrosatributos...
publicbooleanequals(Objectobject){if(object==null){returnfalse;}
ContaoutraConta=(Conta)object;
Castingdereferências
.
if(this.numero==outraConta.numero&&this.agencia.equals(outraConta.agencia)){returntrue;}returnfalse;}}
VocêpoderiacriarummétodocomoutronomeemvezdereescreverequalsquerecebeObject,mas ele é importante poismuitas bibliotecas o chamam através do polimorfismo, como veremos nocapítulodojava.util.
O método hashCode() anda de mãos dadas com o método equals() e é de fundamentalentendimento no caso de você utilizar suas classes com estruturas de dados que usam tabelas deespalhamento.Tambémfalaremosdelenocapítulodejava.util.
REGRASPARAAREESCRITADOMÉTODOEQUALS
Pelo contrato definido pela classe Object devemos retornar false também no caso doobjetopassadonãoserdetipocompatívelcomasuaclasse.Entãoantesdefazerocastingdevemosverificar isso,eparatalusamosapalavrachaveinstanceof,ou teríamosumaexceptionsendolançada.
Alémdisso,podemosresumirnossoequalsdetalformaanãousarumif:
publicbooleanequals(Objectobject){if(object==null){returnfalse;}if(!(objectinstanceofConta)){returnfalse;}ContaoutraConta=(Conta)object;return(this.numero==outraConta.numero&&this.agencia.equals(outraConta.agencia));}
.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
1. Como verificar se a classeThrowable que é a superclasse deException também reescreve ométodotoString?
AmaioriadasclassesdoJavaquesãomuitoutilizadas terãoseusmétodosequals etoStringreescritosconvenientemente.
2. Utilize-sedadocumentaçãodoJavaedescubradequeclasseéoobjetoreferenciadopeloatributooutdaSystem.
Repareque,comodevidoimport,poderíamosescrever:
//faltaadeclaraçãodasaída________saida=System.out;saida.println("ola");
Avariávelsaida precisa ser declarada de que tipo? É isso que você precisa descobrir. Se vocêdigitaressecódigonoEclipse,elevaitesugerirumquickfixedeclararáavariávelparavocê.
Estudaremosessaclasseemumcapítulofuturo.
3. Rode a aplicação e cadastreduas contas.Na tela dedetalhesde conta, verifiqueoque aparecenacaixadeseleçãodecontaparatransferência.Porqueissoacontece?
4. Reescreva o método toString da sua classe Conta fazendo com que uma mensagemmaisexplicativa seja devolvida. Lembre-se de aproveitar dos recursos do Eclipse para isto: digitandoapenasocomeçodonomedométodoa ser reescritoepressionandoctrl+espaço, elevai sugerirreescrever ométodo, poupando o trabalho de escrever a assinatura dométodo e cometer algumengano.
publicabstractclassConta{
Agoraéamelhorhoraderespirarmaistecnologia!
13.5EXERCÍCIOS:JAVA.LANG.OBJECT
.
protecteddoublesaldo;
@OverridepublicStringtoString(){return"[titular="+titular+",numero="+numero+",agencia="+agencia+"]";}//restantedaclasse
}
Rode a aplicação novamente, cadastre duas contas e verifique novamente a caixa de seleção datransferência.Oqueaconteceu?
5. Reescreva ométodoequals da classeConta para que duas contas com omesmo número eagênciasejamconsideradasiguais.Esboço:
publicabstractclassConta{
publicbooleanequals(Objectobj){if(obj==null){returnfalse;}
ContaoutraConta=(Conta)obj;
returnthis.numero==outraConta.numero&&this.agencia.equals(outraConta.agencia);}}
Você pode usar o ctrl+ espaço do Eclipse para escrever o esqueleto dométodoequals, bastadigitardentrodaclasseequepressionarctrl+espaço.
Rodeaaplicaçãoetenteadicionarduascontascomomesmonúmeroeagência.Oqueacontece?
StringéumaclasseemJava.VariáveisdotipoStringguardamreferênciasaobjetos,enãoumvalor,comoacontececomostiposprimitivos.
Aliás,podemoscriarumaStringutilizandoonew:
Stringx=newString("fj11");Stringy=newString("fj11");
Criamosaqui,doisobjetosdiferentes.Oqueacontecequandocomparamosessasduas referênciasutilizandoo==?
if(x==y){System.out.println("referênciaparaomesmoobjeto");}else{System.out.println("referênciasparaobjetosdiferentes!");}
13.6JAVA.LANG.STRING
.
Temosaquidoisobjetosdiferentes!E,então,comofaríamosparaverificarseoconteúdodoobjetoéomesmo?Utilizamosométodoequals,quefoireescritopelaString,parafazeracomparaçãodecharemchar.
if(x.equals(y)){System.out.println("consideramosiguaisnocritériodeigualdade");}else{System.out.println("consideramosdiferentesnocritériodeigualdade");}
Aqui,acomparaçãoretornaverdadeiro.Porquê?PoisquemimplementouaclasseStringdecidiuqueesteseriaomelhorcritériodecomparação.Vocêpodedescobriroscritériosdeigualdadedecadaclassepeladocumentação.
PodemostambémconcatenarStringsusandoo+.PodemosconcatenarStringscomqualquerobjeto,atémesmonúmeros:
inttotal=5;System.out.println("ototalgastoé:"+total);
O compilador utilizará os métodos apropriados da classe String e possivelmente métodos deoutrasclassespararealizartaltarefa.
SequisermoscompararduasStrings,utilizamosométodocompareTo,que recebeumaStringcomoargumento edevolveum inteiro indicando se aString vemantes, é igual ou vemdepois daStringrecebida.Seforemiguais,édevolvido0;seforanterioràStringdoargumento,devolveuminteironegativo;e,seforposterior,uminteiropositivo.
Fatoimportante:umaStringéimutável.OjavacriaumpooldeStringsparausarcomocachee,seaStringnãofosseimutável,mudandoovalordeumaStringafetariatodasasStrings deoutrasclassesquetivessemomesmovalor.
Reparenocódigoabaixo:
Stringpalavra="fj11";palavra.toUpperCase();System.out.println(palavra);
Pode parecer estranho,mas ele imprime "fj11" emminúsculo. Todométodo que parece alterar ovalordeumaString,naverdade,criaumanovaStringcomasmudançassolicitadasearetorna!Tantoqueessemétodonãoévoid.Ocódigorealmenteútilficariaassim:
Stringpalavra="fj11";Stringoutra=palavra.toUpperCase();System.out.println(outra);
Ouvocêpodeeliminaracriaçãodeoutravariáveltemporária,seacharconveniente:
Stringpalavra="fj11";palavra=palavra.toUpperCase();
.
System.out.println(palavra);
Isso funciona da mesma forma para todos os métodos que parecem alterar o conteúdo de umaString.
Sevocêaindaquisertrocaronúmero1para2,faríamos:
Stringpalavra="fj11";palavra=palavra.toUpperCase();palavra=palavra.replace("1","2");System.out.println(palavra);
Ouaindapodemosconcatenaras invocaçõesdemétodo, jáqueumaString é devolvida a cadainvocação:
Stringpalavra="fj11";palavra=palavra.toUpperCase().replace("1","2");System.out.println(palavra);
O funcionamento do pool interno de Strings do Java tem uma série de detalhes e você podeencontrar mais informações sobre isto na documentação da classe String e no seu métodointern().
OUTROSMÉTODOSDACLASSESTRING
Existem diversos métodos da classe String que são extremamente importantes.Recomendamossempreconsultarojavadocrelativoaessaclasseparaaprendercadavezmaissobreamesma.
Porexemplo,ométodocharAt(i),retornaocaractereexistentenaposiçãoidaString,ométodolengthretornaonúmerodecaracteresnamesmaeométodosubstringquerecebeumintedevolveaSubStringapartirdaposiçãopassadaporaqueleint.
OindexOfrecebeumcharouumaStringedevolveoíndiceemqueaparecepelaprimeiraveznaStringprincipal(hátambémolastIndexOfquedevolveoíndicedaúltimaocorrência).
OtoUpperCaseeotoLowerCasedevolvemumanovaStringtodaemmaiúsculaetodaemminúscula,respectivamente.
ApartirdoJava6,temosaindaométodoisEmpty,quedevolvetrueseaStringforvaziaoufalsecasocontrário.
Algunsmétodosúteisparabuscassãoocontainseomatches.
Hámuitosoutrosmétodos,recomendamosquevocêsempreconsulteojavadocdaclasse.
.
JAVA.LANGSTRINGBUFFERESTRINGBUILDER
ComoaclasseStringéimutável,trabalharcomumamesmaStringdiversasvezespodeterum efeito colateral: gerar inúmeras Strings temporárias. Isto prejudica a performance daaplicaçãoconsideravelmente.
NocasodevocêtrabalharmuitocomamanipulaçãodeumamesmaString (por exemplo,dentrodeumlaço),oidealéutilizaraclasseStringBuffer.AclasseStringBufferrepresentaumasequênciadecaracteres.DiferentementedaString,elaémutável,enãopossuiaquelepool.
AclasseStringBuilder temexatamenteosmesmosmétodos,comadiferençadelanãoserthread-safe.VeremossobreesteconceitonocapítulodeThreads.String.
1. Queremosqueascontasapresentadasnacaixadeseleçãodatransferênciaapareçamcomonomedotitularemmaiúsculas.ParafazerissovamosalterarométodotoStringdaclasseConta.UtilizeométodotoUpperCasedaStringparaisso.
2. ApósalterarmosométodotoString, aconteceu algumamudança comonomedo titular que éapresentadonalistadecontas?Porque?
3. Testeosexemplosdessecapítulo,paraverqueumaStringéimutável.Porexemplo:
publicclassTestaString{
publicstaticvoidmain(String[]args){Strings="fj11";s.replaceAll("1","2");System.out.println(s);}
}
Comofazerparaeleimprimirfj22?
4. Como fazerpara saber seumaString se encontradentrodeoutra?Epara tirar os espaços embrancodaspontasdeumaString?EparasaberseumaStringestávazia?EparasaberquantoscaracterestemumaString?
TomecomohábitosemprepesquisaroJavaDoc!ConheceraAPI,aospoucos,é fundamentalparaquevocênãoprecisereescreveraroda!
5. (opcional) Escreva ummétodo que usa osmétodoscharAt elength de umaString paraimprimiramesmacaractereacaractere,comcadacaractereemumalinhadiferente.
13.7EXERCÍCIOS:JAVA.LANG.STRING
.
6. (opcional) Reescreva o método do exercício anterior, mas modificando ele para que imprima aString de trás para a frente e emuma linha só.Teste-apara "Socorram-me, subi no ônibus emMarrocos"e"anotaramadatadamaratona".
7. (opcional)PesquiseaclasseStringBuilder(ouStringBuffernoJava1.4).Elaémutável.Porqueusá-laemvezdaString?Quandousá-la?
Comovocêpoderia reescrever ométodode escrever aString de trás para a frenteusandoumStringBuilder?
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
1. ConvertaumaStringparaumnúmerosemusarasbibliotecasdojavaquejáfazemisso. Issoé,umaStringx="762"devegeraruminti=762.
Paraajudar,saibaqueumcharpodeser"transformado"emintcomomesmovalornuméricofazendo:
charc='3';inti=c-'0';//ivale3!
Aquiestamosnosaproveitandodoconhecimentodatabelaunicode:osnúmerosde0a9estãoemsequência! Você poderia usar o método estático Character.getNumericValue(char) em vezdisso.
QualéasuanecessidadecomoJava?Precisafazeralgoritmosderedesneurais?Gerargráficos3D?Relatórios emPDF?Gerar código de barra?Gerar boletos?ValidarCPF?Mexer comum arquivo do
EditoraCasadoCódigocomlivrosdeumaformadiferente
13.8DESAFIO
13.9DISCUSSÃOEMAULA:OQUEVOCÊPRECISAFAZEREMJAVA?
.
Excel?
O instrutor vai mostrar que para a maioria absoluta das suas necessidades, alguém já fez umabibliotecaeadisponibilizou.
.
CAPÍTULO14
"Ohomemesqueceráantesamortedopaiqueaperdadapropriedade"--Maquiavel
Aotérminodessecapítulo,vocêserácapazde:
declarareinstanciararrays;popularepercorrerarrays.
Dentrodeumbloco,podemosdeclarardiversasvariáveiseusá-las:
doublesaldoDaConta1=conta1.getSaldo();doublesaldoDaConta2=conta2.getSaldo();doublesaldoDaConta3=conta3.getSaldo();doublesaldoDaConta4=conta4.getSaldo();
Isso pode se tornar um problema quando precisamos mudar a quantidade de variáveis a seremdeclaradasdeacordocomumparâmetro.Esseparâmetropodevariar,comoporexemplo,aquantidadedenúmerocontidosnumbilhetedeloteria.Umjogosimplespossui6números,maspodemoscomprarumbilhetemaiscaro,com7númerosoumais.
Parafacilitaressetipodecasopodemosdeclararumvetor(array)dedoubles:
double[]saldosDasContas;
Odouble[]éumtipo.Umaarrayésempreumobjeto,portanto,avariávelsaldosDasContaséumareferência.Vamosprecisarcriarumobjetoparapoderusaraarray.Comocriamosoobjeto-array?
saldosDasContas=newdouble[10];
Oque fizemos foi criaruma arraydedoublede 10posições e atribuir o endereçonoqual ela foicriada.Podemosaindaacessarasposiçõesdoarray:
saldosDasContas[5]=conta5.getSaldo();
Ocódigoacimaalteraasextaposiçãodoarray.NoJava,osíndicesdoarrayvãode0an-1,ondenéotamanhodadonomomentoemquevocêcriouoarray.Sevocêtentaracessarumaposiçãoforadessealcance,umerroocorreráduranteaexecução.
UMPOUCODEARRAYS
14.1OPROBLEMA
.
ARRAYS-UMPROBLEMANOAPRENDIZADODEMUITASLINGUAGENS
Aprender a usar arrays pode ser um problema em qualquer linguagem. Isso porque envolveumasériedeconceitos,sintaxeeoutros.NoJava,muitasvezesutilizamosoutrosrecursosemvezdearrays, em especial os pacotes de coleções do Java, que veremos no capítulo 15. Portanto, fiquetranquilocasonãoconsigadigerirtodasintaxedasarraysnumprimeiromomento.
No caso do bilhete de loteria, podemos utilizar o mesmo recurso. Mais ainda, a quantidade denúmeros do nosso bilhete pode ser definido por uma variável. Considere que n indica quantosnúmerosnossobilheteterá,podemosentãofazer:
int[]numerosDoBilhete=newint[n];
Eassimpodemosacessaremodificarosinteiroscomíndicede0an-1.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
É comum ouvirmos "array de objetos". Porém quando criamos uma array de alguma classe, elapossui referências. O objeto, como sempre, está na memória principal e, na sua array, só ficamguardadasasreferências(endereços).
ContaCorrente[]minhasContas;minhasContas=newContaCorrente[10];
JáconheceoscursosonlineAlura?
14.2ARRAYSDEREFERÊNCIAS
.
Quantascontasforamcriadasaqui?Naverdade,nenhuma.Foramcriados10espaçosquevocêpodeutilizarparaguardarumareferênciaaumaContaCorrente.Porenquanto,elessereferenciamparalugarnenhum(null).Sevocêtentar:
System.out.println(minhasContas[0].getSaldo());
Umerrodurante a execuçãoocorrerá! Pois, na primeira posiçãoda array, nãoháuma referênciaparaumaconta,nemparalugarnenhum.Vocêdevepopularsuaarrayantes.
ContaCorrentecontaNova=newContaCorrente();contaNova.deposita(1000.0);minhasContas[0]=contaNova;
Ouvocêpodefazerissodiretamente:
minhasContas[1]=newContaCorrente();minhasContas[1].deposita(3200.0);
Umaarraydetiposprimitivosguardavalores,umarraydeobjetosguardareferências.
Mas e se agoraquisermos guardar tantoContaCorrente quantoContaPoupança?Um array deContaCorrente só consegue guardar objetos domesmo tipo. Se quisermos guardar os dois tipos deconta,devemoscriarumarraydeConta!
Conta[]minhasContas=newConta[10];minhasContas[0]=newContaCorrente();minhasContas[1]=newContaPoupanca();
Percebaquenão estamos criandoumobjetodo tipoConta, que é abstrata, estamos criando 10espaçosqueguardamreferênciasparaqualquertipodeconta.
14.3PERCORRENDOUMAARRAY
.
Percorrerumarrayémuitosimplesquandofomosnósqueacriamos:
publicstaticvoidmain(String[]args){int[]idades=newint[10];for(inti=0;i<10;i++){idades[i]=i*10;}for(inti=0;i<10;i++){System.out.println(idades[i]);}}
Porém,emmuitoscasos,recebemosumaarraycomoargumentoemummétodo:
publicvoidimprimeArray(int[]array){//nãocompila!!for(inti=0;i<????;i++){System.out.println(array[i]);}}
Atéondeofordeveir?TodaarrayemJavatemumatributoquesechamalength,evocêpodeacessá-loparasaberotamanhodoarrayaoqualvocêestásereferenciandonaquelemomento:
publicvoidimprimeArray(int[]array){for(inti=0;i<array.length;i++){System.out.println(array[i]);}}
ARRAYSNÃOPODEMMUDARDETAMANHO
Apartirdomomentoqueumaarrayfoicriada,elanãopodemudardetamanho.
Sevocêprecisardemaisespaço,seránecessáriocriarumanovaarraye,antesdesereferirela,copieoselementosdaarrayvelha.
OJava5.0trazumanovasintaxeparapercorremosarrays(ecoleções,queveremosmaisafrente).
Nocasodevocênãoternecessidadedemanterumavariávelcomoíndicequeindicaaposiçãodoelementonovetor(queéumagrandepartedoscasos),podemosusaroenhanced-for.
publicclassAlgumaClasse{publicstaticvoidmain(String[]args){int[]idades=newint[10];for(inti=0;i<10;i++){idades[i]=i*10;}
//imprimindotodaaarray
14.4PERCORRENDOUMAARRAYNOJAVA5.0
.
for(intx:idades){System.out.println(x);}}}
Nãoprecisamosmaisdolengthparapercorrermatrizescujotamanhonãoconhecemos:
publicclassAlgumaClasse{publicvoidimprimeArray(int[]array){for(intx:array){System.out.println(x);}}}
Omesmoéválidoparaarraysdereferências.Essefornadamaiséqueumtruquedecompilaçãoparafacilitaressatarefadepercorrerarraysetorná-lamaislegível.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
Paraconsolidarmososconceitossobrearrays,vamosfazeralgunsexercíciosquenãointerferememnossoprojeto.
1. CrieumaclasseTestaArrays enométodomain crie umarrayde contasde tamanho10.Emseguida,façaumlaçoparacriar10contascomsaldosdistintosecolocá-lasnoarray.Porexemplo,vocêpodeutilizaroíndicedolaçoemultiplicá-lopor100paragerarosaldodecadaconta:
Conta[]contas=newConta[10];
for(inti=0;i<contas.length;i++){Contaconta=newContaCorrente();
SaberinglêsémuitoimportanteemTI
14.5EXERCÍCIOS:ARRAYS
.
conta.deposita(i*100.0);//escrevaocódigoparaguardaracontanaposiçãoidoarray}
2. AindanaclasseTestaArrays,façaumoutrolaçoparacalculareimprimiramédiadossaldosdetodasascontasdoarray.
3. (opcional) Crie uma classe TestaSplit que reescreva uma frase com as palavras na ordeminvertida."Socorram-me, subinoônibus emMarrocos"deveretornar "Marrocos emônibusno subiSocorram-me,".Utilize ométodosplit da String para te auxiliar. Essemétodo divide umaStringdeacordocomoseparadorespecificadoedevolveaspartesemumarraydeString,porexemplo:
Stringfrase="Umamensagemqualquer";String[]palavras=frase.split("");
//Agorasóbastapercorreroarraynaordeminversaimprimindoaspalavras
4. (opcional)CrieumaclasseBancodentrodopacotebr.com.caelum.contas.modeloOBancodeve terumnomeeumnúmero (obrigatoriamente) euma referência aumaarraydeConta detamanho10,alémdeoutrosatributosquevocêjulgarnecessário.
publicclassBanco{privateStringnome;privateintnumero;privateConta[]contas;
//outrosatributosquevocêacharnecessário
publicBanco(Stringnome,intnumero){this.nome=nome;this.numero=numero;this.contas=newContaCorrente[10];}
//gettersparanomeenúmero,nãocolocarossetterspoisjárecebemosno//construtor}
5. (opcional)AclasseBancodeveterummétodoadiciona,querecebeumareferênciaaContacomoargumentoeguardaessaconta.
VocêdeveinseriraContaemumaposiçãodaarrayqueestejalivre.Existemváriasmaneirasparavocêfazerisso:guardarumcontadorparaindicarqualapróximaposiçãovaziaouprocurarporumaposiçãovaziatodavez.Oqueseriamaisinteressante?
Sequiserverificarqualaprimeiraposiçãovazia(nula)eadicionarnela,poderiaserfeitoalgocomo:
publicvoidadiciona(Contac){for(inti=0;i<this.contas.length;i++){//verificarseaposiçãoestávazia//adicionarnoarray}}
.
Éimportanterepararqueométodoadicionanãorecebetitular,agencia,saldo,etc.Essaseriaumamaneiranemumpoucoestruturada,muitomenosorientadaaobjetosde se trabalhar.VocêantescriaumaContaejápassaareferênciadela,quedentrodoobjetopossuititular,saldo,etc.
6. (opcional)CrieumaclasseTestaBancoquepossuiráummétodomain.DentrodelecriealgumasinstânciasdeContaepasseparaobancopelométodoadiciona.
Bancobanco=newBanco("CaelumBank",999);//....
Criealgumascontasepassecomoargumentoparaoadicionadobanco:
ContaCorrentec1=newContaCorrente();c1.setTitular("Batman");c1.setNumero(1);c1.setAgencia(1000);c1.deposita(100000);banco.adiciona(c1);
ContaPoupancac2=newContaPoupanca();c2.setTitular("Coringa");c2.setNumero(2);c2.setAgencia(1000);c2.deposita(890000);banco.adiciona(c2);
Você pode criar essas contas dentro de um loop e dar a cada um deles valores diferentes dedepósitos:
for(inti=0;i<5;i++){ContaCorrenteconta=newContaCorrente();conta.setTitular("Titular"+i);conta.setNumero(i);conta.setAgencia(1000);conta.deposita(i*1000);banco.adiciona(conta);}
Repare que temos de instanciar ContaCorrente dentro do laço. Se a instanciação deContaCorrente ficasse acimado laço, estaríamos adicionado cinco vezes amesma instância deContaCorrentenesteBancoeapenasmudandoseudepósitoacadaiteração,quenessecasonãoéoefeitodesejado.
Opcional:ométodoadicionapodegerarumamensagemdeerroindicandoquandooarrayjáestácheio.
7. (opcional)PercorraoatributocontasdasuainstânciadeBancoeimprimaosdadosdetodasassuascontas.Parafazerisso,vocêpodecriarummétodochamadomostraContasdentrodaclasseBanco:
publicvoidmostraContas(){for(inti=0;i<this.contas.length;i++){System.out.println("Contanaposição"+i);//preencherparamostraroutrasinformacoesdaconta
.
}}
Cuidadoaopreencheressemétodo:alguns índicesdoseuarraypodemnãoconterreferênciaparaumaContaconstruída,istoé,aindasereferiremparanull.Sepreferir,useofornovodojava5.0.
Aí,atravésdoseumain,depoisdeadicionaralgumascontas,bastafazer:
banco.mostraContas();
8. (opcional) Em vez de mostrar apenas o salário de cada funcionário, você pode usar o métodotoString()decadaContadoseuarray.
9. (opcional)Crieummétodoparaverificar seumadeterminadaConta se encontraounão comocontadestebanco:
publicbooleancontem(Contaconta){//...}
Vocêvaiprecisar fazerumfor em seu array e verificar se a contapassada comoargumento seencontradentrodoarray.Eviteaomáximousarnúmeroshard-coded,istoé,useo.length.
10. (opcional)Casoo array já esteja cheionomomentode adicionarumaoutra conta, crieumarraynovocomumacapacidademaiorecopieosvaloresdoarrayatual.Istoé,vamosfazerarealocaçãodoselementosdoarrayjáquejavanãotemisso:umarraynasceemorrecomomesmolength.
USANDOOTHISPARAPASSARARGUMENTO
Dentrodeummétodo,vocêpodeusarapalavrathisparareferenciarasimesmoepodepassaressareferênciacomoargumento.
Arrayspodemtermaisdeumadimensão. Istoé,emvezde termosumaarrayde10contas,podemosterumaarrayde10por10contasevocêpodeacessaracontanaposiçãodacolunaxelinhay.Naverdade,umaarraybidimensionalemJavaéumaarraydearrays.Pesquisesobreisso.
14.6UMPOUCOMAIS...
.
Umaarraybidimensionalnãoprecisa ser retangular, istoé, cada linhapode terumnúmerodiferentedecolunas.Como?Porque?
Oqueacontecesecriarmosumaarrayde0elementos?e-1?
Ométodomain recebeumaarraydeStrings comoargumento.Essa array é passadapelousuárioquandoeleinvocaoprograma:
$javaTesteargumento1outromaisoutro
Enossaclasse:
publicclassTeste{publicstaticvoidmain(String[]args){for(Stringargumento:args){
.
System.out.println(argumento);}}}
Issoimprimirá:
argumento1outromaisoutro
1. Nosprimeiroscapítulos,vocêdeveterreparadoqueaversãorecursivaparaoproblemadeFibonacciélentaporquetodahoraestamosrecalculandovalores.Façacomqueaversãorecursivasejatãoboaquantoaversãoiterativa.(Dica:usearraysparaisso)
2. Oobjetivodesteexercícioéfixarosconceitosvistos.Sevocêestácomdificuldadeemalgumapartedessecapítulo,aproveiteetreinetudooquevimosatéagoranopequenoprogramaabaixo:
Programa:
Classe: Casa Atributos: cor, totalDePortas, portas[] Métodos: void pinta(String s), intquantasPortasEstaoAbertas(),voidadicionaPorta(Portap),inttotalDePortas()
Crieumacasa,pinte-a.Crietrêsportasecoloque-asnacasaatravésdométodoadicionaPorta,abraefeche-ascomodesejar.UtilizeométodoquantasPortasEstaoAbertaspara imprimironúmerodeportasabertaseométodototalDePortaspara imprimiro totaldeportasemsuacasa.
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
14.7DESAFIOSOPCIONAIS
AprendasedivertindonaAluraStart!
.
CAPÍTULO15
"Aamizadeéumcontratosegundooqualnoscomprometemosaprestarpequenosfavoresparaqueno-losretribuamcomgrandes."--BarondelaBredeetdeMontesquieu
Aotérminodessecapítulo,vocêserácapazde:
utilizararrays,lists,setsoumapsdependendodanecessidadedoprograma;iterareordenarlistasecoleções;usarmapasparainserçãoebuscadeobjetos.
Comovimosnocapítulodearrays,manipulá-lasébastantetrabalhoso.Essadificuldadeapareceemdiversosmomentos:
nãopodemosredimensionarumarrayemJava;éimpossívelbuscardiretamenteporumdeterminadoelementocujoíndicenãosesabe;não conseguimos saber quantas posições do array já foram populadas sem criar, para isso,métodosauxiliares.
Na figura acima, você pode ver um array que antes estava sendo completamente utilizado e que,depois,teveumdeseuselementosremovidos.
Supondoqueosdadosarmazenadosrepresentemcontas,oqueacontecequandoprecisarmosinseriruma nova conta no banco? Precisaremos procurar por um espaço vazio? Guardaremos em algumaestruturadedadosexterna,asposiçõesvazias?Esenãohouverespaçovazio?Teríamosdecriarumarraymaiorecopiarosdadosdoantigoparaele?
Hámais questões: comoposso saber quantas posições estão sendousadasno array?Vouprecisarsemprepercorreroarrayinteiroparaconseguiressainformação?
COLLECTIONSFRAMEWORK
15.1ARRAYSSÃOTRABALHOSOS,UTILIZARESTRUTURADEDADOS
.
Alémdessasdificuldadesqueosarraysapresentavam, faltavaumconjuntorobustodeclassesparasupriranecessidadedeestruturasdedadosbásicas,comolistasligadasetabelasdeespalhamento.
Comesseseoutrosobjetivosemmente,ocomitêresponsávelpeloJavacriouumconjuntodeclasseseinterfacesconhecidocomoCollectionsFramework,queresidenopacotejava.utildesdeoJava21.2.
COLLECTIONS
AAPIdeCollectionsérobustaepossuidiversasclassesquerepresentamestruturasdedadosavançadas.
Porexemplo,nãoénecessárioreinventararodaecriarumalistaligada,massimutilizaraquelaqueoJavadisponibiliza.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
Um primeiro recurso que a API de Collections traz são listas. Uma lista é uma coleção quepermiteelementosduplicadosemantémumaordenaçãoespecíficaentreoselementos.
Em outras palavras, você tem a garantia de que, quando percorrer a lista, os elementos serãoencontrados em uma ordem pré-determinada, definida na hora da inserção dosmesmos. Ela resolvetodososproblemasque levantamosemrelaçãoaoarray (busca, remoção, tamanho "infinito",...).Esse
SaberinglêsémuitoimportanteemTI
15.2LISTAS:JAVA.UTIL.LIST
.
códigojáestápronto!
AAPIdeCollectionstrazainterfacejava.util.List,queespecificaoqueumaclassedevesercapazde fazerparaseruma lista.Hádiversas implementaçõesdisponíveis,cadaumacomumaformadiferentederepresentarumalista.
A implementaçãomaisutilizadada interfaceList éaArrayList, que trabalha comumarrayinterno para gerar uma lista. Portanto, ela é mais rápida na pesquisa do que sua concorrente, aLinkedList,queémaisrápidanainserçãoeremoçãodeitensnaspontas.
ARRAYLISTNÃOÉUMARRAY!
É comumconfundiremumaArrayList comum array, porém ela não é um array.O queocorreéque,internamente,elausaumarraycomoestruturaparaarmazenarosdados,porémesteatributoestápropriamenteencapsuladoevocênãotemcomoacessá-lo.Repare,também,quevocênãopodeusar[]comumaArrayList,nemacessaratributolength.Nãohárelação!
ParacriarumArrayList,bastachamaroconstrutor:
ArrayListlista=newArrayList();
ÉsemprepossívelabstrairalistaapartirdainterfaceList:
Listlista=newArrayList();
Paracriarumalistadenomes(String),podemosfazer:
Listlista=newArrayList();lista.add("Manoel");lista.add("Joaquim");lista.add("Maria");
AinterfaceListpossuidoismétodosadd,umquerecebeoobjetoaserinseridoeocolocanofinaldalista,eumsegundoquepermiteadicionaroelementoemqualquerposiçãodamesma.Noteque,em momento algum, dizemos qual é o tamanho da lista; podemos acrescentar quantos elementosquisermos,quealistacresceconformefornecessário.
Todalista(naverdade,todaCollection)trabalhadomodomaisgenéricopossível.Istoé,nãoháuma ArrayList específica para Strings, outra para Números, outra para Datas etc. Todos osmétodostrabalhamcomObject.
Assim,épossívelcriar,porexemplo,umalistadeContasCorrentes:
ContaCorrentec1=newContaCorrente();c1.deposita(100);
ContaCorrentec2=newContaCorrente();
.
c2.deposita(200);
ContaCorrentec3=newContaCorrente();c3.deposita(300);
Listcontas=newArrayList();contas.add(c1);contas.add(c3);contas.add(c2);
Parasaberquantoselementoshánalista,usamosométodosize():
System.out.println(contas.size());
Háaindaummétodoget(int) que recebe comoargumentoo índicedo elementoque se querrecuperar.Atravésdele,podemosfazerumforparaiterarnalistadecontas:
for(inti=0;i<contas.size();i++){contas.get(i);//códigonãomuitoútil....}
Mascomofazerparaimprimirosaldodessascontas?PodemosacessarogetSaldo()diretamenteapósfazercontas.get(i)?Nãopodemos; lembre-se que toda lista trabalha sempre comObject.Assim, a referência devolvida pelo get(i) é do tipo Object , sendo necessário o cast paraContaCorrentesequisermosacessarogetSaldo():
for(inti=0;i<contas.size();i++){ContaCorrentecc=(ContaCorrente)contas.get(i);System.out.println(cc.getSaldo());}//notequeaordemdoselementosnãoéalterada
Háaindaoutrosmétodos,comoremove()querecebeumobjetoquesedesejaremoverdalista;econtains(), que recebe umobjeto como argumento e devolvetrue oufalse, indicando se oelementoestáounãonalista.
AinterfaceListealgumasclassesqueaimplementampodemservistasnodiagramaaseguir:
.
ACESSOALEATÓRIOEPERCORRENDOLISTASCOMGET
Algumaslistas,comoaArrayList,têmacessoaleatórioaosseuselementos:abuscaporumelemento em uma determinada posição é feita demaneira imediata, sem que a lista inteira sejapercorrida(quechamamosdeacessosequencial).
Nestecaso,oacessoatravésdométodoget(int)émuitorápido.Casocontrário,percorrerumalistausandoumforcomoessequeacabamosdever,podeserdesastroso.Aopercorrermosumalista,devemosusarsempreumIteratorouenhancedfor,comoveremos.
Umalistaéumaexcelentealternativaaumarraycomum,jáquetemostodososbenefíciosdearrays,semanecessidadedetomarcuidadocomremoções,faltadeespaçoetc.
A outra implementação muito usada, a LinkedList, fornece métodos adicionais para obter eremoveroprimeiroeúltimoelementodalista.Elatambémtemofuncionamentointernodiferente,oquepodeimpactarperformance,comoveremosduranteosexercíciosnofinaldocapítulo.
.
VECTOR
Outra implementação é a tradicional classe Vector , presente desde o Java 1.0, que foiadaptadaparausocomoframeworkdeCollections,comainclusãodenovosmétodos.
Ela deve ser escolhida com cuidado, pois lida de uma maneira diferente com processoscorrendo em paralelo e terá um custo adicional em relação a ArrayList quando não houveracessosimultâneoaosdados.
Emqualquerlista,épossívelcolocarqualquerObject.Comisso,épossívelmisturarobjetos:
ContaCorrentecc=newContaCorrente();
Listlista=newArrayList();lista.add("Umastring");lista.add(cc);...
Mas e depois, na hora de recuperar esses objetos?Como ométodoget devolve umObject,precisamosfazerocast.Mascomumalistacomváriosobjetosdetiposdiferentes,issopodenãosertãosimples...
Geralmente, não nos interessa uma lista com vários tipos de objetos misturados; no dia-a-dia,usamoslistascomoaqueladecontascorrentes.NoJava5.0,podemosusarorecursodeGenericspararestringiraslistasaumdeterminadotipodeobjetos(enãoqualquerObject):
List<ContaCorrente>contas=newArrayList<ContaCorrente>();contas.add(c1);contas.add(c3);contas.add(c2);
ReparenousodeumparâmetroaoladodeListeArrayList:eleindicaquenossalistafoicriadaparatrabalharexclusivamentecomobjetosdotipoContaCorrente. Issonostrazumasegurançaemtempodecompilação:
contas.add("umastring");//issonãocompilamais!!
OusodeGenericstambémeliminaanecessidadedecasting,jáque,seguramente,todososobjetosinseridosnalistaserãodotipoContaCorrente:
for(inti=0;i<contas.size();i++){ContaCorrentecc=contas.get(i);//semcasting!System.out.println(cc.getSaldo());}
A partir do Java 7, se você instancia um tipo genérico namesma linha de sua declaração, não é
15.3LISTASNOJAVA5EJAVA7COMGENERICS
.
necessáriopassar os tiposnovamente, bastausarnewArrayList<>(). É conhecido comooperadordiamante:
List<ContaCorrente>contas=newArrayList<>();
ValeressaltaraimportânciadousodainterfaceList:quandodesenvolvemos,procuramossemprenosreferiraela,enãoàsimplementaçõesespecíficas.Porexemplo,setemosummétodoquevaibuscarumasériedecontasnobancodedados,poderíamosfazerassim:
classAgencia{publicArrayList<Conta>buscaTodasContas(){ArrayList<Conta>contas=newArrayList<>();
//paracadacontadobancodedados,contas.add
returncontas;}}
Porém,paraqueprecisamosretornarareferênciaespecíficaaumaArrayList?Paraque ser tãoespecífico?Dessamaneira,odiaqueoptarmospordevolverumaLinkedListemvezdeArrayList,as pessoas que estão usando o método buscaTodasContas poderão ter problemas, pois estavamfazendo referência a uma ArrayList. O ideal é sempre trabalhar com a interface mais genéricapossível:
classAgencia{
//modificaçãoapenasnoretorno:publicList<Conta>buscaTodasContas(){ArrayList<Conta>contas=newArrayList<>();
//paracadacontadobancodedados,contas.add
returncontas;}}
ÉomesmocasodepreferirreferenciaraosobjetoscomInputStream como fizemosnocapítulopassado.
Assim como no retorno, é boa prática trabalhar com a interface em todos os lugares possíveis:métodos que precisam receber uma lista de objetos têm List como parâmetro em vez de umaimplementaçãoemespecíficocomoArrayList,deixandoométodomaisflexível:
classAgencia{
publicvoidatualizaContas(List<Conta>contas){//...}}
15.4AIMPORTÂNCIADASINTERFACESNASCOLEÇÕES
.
Também declaramos atributos como List em vez de nos comprometer como uma ou outraimplementação.Dessaformaobtemosumbaixoacoplamento:podemostrocaraimplementação,jáqueestamosprogramandoparaainterface!Porexemplo:
classEmpresa{
privateList<Funcionario>empregados=newArrayList<>();
//...}
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
Vimos anteriormente que as listas são percorridas demaneira pré-determinada de acordo com ainclusãodositens.Mas,muitasvezes,queremospercorreranossalistademaneiraordenada.
AclasseCollectionstrazummétodoestáticosortquerecebeumListcomoargumentoeoordenaporordemcrescente.Porexemplo:
List<String>lista=newArrayList<>();lista.add("Sérgio");lista.add("Paulo");lista.add("Guilherme");
//reparequeotoStringdeArrayListfoisobrescrito:System.out.println(lista);
Collections.sort(lista);
System.out.println(lista);
Aotestaroexemploacima,vocêobservaráque,primeiro,alistaéimpressanaordemdeinserçãoe,depoisdeinvocarosort,elaéimpressaemordemalfabética.
AprendasedivertindonaAluraStart!
15.5ORDENAÇÃO:COLLECTIONS.SORT
.
Mas toda lista em Javapode serdequalquer tipodeobjeto, por exemplo,ContaCorrente. E sequisermosordenaruma listadeContaCorrente?Emqueordema classeCollections ordenará?Pelosaldo?Pelonomedocorrentista?
ContaCorrentec1=newContaCorrente();c1.deposita(500);
ContaCorrentec2=newContaCorrente();c2.deposita(200);
ContaCorrentec3=newContaCorrente();c3.deposita(150);
List<ContaCorrente>contas=newArrayList<>();contas.add(c1);contas.add(c3);contas.add(c2);
Collections.sort(contas);//qualseriaocritérioparaestaordenação?
Semprequefalamosemordenação,precisamospensaremumcritériodeordenação,umaformadedeterminar qual elemento vem antes de qual. É necessário instruir o sort sobre como compararnossasContaCorrenteafimdedeterminarumaordemnalista.Paraisto,ométodosortnecessitaque todos seusobjetosda lista sejamcomparáveis epossuamummétodoque se comparacomoutraContaCorrente.Comoéqueométodosortteráagarantiadequeasuaclassepossuiessemétodo?Issoseráfeito,novamente,atravésdeumcontrato,deumainterface!
Vamos fazer com que os elementos da nossa coleção implementem a interfacejava.lang.Comparable,quedefineométodointcompareTo(Object).Estemétododeveretornarzero,seoobjetocomparadoforigualaesteobjeto,umnúmeronegativo,seesteobjetoformenorqueoobjetodado,eumnúmeropositivo,seesteobjetoformaiorqueoobjetodado.
ParaordenarasContaCorrentesporsaldo,bastaimplementaroComparable:
publicclassContaCorrenteextendsContaimplementsComparable<ContaCorrente>{
//...todoocódigoanteriorficaaqui
publicintcompareTo(ContaCorrenteoutra){if(this.saldo<outra.saldo){return-1;}
if(this.saldo>outra.saldo){return1;}
return0;}}
Com o código anterior, nossa classe tornou-se "comparável": dados dois objetos da classe,conseguimos dizer se um objeto émaior,menor ou igual ao outro, segundo algum critério por nós
.
definido.Nonossocaso,acomparaçãoseráfeitabaseando-senosaldodaconta.
Reparequeocritériodeordenaçãoé totalmenteaberto,definidopeloprogramador.Sequisermosordenarporoutroatributo(ouatéporumacombinaçãodeatributos),bastamodificaraimplementaçãodométodocompareTonaclasse.
QuandochamarmosométodosortdeCollections,elesaberácomofazeraordenaçãodalista;eleusaráocritérioquedefinimosnométodocompareTo.
OUTRAIMPLEMENTAÇÃO...
Oqueachadaimplementaçãoabaixo?
publicintcompareTo(Contaoutra){returnInteger.compare(this.getNumero(),outra.getNumero());}
Mas,eoexemploanterior,comumalistadeStrings?Porqueaordenaçãofuncionou,naquelecaso,semprecisarmos fazernada? Simples: quemescreveu a classeString (lembre que ela é uma classecomoqualqueroutra)implementouainterfaceComparableeométodocompareToparaStrings,fazendocomparaçãoemordemalfabética.(ConsulteadocumentaçãodaclasseStringevejaométodocompareTo lá).OmesmoacontececomoutrasclassescomoInteger,BigDecimal,Date, entreoutras.
.
OUTROSMÉTODOSDACLASSECOLLECTIONS
AclasseCollectionstrazumagrandequantidadedemétodosestáticosúteisnamanipulaçãodecoleções.
binarySearch(List,Object):Realizaumabuscabináriapordeterminadoelementonalistaordenadaeretornasuaposiçãoouumnúmeronegativo,casonãoencontrado.
max(Collection):Retornaomaiorelementodacoleção.
min(Collection):Retornaomenorelementodacoleção.
reverse(List):Invertealista.
...emuitosoutros.Consulteadocumentaçãoparaveroutrosmétodos.
No Java 8 muitas dessas funcionalidades da Collections podem ser feitas através doschamadosStreams,queficaumpoucoforadoescopodeumcursoinicialdeJava.
Existeumaclasseanáloga,ajava.util.Arrays,quefazoperaçõessimilarescomarrays.
Éimportanteconhecê-lasparaevitarescrevercódigojáexistente.
Vamosordenarocampodedestinoda teladedetalhesdacontaparaqueascontasapareçamemordemalfabéticadetitular.
1. FaçasuaclasseContaimplementarainterfaceComparable<Conta>.Utilizeocritériodeordenarpelotitulardaconta.
publicclassContaimplementsComparable<Conta>{...}
DeixeoseumétodocompareToparecidocomeste:
publicclassContaimplementsComparable<Conta>{
//...todoocódigoanteriorficaaqui
publicintcompareTo(ContaoutraConta){returnthis.titular.compareTo(outraConta.titular);}}
2. Queremosqueascontasapareçamnocampodedestinoordenadaspelotitular.Vamosentãocriaro
15.6EXERCÍCIOS:ORDENAÇÃO
.
método ordenaLista na classe ManipuladorDeContas. Use o Collections.sort() paraordenaralistarecuperadadoEvento:
publicclassManipuladorDeContas{
//outrosmétodos
publicvoidordenaLista(Eventoevento){List<Conta>contas=evento.getLista("destino");Collections.sort(contas);}}
Rodeaaplicação,adicionealgumascontaseverifiqueseascontasaparecemordenadaspelonomedotitularnateladedetalhesdeconta.
Atençãoespecial:reparequeescrevemosummétodocompareToemnossaclasseenossocódigonunca o invoca!! Isto émuito comum.Reescrevemos (ou implementamos)ummétodo e quemoinvocará seráumoutro conjuntode classes (nesse caso, quemestá chamandoocompareTo é oCollections.sort, queousa comobaseparao algoritmodeordenação). Isso criaum sistemaextremamente coeso e, aomesmo tempo, combaixo acoplamento: a classeCollections nuncaimaginouqueordenariaobjetosdotipoConta,mas jáqueelessãoComparable, o seumétodosortestásatisfeito.
3. OqueteriaacontecidoseaclasseContanãoimplementasseComparable<Conta>mas tivesseométodocompareTo?
Façaumteste:removatemporariamenteasentençaimplementsComparable<Conta>,nãoremovaométodocompareToevejaoqueacontece.Bastaterométodo,semassinarainterface?
4. Comoposso inverter a ordemdeuma lista?Comoposso embaralhar todosos elementosdeumalista?Comopossorotacionaroselementosdeumalista?
InvestigueadocumentaçãodaclasseCollectionsdentrodopacotejava.util.
5. (opcional)CrieumanovaclasseTestaListaquecriaumaArrayListeinserenovascontascomsaldosaleatóriosusandoumlaço(for).Adivinheonomedaclasseparacolocarsaldosaleatórios?Random. Do pacote java.util . Consulte sua documentação para usá-la (utilize o métodonextInt()passandoonúmeromáximoasersorteado).
6. ModifiqueaclasseTestaListaparautilizarumaLinkedListemvezdeArrayList:
List<Conta>contas=newLinkedList<Conta>();
Precisamos alterar mais algum código para que essa substituição funcione? Rode o programa.Algumadiferença?
7. (opcional)Imprimaareferênciaparaessalista.OtoStringdeumaArrayList/LinkedListé
.
reescrito?
System.out.println(contas);
Umconjunto(Set)funcionadeformaanálogaaosconjuntosdamatemática,eleéumacoleçãoquenãopermiteelementosduplicados.
Outracaracterísticafundamentaldeleéofatodequeaordememqueoselementossãoarmazenadospodenãoseraordemnaqualelesforaminseridosnoconjunto.Ainterfacenãodefinecomodeveserestecomportamento.Talordemvariadeimplementaçãoparaimplementação.
Um conjunto é representado pela interfaceSet e tem como suas principais implementações asclassesHashSet,LinkedHashSeteTreeSet.
15.7CONJUNTO:JAVA.UTIL.SET
.
Ocódigoaseguircriaumconjuntoeadicionadiversoselementos,ealgunsrepetidos:
Set<String>cargos=newHashSet<>();
cargos.add("Gerente");cargos.add("Diretor");cargos.add("Presidente");cargos.add("Secretária");cargos.add("Funcionário");cargos.add("Diretor");//repetido!
//imprimenatelatodososelementosSystem.out.println(cargos);
Aqui,osegundoDiretornãoseráadicionadoeométodoaddlheretornaráfalse.
O uso de um Set pode parecer desvantajoso, já que ele não armazena a ordem, e não aceitaelementos repetidos. Não hámétodos que trabalham com índices, como o get(int) que as listaspossuem.AgrandevantagemdoSetéqueexistemimplementações,comoaHashSet, quepossuiumaperformanceincomparávelcomasListsquandousadoparapesquisa(métodocontains porexemplo).Veremosessaenormediferençaduranteosexercícios.
ORDEMDEUMSET
Seriapossívelusarumaoutraimplementaçãodeconjuntos,comoumTreeSet,queinsereoselementosdetalformaque,quandoforempercorridos,elesapareçamemumaordemdefinidapelométodo de comparação entre seus elementos. Esse método é definido pela interfacejava.lang.Comparable.Ou,ainda,podesepassarumComparatorparaseuconstrutor.
JáoLinkedHashSetmantémaordemdeinserçãodoselementos.
AntesdoJava5,nãopodíamosutilizargenerics,eusávamosoSetdeformaqueeletrabalhavacomObject,havendonecessidadedecastings.
.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
AscoleçõestêmcomobaseainterfaceCollection,quedefinemétodosparaadicionareremoverumelemento,everificarseeleestánacoleção,entreoutrasoperações,comomostraatabelaaseguir:
UmacoleçãopodeimplementardiretamenteainterfaceCollection,porémnormalmenteseusaumadasduassubinterfacesmaisfamosas:justamenteSeteList.
A interfaceSet, como previamente vista, define um conjunto de elementos únicos enquanto ainterfaceListpermiteelementosduplicados,alémdemanteraordemaqualelesforamadicionados.
A busca emumSet pode sermais rápida do que emumobjeto do tipoList, pois diversasimplementações utilizam-se de tabelas de espalhamento (hash tables), realizando a busca para tempolinear(O(1)).
A interfaceMap faz parte do framework,mas não estendeCollection. (veremos Map maisadiante).
Seuslivrosdetecnologiaparecemdoséculopassado?
15.8PRINCIPAISINTERFACES:JAVA.UTIL.COLLECTION
.
NoJava5,temosoutrainterfacefilhadeCollection:aQueue,quedefinemétodosdeentradaede saídae cujocritério serádefinidopela sua implementação (porexemploLIFO,FIFOouaindaumheapondecadaelementopossuisuachavedeprioridade).
Comopercorreroselementosdeumacoleção?Se foruma lista,podemossempreutilizarumlaçofor,invocandoométodogetparacadaelemento.Maseseacoleçãonãopermitirindexação?
Por exemplo, um Set não possui um método para pegar o primeiro, o segundo ou o quintoelementodoconjunto,jáqueumconjuntonãopossuioconceitode"ordem"
Podemosusaroenhanced-for(o"foreach")doJava5parapercorrerqualquerCollectionsemnospreocupar com isso. Internamente o compilador vai fazer com que seja usado o Iterator daCollectiondadaparapercorreracoleção.Repare:
Set<String>conjunto=newHashSet<>();
conjunto.add("java");conjunto.add("vraptor");conjunto.add("scala");
for(Stringpalavra:conjunto){System.out.println(palavra);}
Emqueordemoselementosserãoacessados?
15.9PERCORRENDOCOLEÇÕESNOJAVA5
.
Numa lista, os elementos aparecerão de acordo com o índice em que foram inseridos, isto é, deacordo com o que foi pré-determinado. Em um conjunto, a ordem depende da implementação dainterfaceSet:vocêmuitasvezesnãovaisaberaocertoemqueordemosobjetosserãopercorridos.
PorqueoSeté,então,tãoimportanteeusado?
Paraperceberseumitemjáexisteemumalista,émuitomaisrápidousaralgumasimplementaçõesdeSetdoqueumList, eosTreeSets já vêmordenadosde acordo comas características quedesejarmos!SempreconsidereusarumSetsenãohouveranecessidadedeguardaroselementosemdeterminadaordemebuscá-losatravésdeumíndice.
No eclipse, você pode escrever foreach e dar ctrl+espaço, que ele vai gerar o esqueleto desseenhancedfor!Muitoútil!
Antes do Java 5 introduzir o novo enhanced-for, iterações em coleções eram feitas com oIterator . Toda coleção fornece acesso a um iterator, um objeto que implementa a interfaceIterator,queconheceinternamenteacoleçãoedáacessoatodososseuselementos,comoafiguraabaixomostra.
Aindahoje(depoisdoJava5)podemosusaroIterator,masomaiscomuméusaroenhanced-for.E,naverdade,oenhanced-foréapenasumaçúcarsintáticoqueusaiteratorportrásdospanos.
Primeiro criamos um Iterator que entra na coleção. A cada chamada do método next, oIterator retorna o próximo objeto do conjunto.Um iterator pode ser obtido com ométodoiterator()deCollection,porexemplonumalistadeString:
Iterator<String>i=lista.iterator();
AinterfaceIteratorpossuidoismétodosprincipais:hasNext()(comretornobooleano),indica
15.10 PARA SABER MAIS: ITERANDO SOBRE COLEÇÕES COMJAVA.UTIL.ITERATOR
.
seaindaexisteumelementoaserpercorrido;next(),retornaopróximoobjeto.
Voltandoaoexemplodoconjuntodestrings,vamospercorreroconjunto:
Set<String>conjunto=newHashSet<>();conjunto.add("item1");conjunto.add("item2");conjunto.add("item3");
//retornaoiteratorIterator<String>i=conjunto.iterator();while(i.hasNext()){//recebeapalavraStringpalavra=i.next();System.out.println(palavra);}
Owhile anterior só terminaquando todosos elementosdo conjunto forempercorridos, isto é,quandoométodohasNextmencionarquenãoexistemmaisitens.
LISTITERATOR
Umalistafornece,alémdeacessoaumIterator,umListIterator,queoferecerecursosadicionais,específicosparalistas.
UsandooListIterator,vocêpode,porexemplo,adicionarumelementonalistaouvoltarparaoelementoquefoi"iterado"anteriormente.
USARITERATOREMVEZDOENHANCED-FOR?
OIteratorpodesimaindaserútil.Alémde iterarnacoleçãocomofazoenhanced-for,oIterator consegue remover elementos da coleção durante a iteração de uma forma elegante,atravésdométodoremove.
.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
Muitas vezes queremos buscar rapidamente um objeto dado alguma informação sobre ele. Umexemploseria,dadaaplacadocarro,obtertodososdadosdocarro.Poderíamosutilizarumalistaparaissoepercorrer todososseuselementos,mas issopodeserpéssimoparaaperformance,mesmoparalistasnãomuitograndes.Aquientraomapa.
Ummapaécompostoporumconjuntodeassociaçõesentreumobjetochaveaumobjetovalor.Éequivalenteaoconceitodedicionário,usadoemvárias linguagens.Algumas linguagens,comoPerlouPHP,possuemumsuportemaisdiretoamapas,ondesãoconhecidoscomomatrizes/arraysassociativas.
java.util.Map é um mapa, pois é possível usá-lo para mapear uma chave a um valor, porexemplo: mapeie à chave "empresa" o valor "Caelum", ou então mapeie à chave "rua" ao valor"Vergueiro".Semelhanteaassociaçõesdepalavrasquepodemosfazeremumdicionário.
Agoraéamelhorhoraderespirarmaistecnologia!
15.11MAPAS-JAVA.UTIL.MAP
.
Ométodo put(Object, Object) da interface Map recebe a chave e o valor de uma novaassociação. Para saber o que está associado a um determinado objeto-chave, passa-se esse objeto nométodoget(Object).Semdúvidaessassãoasduasoperaçõesprincipaisemaisfrequentesrealizadassobreummapa.
Observeoexemplo:criamosduascontascorrenteseascolocamosemummapaassociando-asaosseusdonos.
ContaCorrentec1=newContaCorrente();c1.deposita(10000);
ContaCorrentec2=newContaCorrente();c2.deposita(3000);
//criaomapaMap<String,ContaCorrente>mapaDeContas=newHashMap<>();
//adicionaduaschaveseseusrespectivosvaloresmapaDeContas.put("diretor",c1);mapaDeContas.put("gerente",c2);
//qualacontadodiretor?(semcasting!)ContaCorrentecontaDoDiretor=mapaDeContas.get("diretor");System.out.println(contaDoDiretor.getSaldo());
Ummapaémuitousadopara"indexar"objetosdeacordocomdeterminadocritério,parapodermosbuscar esse objetos rapidamente. Ummapa costuma aparecer juntamente com outras coleções, parapoderrealizaressasbuscas!
Ele,assimcomoascoleções,trabalhadiretamentecomObjects(tantonachavequantonovalor),oque tornaria necessário o casting no momento que recuperar elementos. Usando os generics, comofizemosaqui,nãoprecisamosmaisdocasting.
SuasprincipaisimplementaçõessãooHashMap,oTreeMapeoHashtable.
Apesardomapa fazerpartedo framework, elenão estende a interfaceCollection, por ter umcomportamentobemdiferente.Porém,ascoleçõesinternasdeummapa(adechaveseadevalores,verFigura7)sãoacessíveispormétodosdefinidosnainterfaceMap.
.
OmétodokeySet()retornaumSetcomaschavesdaquelemapaeométodovalues()retornaaCollectioncomtodososvaloresqueforamassociadosaalgumadaschaves.
Ummapa importante é a tradicional classeProperties, quemapeia strings e émuitoutilizadaparaaconfiguraçãodeaplicações.
APropertiespossui,também,métodosparaleregravaromapeamentocombaseemumarquivotexto,facilitandomuitoasuapersistência.
Propertiesconfig=newProperties();
config.setProperty("database.login","scott");config.setProperty("database.password","tiger");config.setProperty("database.url","jdbc:mysql:/localhost/teste");
//muitaslinhasdepois...
Stringlogin=config.getProperty("database.login");Stringpassword=config.getProperty("database.password");Stringurl=config.getProperty("database.url");DriverManager.getConnection(url,login,password);
ReparequenãohouveanecessidadedocastingparaStringnomomentoderecuperarosobjetosassociados. Isto porque a classe Properties foi desenhada com o propósito de trabalhar com a
15.12PARASABERMAIS:PROPERTIES
.
associaçãoentreStrings.
Muitas das coleções do java guardam os objetos dentro de tabelas de hash. Essas tabelas sãoutilizadasparaqueapesquisadeumobjetosejafeitademaneirarápida.
Comofunciona?Cadaobjetoé"classificado"peloseuhashCodee,comisso,conseguimosespalharcadaobjetoagrupando-ospelohashCode.Quandobuscamosdeterminadoobjeto,sóvamosprocurarentre os elementos que estão no grupo daquele hashCode. Dentro desse grupo, vamos testando oobjetoprocuradocomocandidatousandoequals().
Paraque isso funcionedireito,ométodohashCodedecadaobjetodeve retornaromesmovalorparadoisobjetos,seelessãoconsideradosequals.Emoutraspalavras:
a.equals(b)implicaa.hashCode()==b.hashCode()
Implementar hashCode de tal maneira que ele retorne valores diferentes para dois objetosconsideradosequalsquebraocontratodeObjecteresultaráemcollectionsqueusamespalhamento(comoHashSet,HashMapeHashtable),nãoachandoobjetosiguaisdentrodeumamesmacoleção.
EQUALSEHASHCODENOECLIPSE
O Eclipse é capaz de gerar uma implementação correta de equals e hashcode baseado nosatributosquevocêqueiracomparar.BastairnomenuSourceedepoisemGeneratehashcode()andequals().
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
15.13PARASABERMAIS:EQUALSEHASHCODE
EditoraCasadoCódigocomlivrosdeumaformadiferente
.
AscoleçõesdoJavaoferecemgrandeflexibilidadeaousuário.Aperdadeperformanceemrelaçãoàutilizaçãodearrayséirrelevante,masdeve-setomaralgumasprecauções:
Grande parte das coleções usam, internamente, um array para armazenar os seus dados.Quandoessearraynãoémaissuficiente,écriadaummaioreoconteúdodaantigaécopiado.Esteprocessopodeacontecermuitasvezes,nocasodevocêterumacoleçãoquecrescemuito.Vocêdeve,então,criarumacoleçãojácomumacapacidadegrande,paraevitaroexcessoderedimensionamento.
Eviteusarcoleçõesqueguardamoselementospelasuaordemdecomparaçãoquandonãohánecessidade.UmTreeSet gasta computacionalmenteO(log(n)) para inserir (ele utilizaumaárvorerubro-negracomoimplementação),enquantooHashSetgastaapenasO(1).
NãoiteresobreumaListutilizandoumforde0atélist.size()eusandoget(int)parareceberosobjetos.Enquantoissopareceatraente,algumasimplementaçõesdaListnãosão de acesso aleatório como a LinkedList , fazendo esse código ter uma péssimaperformancecomputacional.(useIterator)
1. Crieumcódigoqueinsira30milnúmerosnumaArrayListepesquise-os.VamosusarummétododeSystemparacronometrarotempogasto:
publicclassTestaPerformance{
publicstaticvoidmain(String[]args){System.out.println("Iniciando...");Collection<Integer>teste=newArrayList<>();longinicio=System.currentTimeMillis();
inttotal=30000;
for(inti=0;i<total;i++){teste.add(i);}
for(inti=0;i<total;i++){teste.contains(i);}
longfim=System.currentTimeMillis();longtempo=fim-inicio;System.out.println("Tempogasto:"+tempo);}}
TroqueaArrayListporumHashSeteverifiqueotempoquevaidemorar:
Collection<Integer>teste=newHashSet<>();
15.14PARASABERMAIS:BOASPRÁTICAS
15.15EXERCÍCIOS:COLLECTIONS
.
Oqueélento?Ainserçãode30milelementosouas30milbuscas?Descubracomputandootempogastoemcadaforseparadamente.
Adiferençaémaisquegritante.Sevocêpassarde30milparaumnúmeromaior,como50ou100mil,veráqueissoinviabilizaporcompletoousodeumaList,nocasoemquequeremosutilizá-laessencialmenteempesquisas.
2. (conceitual,importante)Repareque,sevocêdeclararacoleçãoedernewassim:
Collection<Integer>teste=newArrayList<>();
emvezde:
ArrayList<Integer>teste=newArrayList<>();
É garantido que vai ter de alterar só essa linha para substituir a implementação porHashSet.Estamosaquiusandoopolimorfismoparanosprotegerquemudançasde implementaçãovenhamnos obrigar a alterar muito código. Mais uma vez: programe voltado a interface, e não àimplementação!
Esse é um excelente exemplo de bom uso de interfaces, afinal, de que importa como a coleçãofunciona? O que queremos é uma coleção qualquer, isso é suficiente para os nossos propósitos!Nosso código está com baixo acoplamento em relação a estrutura de dados utilizada: podemostrocá-lafacilmente.
Esseéumcódigoextremamenteelegantee flexível.Como tempovocêvai repararque as pessoastentamprogramarsempresereferindoaessasinterfacesmenosespecíficas,namedidadopossível:métodos costumam receber e devolver Collections, Lists e Sets em vez de referenciardiretamente uma implementação. É o mesmo que ocorre com o uso de InputStream eOutputStream:elessãoosuficiente,nãoháporqueforçarousodealgomaisespecífico.
Obviamente,algumasvezesnãoconseguimostrabalhardessaformaeprecisamosusarumainterfacemaisespecíficaoumesmonosreferiraoobjetopelasuaimplementaçãoparapoderchamaralgunsmétodos. Por exemplo, TreeSet tem mais métodos que os definidos em Set, assim comoLinkedListemrelaçãoàList.
DêumexemplodeumcasoemquenãopoderíamosnosreferiraumacoleçãodeelementoscomoCollection,masnecessariamenteporinterfacesmaisespecíficascomoListouSet.
3. FaçatestescomoMap,comovistonessecapítulo:
publicclassTestaMapa{
publicstaticvoidmain(String[]args){Contac1=newContaCorrente();c1.deposita(10000);
Contac2=newContaCorrente();
.
c2.deposita(3000);
//criaomapaMapmapaDeContas=newHashMap();
//adicionaduaschaveseseusvaloresmapaDeContas.put("diretor",c1);mapaDeContas.put("gerente",c2);
//qualacontadodiretor?ContacontaDoDiretor=(Conta)mapaDeContas.get("diretor");System.out.println(contaDoDiretor.getSaldo());}}
Depois,altereocódigoparausarogenericsenãohaveranecessidadedocasting,alémdagarantiadequenossomapaestaráseguroemrelaçãoatipagemusada.
VocêpodeutilizaroquickfixdoEclipseparaqueeleconserteissoparavocê:nalinhaemquevocêestáchamandooput,useoctrl+1.Depoisdemaisumquickfix(descubra!)seucódigodeveficarcomosegue:
//criaomapaMap<String,Conta>mapaDeContas=newHashMap<>();
Queopçãodoctrl+1vocêescolheuparaqueeleadicionasseogenericsparavocê?
4. (opcional)Assimcomono exercício1, crieumacomparação entreArrayList eLinkedList,para ver qual é a mais rápida para se adicionar elementos na primeira posição (list.add(0,elemento)),comoporexemplo:
publicclassTestaPerformanceDeAdicionarNaPrimeiraPosicao{publicstaticvoidmain(String[]args){System.out.println("Iniciando...");longinicio=System.currentTimeMillis();
//trocardepoisporArrayListList<Integer>teste=newLinkedList<>();
for(inti=0;i<30000;i++){teste.add(0,i);}
longfim=System.currentTimeMillis();doubletempo=(fim-inicio)/1000.0;System.out.println("Tempogasto:"+tempo);}}
Seguindo o mesmo raciocínio, você pode ver qual é a mais rápida para se percorrer usando oget(indice) (sabemosqueo correto seriautilizar o enhanced for ouoIterator). Para isso,insira30milelementosedepoispercorra-osusandocadaimplementaçãodeList.
Perceba que aqui o nosso intuito não é que você aprenda qual é o mais rápido, o importante éperceber que podemos tirar proveito do polimorfismo para nos comprometer apenas com a
.
interface.Depois,quandonecessário,podemostrocareescolherumaimplementaçãomaisadequadaasnossasnecessidades.
Qualdasduaslistasfoimaisrápidaparaadicionarelementosàprimeiraposição?
5. (opcional) Crie a classe Banco (caso não tenha sido criada anteriormente) no pacotebr.com.caelum.contas.modeloquepossuiumaListdeContachamadacontas.ReparequenumalistadeConta,vocêpodecolocartantoContaCorrentequantoContaPoupancaporcausadopolimorfismo.
Crie ummétodovoid adiciona(Conta c), ummétodoConta pega(int x) e outro intpegaQuantidadeDeContas(). Basta usar a sua lista e delegar essas chamadas para os métodos ecoleçõesqueestudamos.
ComoficouaclasseBanco?
6. (opcional)NoBanco,crieummétodoContabuscaPorTitular(Stringnome)queprocuraporumaContacujotitularsejaequalsaonomeDoTitulardado.
Vocêpode implementaressemétodocomumfornasua listadeConta, porémnão temumaperformanceeficiente.
Adicionandoum atributo privado do tipoMap<String,Conta> terá um impacto significativo.Toda vez que o método adiciona(Conta c) for invocado, você deve invocar.put(c.getTitular(),c)noseumapa.Dessamaneira,quandoalguéminvocarométodoContabuscaPorTitular(String nomeDoTitular), basta você fazer o get no seu mapa, passandonomeDoTitularcomoargumento!
Note, apenas, que isso é só um exercício! Dessa forma você não poderá ter dois clientes com omesmonomenessebanco,oquesabemosquenãoélegal.
ComoficariasuaclasseBancocomesseMap?
7. (opcional, avançado) Crie o método hashCode para a sua conta, de forma que ele respeite oequalsdequeduascontassãoequalsquandotemomesmonúmeroeagência.Felizmenteparanós, o próprio Eclipse já vem com um criador de equals e hashCode que os faz de formaconsistente.
NaclasseConta,useoctrl+3ecomeceaescreverhashCodeparaacharaopçãodegerá-los.Então,selecioneosatributosnumeroeagenciaemandegerarohashCodeeoequals.
Comoficouocódigogerado?
8. (opcional, avançado) Crie uma classe de teste e verifique se sua classe Conta funciona agoracorretamenteemumHashSet,istoé,queelanãoguardacontascomnúmeroeagênciarepetidos.
.
Depois,removaométodohashCode.Continuafuncionando?
DominarousoeofuncionamentodohashCodeéfundamentalparaobomprogramador.
1. Gere todososnúmeros entre 1 e 1000 eordene emordemdecrescenteutilizandoumTreeSet.Comoficouseucódigo?
2. Geretodososnúmerosentre1e1000eordeneemordemdecrescenteutilizandoumArrayList.Comoficouseucódigo?
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
E se precisarmos ordernar uma lista com outro critério de comparação? Se precisarmos alterar aprópriaclasseemudarseumétodocompareTo, teremosapenasuma formade comparaçãoporvez.Precisamosdemais!
É possível definir outros critérios de ordenação usando a interface do java.util chamadaComparator . Existe um método sort em Collections que recebe, além da List , umComparatordefinindoumcritériodeordenaçãoespecífico.ÉpossívelterváriosComparators comcritériosdiferentesparausarquandofornecessário.
VamoscriarumComparatorqueserveparaordernarStringsdeacordocomseutamanho.
classComparadorPorTamanhoimplementsComparator<String>{publicintcompare(Strings1,Strings2){if(s1.length()<s2.length())return-1;
15.16DESAFIOS
JáconheceoscursosonlineAlura?
15.17PARASABERMAIS:COMPARATORS,CLASSESANÔNIMAS,JAVA8EOLAMBDA
.
if(s2.length()<s1.length())return1;return0;}}
Repare que, diferente de Comparable , o método aqui se chama compare e recebe doisargumentos,jáquequemoimplementanãoéopróprioobjeto.
Podemosdeixá-lomaiscurto,tomandoproveitodométodoestáticoauxiliarInteger.comparequecomparadoisinteiros:
classComparadorPorTamanhoimplementsComparator<String>{publicintcompare(Strings1,Strings2){returnInteger.compare(s1.length(),s2.length());}}
Depois, dentro do nosso código, teríamos uma chamada a Collections.sort passando ocomparadortambém:
List<String>lista=newArrayList<>();lista.add("Sérgio");lista.add("Paulo");lista.add("Guilherme");
//invocandoosortpassandoocomparadorComparadorPorTamanhocomparador=newComparadorPorTamanho();Collections.sort(lista,comparador);
System.out.println(lista);
Comoavariáveltemporáriacomparadoréutilizadaapenasaí,écomumescrevermosdiretamenteCollections.sort(lista,newComparadorPorTamanho()).
ReparequeaclasseComparadorPorTamanhoébempequena.Écomumhaveranecessidadedecriarvários critérios de comparação, emuitas vezes eles são utilizados apenas num único ponto do nossoprograma.
Háumaformadeescreveressaclasseeinstanciá-lanumaúnicainstrução.VocêfazissodandonewemComparator.Mascomo,sedissemosqueumainterfacenãopodeserinstanciada?RealmentenewComparator() não compila. Mas vai compilar se você abrir chaves e implementar tudo o que énecessário.Vejaocódigo:
List<String>lista=newArrayList<>();lista.add("Sérgio");lista.add("Paulo");lista.add("Guilherme");
Comparator<String>comparador=newComparator<String>(){publicintcompare(Strings1,Strings2){
EscrevendoumComparatorcomclasseanônima
.
returnInteger.compare(s1.length(),s2.length());}};Collections.sort(lista,comparador);
System.out.println(lista);
Asintaxeérealmenteesdrúxula!Numaúnicalinhanósdefinimosumaclasseeainstanciamos!Umaclassequenemmesmonometem.Poressemotivoorecursoéchamadodeclasseanônima.Eleaparececomcertafrequência,emespecialparanãoprecisarimplementarinterfacesqueocódigodosmétodosseriammuitocurtosenão-reutilizáveis.
Há ainda como diminuir ainda mais o código, evitando a criação da variável temporáriacomparadoreinstanciandoainterfacedentrodainvocaçãoparaosort:
List<String>lista=newArrayList<>();lista.add("Sérgio");lista.add("Paulo");lista.add("Guilherme");
Collections.sort(lista,newComparator<String>(){publicintcompare(Strings1,Strings2){returnInteger.compare(s1.length(),s2.length());}});
System.out.println(lista);
VocêpodefazerodownloaddoJava8aqui:
https://jdk8.java.net/download.html
O Eclipse já possui atualizações para compatibilidade com a nova versão, mas ele pode serrelativamenteinstável.Vocêpodeutilizaralinhadecomando,comofizemosnocomeçodocurso,paraessestestes,casoachenecessário.
ApartirdessanovaversãodoJavaháumaformamaissimplesdeobteressemesmoComparator.Repare:
Collections.sort(lista,(s1,s2)->Integer.compare(s1.length(),s2.length()));
Ocódigo(s1,s2)->Integer.compare(s1.length(),l2.length())geraráumainstânciadeComparatorqueocompare devolveInteger.compare(s1.length,l2.length).Atémesmooreturnnãoénecessário,jáquesótemosumainstruçãoapóso->.EsseéorecursodelambdadoJava8.
Uma outra novidade do Java 8 é a possibilidade de declarar métodos concretos dentro de umainterface, os chamadosdefaultmethods. Até o Java 7 não existiasort em listas. Colocar um novométodoabstratoemumainterfacepodeterconsequênciasdrásticas: todomundoqueaimplementava
EscrevendoumComparatorcomlambdanoJava8
.
paradecompilar!Mascolocarummétododefaultnãotemessemesmoimpactodevastador, jáqueasclassesqueimplementamainterface'herdam'essemétodo.Entãovocêpodefazer:
lista.sort((s1,s2)->Integer.compare(s1.length(),s2.length()));
Háoutrosmétodosnascoleçõesqueutilizamdolambdaparaseremmaissucintos.
UmdeleséoforEach.Vocêpodefazerlista.forEach(s->System.out.println(s)).
OremoveIféoutrodeles.Porexemplo,podemosescreverlista.removeIf(c->c.getSaldo()<0).OremoveIfrecebecomoargumentoumobjetoqueimplementeainterfacePredicate,quepossuiapenasummétodo,querecebeumelementedevolveboolean.Porpossuirapenasummétodoabstrato também chamamos essa interface é uma interface funcional. Omesmo ocorre ao invocar oforEach,querecebeumargumentoqueimplementaainterfacefuncionalConsumer.
TrabalharcomlambdasnoJava8vaimuitoalém.Hádiversosdetalheserecursosquenãoveremosnesseprimeirocurso.Casotenhacuriosidadeequeirasabermais,vejanoblog:
http://blog.caelum.com.br/o-minimo-que-voce-deve-saber-de-java-8/
Mais?Methodreferences,streamsecollectors
.
CAPÍTULO16
"A benevolência é sobretudo um vício do orgulho e não uma virtude da alma." -- Doantien AlphonseFrançois(MarquêsdeSade)
Aotérminodessecapítulo,vocêserácapazde:
usarasclasseswrappers(comoInteger)eboxing;lereescreverbytes,caractereseStringsde/paraaentradaesaídapadrão;lereescreverbytes,caractereseStringsde/paraarquivos;utilizarbuffersparaagilizaraleituraeescritaatravésdefluxos;usarScannerePrintStream.
VamospassaraconhecerAPIsdoJava.java.ioejava.utilpossuemasclassesquevocêmaiscomumentevaiusar,nãoimportandoseseuaplicativoédesktop,web,oumesmoparacelulares.
Apesardeserimportanteconhecernomesemétodosdasclassesmaisutilizadas,ointeressanteaquiéquevocêenxerguequetodososconceitospreviamenteestudadossãoaplicadosatodahoranasclassesdabibliotecapadrão.
Nãosepreocupeemdecorarnomes.Atenha-seementendercomoessasclassesestãorelacionadasecomoelasestãotirandoproveitodousodeinterfaces,polimorfismo,classesabstrataseencapsulamento.Lembre-sedeestarcomadocumentação(javadoc)abertaduranteocontatocomessespacotes.
Veremos também threads e sockets em capítulos posteriores, que ajudarão a condensar nossoconhecimento, tendo em vista que no exercício de sockets utilizaremos todos conceitos aprendidos,juntamentecomasváriasAPIs.
PACOTEJAVA.IO
16.1CONHECENDOUMAAPI
.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
AssimcomotodoorestodasbibliotecasemJava,apartedecontroledeentradae saídadedados(conhecidocomoio)éorientadaaobjetoseusaosprincipaisconceitosmostradosatéagora:interfaces,classesabstratasepolimorfismo.
Aideiaatrásdopolimorfismonopacotejava.ioédeutilizarfluxosdeentrada(InputStream)edesaída(OutputStream)paratodaequalqueroperação,sejaelarelativaaumarquivo,aumcampoblobdobancodedados,aumaconexãoremotaviasockets,ouatémesmoàsentradaesaídapadrãodeumprograma(normalmenteotecladoeoconsole).
AsclassesabstratasInputStreameOutputStreamdefinem,respectivamente,ocomportamentopadrãodos fluxosemJava:emumfluxodeentrada,épossível lerbytese,no fluxode saída,escreverbytes.
A grande vantagem dessa abstração pode ser mostrada em ummétodo qualquer que utiliza umOutputStreamrecebidocomoargumentoparaescreveremumfluxodesaída.Paraondeométodoestáescrevendo?Nãosesabeenãoimporta:quandoosistemaprecisarescreveremumarquivoouemumasocket,bastachamaromesmométodo,jáqueeleaceitaqualquerfilhadeOutputStream!
Paralerumbytedeumarquivo,vamosusaroleitordearquivo,oFileInputStream.ParaumFileInputStreamconseguirlerumbyte,eleprecisasaberdeondeeledeveráler.Essainformaçãoétãoimportantequequemescreveuessaclasseobrigavocêapassaronomedoarquivopeloconstrutor:semissooobjetonãopodeserconstruído.
classTestaEntrada{publicstaticvoidmain(String[]args)throwsIOException{
Seuslivrosdetecnologiaparecemdoséculopassado?
16.2ORIENTAÇÃOAOBJETOSNOJAVA.IO
16.3INPUTSTREAM,INPUTSTREAMREADEREBUFFEREDREADER
.
InputStreamis=newFileInputStream("arquivo.txt");intb=is.read();}}
A classe InputStream é abstrata e FileInputStream uma de suas filhas concretas.FileInputStream vai procurar o arquivo no diretório em que a JVM fora invocada (no caso doEclipse,vaiserapartirdedentrododiretóriodoprojeto).Alternativamentevocêpodeusarumcaminhoabsoluto.
Quandotrabalhamoscomjava.io,diversosmétodoslançamIOException,queéumaexceptiondo tipo checked - o que nos obriga a tratá-la ou declará-la. Nos exemplos aqui, estamos declarandoIOExceptionatravésdaclausulathrowsdomainapenasparafacilitaroexemplo.Casoaexceptionocorra,aJVMvaiparar,mostrandoastacktrace.Estanãoéumaboapráticaemumaaplicaçãoreal:tratesuasexceptionsparasuaaplicaçãopoderabortarelegantemente.
InputStream tem diversas outras filhas, como ObjectInputStream , AudioInputStream ,ByteArrayInputStream,entreoutras.
Pararecuperarumcaractere,precisamostraduzirosbytescomoencodingdadoparaorespectivocódigounicode,issopodeusarumoumaisbytes.Escreveressedecodificadorémuitocomplicado,quemfazissoporvocêéaclasseInputStreamReader.
classTestaEntrada{publicstaticvoidmain(String[]args)throwsIOException{InputStreamis=newFileInputStream("arquivo.txt");InputStreamReaderisr=newInputStreamReader(is);intc=isr.read();}}
OconstrutordeInputStreamReaderpodereceberoencodingaserutilizadocomoparâmetro,sedesejado,talcomoUTF-8ouISO-8859-1.
ENCODINGS
Devidoagrandequantidadedeaplicativosinternacionalizadosdehojeemdia,éimprescindívelqueumbomprogramadorentendabemoquesãooscharacterencodingseoUnicode.OblogdaCaelumpossuiumbomartigoarespeito:
http://blog.caelum.com.br/2006/10/22/entendendo-unicode-e-os-character-encodings/
InputStreamReader é filha da classe abstrataReader, que possui diversas outras filhas - sãoclassesquemanipulamchars.
ApesardaclasseabstrataReader jáajudarnotrabalhodemanipulaçãodecaracteres,aindaseria
.
difícilpegarumaString.AclasseBufferedReaderéumReaderquerecebeoutroReaderpeloconstrutoreconcatenaosdiversoscharsparaformarumaStringatravésdométodoreadLine:
classTestaEntrada{publicstaticvoidmain(String[]args)throwsIOException{InputStreamis=newFileInputStream("arquivo.txt");InputStreamReaderisr=newInputStreamReader(is);BufferedReaderbr=newBufferedReader(isr);Strings=br.readLine();}}
Como o próprio nome diz, essa classe lê doReader por pedaços (usando o buffer) para evitarrealizarmuitaschamadasao sistemaoperacional.Vocêpodeatéconfiguraro tamanhodobufferpeloconstrutor.
Éessaacomposiçãodeclassesqueestáacontecendo:
Essepadrãodecomposiçãoébastanteutilizadoeconhecido.ÉoDecoratorPattern.
Aqui,lemosapenasaprimeiralinhadoarquivo.OmétodoreadLinedevolvealinhaquefoilidaemuda o cursor para a próxima linha. Caso ele chegue ao fim do Reader (no nosso caso, fim doarquivo),elevaidevolvernull.Então,comumsimpleslaço,podemosleroarquivoporinteiro:
classTestaEntrada{publicstaticvoidmain(String[]args)throwsIOException{InputStreamis=newFileInputStream("arquivo.txt");InputStreamReaderisr=newInputStreamReader(is);BufferedReaderbr=newBufferedReader(isr);
Strings=br.readLine();//primeiralinha
while(s!=null){System.out.println(s);s=br.readLine();}
br.close();}}
Com um passe de mágica, passamos a ler do teclado em vez de um arquivo, utilizando oSystem.in,queéumareferênciaaumInputStreamoqual,porsuavez,lêdaentradapadrão.
16.4LENDOSTRINGSDOTECLADO
.
classTestaEntrada{publicstaticvoidmain(String[]args)throwsIOException{InputStreamis=System.in;InputStreamReaderisr=newInputStreamReader(is);BufferedReaderbr=newBufferedReader(isr);Strings=br.readLine();
while(s!=null){System.out.println(s);s=br.readLine();}}}
Apenasmodificamosaquemavariávelisestásereferindo.PodemosreceberargumentosdotipoInputStream e ter esse tipo de abstração: não importa exatamente de onde estamos lendo essepunhadodebytes,desdequeagenterecebaainformaçãoqueestamosquerendo.Comonafigura:
Repare que a ponta da direita poderia ser qualquer InputStream, seja ObjectInputStream,AudioInputStream,ByteArrayInputStream,ouanossaFileInputStream.Polimorfismo!OuvocêmesmopodecriarumafilhadeInputStream,sedesejar.
Por isso émuito comummétodos recebereme retornaremInputStream, em vez de suas filhasespecíficas. Com isso, elas desacoplam as informações e escondem a implementação, facilitando amudançaemanutençãodocódigo.Reparequeissovaiaoencontrodetudooqueaprendemosduranteoscapítulosqueapresentaramclassesabstratas,interfaces,polimorfismoeencapsulamento.
.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
Comovocêpodeimaginar,escreveremumarquivoéomesmoprocesso:
classTestaSaida{publicstaticvoidmain(String[]args)throwsIOException{OutputStreamos=newFileOutputStream("saida.txt");OutputStreamWriterosw=newOutputStreamWriter(os);BufferedWriterbw=newBufferedWriter(osw);
bw.write("caelum");
bw.close();}}
Lembre-sededarrefresh (cliquedadireitanonomedoprojeto,refresh)noseuprojetodoEclipseparaqueoarquivocriadoapareça.OFileOutputStream pode receberumbooleanocomosegundoparâmetro,paraindicarsevocêquerreescreveroarquivooumanteroquejáestavaescrito(append).
OmétodowritedoBufferedWriternãoinsereo(s)caractere(s)dequebradelinha.Paraisso,vocêpodechamarométodonewLine.
Agoraéamelhorhoraderespirarmaistecnologia!
16.5AANALOGIAPARAAESCRITA:OUTPUTSTREAM
.
FECHANDOOARQUIVOCOMOFINALLYEOTRY-WITH-RESOURCES
Éimportantesemprefecharoarquivo.Vocêpodefazerissochamandodiretamenteométodo close do FileInputStream / OutputStream , ou ainda chamando o close doBufferedReader/Writer.Nesseúltimocaso,ocloseserácascateadoparaosobjetososquaisoBufferedReader/Writer utiliza para realizar a leitura/escrita, além dele fazer o flush dosbuffersnocasodaescrita.
Écomumefundamentalqueocloseestejadentrodeumblocofinally.Seumarquivoforesquecido aberto e a referência para ele for perdida, pode ser que ele seja fechado pelo garbagecollector,queveremosmaisa frente,porcausadofinalize.Masnãoébomvocêseprenderaisso. Se você esquecer de fechar o arquivo, no caso de um programa minúsculo como esse, oprogramavaiterminarantesqueotaldogarbagecollectorteajude,resultandoemumarquivonãoescrito(osbytes ficaramnobufferdoBufferedWriter). Problemas similares podemacontecercomleitoresquenãoforemfechados.
No Java 7 há a estrutura try-with-resources, que já fará o finally cuidar dos recursosdeclarados dentro do try(), invocando close. Pra isso, os recursos devem implementar ainterfacejava.lang.AutoCloseable,queéocasodosReaders,WriterseStreamsestudadosaqui:
try(BufferedReaderbr=newBufferedReader(newFile("arquivo.txt"))){//comexceçãoounão,oclose()dobrserainvocado}
ApartirdoJava5,temosaclassejava.util.Scanner,quefacilitabastanteotrabalhodelerdeumInputStream.Alémdisso,aclassePrintStreampossuiumconstrutorquejárecebeonomedeumarquivo como argumento.Dessa forma, a leitura do teclado com saída para um arquivo ficoumuitosimples:
Scanners=newScanner(System.in);PrintStreamps=newPrintStream("arquivo.txt");while(s.hasNextLine()){ps.println(s.nextLine());}
NenhumdosmétodoslançaIOException:PrintStreamlançaFileNotFoundExceptionsevocêoconstruirpassandoumaString.EssaexceçãoéfilhadeIOExceptioneindicaqueoarquivonãofoiencontrado.OScanner considerará que chegou ao fim se umaIOException for lançada, mas oPrintStreamsimplesmenteengoleexceptionsdessetipo.Ambospossuemmétodosparavocêverificarsealgumproblemaocorreu.
16.6UMAMANEIRAMAISFÁCIL:SCANNEREPRINTSTREAM
.
AclasseScanner é dopacotejava.util. Ela possuimétodosmuitoúteis para trabalhar comStrings, em especial, diversos métodos já preparados para pegar números e palavras já formatadasatravésdeexpressõesregulares.Ficafácilparsearumarquivocomqualquerformatodado.
SYSTEM.OUT
Comovimosnocapítulopassado,oatributooutdaclasseSystemédotipoPrintStream(e,portanto,éumOutputStream).
EOF
Quando rodar sua aplicação, para encerrar a entrada de dados do teclado, é necessárioenviarmosumsinaldefimdestream.ÉofamosoEOF,istoé,endoffile.
NoLinux/Mac/Solaris/Unixvocêfazissocomoctrl+D.NoWindows,useoctrl+Z.
Existem duas classes chamadas java.io.FileReader e java.io.FileWriter. Elas sãoatalhosparaaleituraeescritadearquivos.
Odo{..}while(condicao);éumaalternativaparaseconstruirumlaço.Pesquise-oeutilize-ono códigopara ler umarquivo, ele vai ficarmais sucinto (vocênãoprecisará ler aprimeiralinhaforadolaço).
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
16.7UMPOUCOMAIS...
EditoraCasadoCódigocomlivrosdeumaformadiferente
.
Anteriormente, vimos que conseguimos ler e escrever dados emum arquivono Java utilizando aclasseScanner. Por padrão, quando fazemos essas operações, estamos trabalhando sempre com osdadosemformadeString.Maseseprecisássemoslerouescrevernúmerosinteirosemumarquivo?ComofaríamosparatransformaressesnúmerosemStringevice-versa?
Cuidado!Usamosaquiotermo"transformar",porémoqueocorrenãoéumatransformaçãoentreos tipos e sim uma forma de conseguirmos umString dado umint e vice-versa. O jeito maissimplesdetransformarumnúmeroemStringéconcatená-lodaseguintemaneira:
inti=100;Strings=""+i;System.out.println(s);
doubled=1.2;Strings2=""+d;System.out.println(s2);
Para formatar o número de uma maneira diferente, com vírgula e número de casas decimaisdevemosutilizaroutrasclassesdeajuda(NumberFormat,Formatter).
ParatransformarumaStringemnúmero,utilizamosasclassesdeajudaparaostiposprimitivoscorrespondentes. Por exemplo, para transformar a Strings em um número inteiro utilizamos ométodoestáticodaclasseInteger:
Strings="101";inti=Integer.parseInt(s);
As classes Double, Short , Long , Float etc contêm o mesmo tipo de método, comoparseDoubleeparseFloatqueretornamumdoubleefloatrespectivamente.
Essas classes também sãomuito utilizadas para fazer owrapping (embrulho) de tipos primitivoscomo objetos, pois referências e tipos primitivos são incompatíveis. Imagine que precisamos passarcomoargumentouminteiroparaonossoguardadordeobjetos.UminteironãoéumObject,comofazer?
inti=5;Integerx=newInteger(i);guardador.adiciona(x);
E,dadoumInteger,podemospegarointqueestádentrodele(desembrulhá-lo):
inti=5;Integerx=newInteger(i);intnumeroDeVolta=x.intValue();
Esse processo de wrapping e unwrapping é entediante. O Java 5.0 em diante traz um recurso
16.8INTEGERECLASSESWRAPPERS(BOX)
16.9AUTOBOXINGNOJAVA5.0
.
chamadodeautoboxing,quefazissosozinhoparavocê,custandolegibilidade:
Integerx=5;inty=x;
NoJava1.4essecódigoéinválido.NoJava5.0emdianteelecompilaperfeitamente.Éimportanteressaltar que isso não quer dizer que tipos primitivos e referências sejam do mesmo tipo, isso ésimplesmenteum"açúcarsintático"(syntaxsugar)parafacilitaracodificação.
Vocêpodefazertodosostiposdeoperaçõesmatemáticascomoswrappers,porémcorreoriscodetomarumNullPointerException.
Vocêpode fazer o autoboxingdiretamenteparaObject também,possibilitandopassarum tipoprimitivoparaummétodoquereceberObjectcomoargumento:
Objecto=5;
NaclasseMath, existeumasériedemétodosestáticosque fazemoperaçõescomnúmeroscomo,por exemplo, arredondar(round), tirar o valor absoluto (abs), tirar a raiz(sqrt), calcular oseno(sin)eoutros.
doubled=4.6;longi=Math.round(d);
intx=-4;inty=Math.abs(x);
Consulteadocumentaçãoparaveragrandequantidadedemétodosdiferentes.
NoJava5.0,podemostirarproveitodoimportstaticaqui:
importstaticjava.lang.Math.*;
Issoeliminaanecessidadedeusaronomedaclasse,sobocustodelegibilidade:
doubled=4.6;longi=round(d);intx=-4;inty=abs(x);
16.10PARASABERMAIS:JAVA.LANG.MATH
.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
Vamossalvarascontascadastradasemumarquivoparanãoprecisarficaradicionandoascontasatodomomento.
1. NaclasseManipuladorDeContas,crieométodosalvaDadosquerecebeumEvento de ondeobteremosalistadecontas:
publicvoidsalvaDados(Eventoevento){List<Conta>contas=evento.getLista("listaContas");//aquisalvaremosascontasemarquivo}
2. Para não colocarmos todo o código de gerenciamento de arquivos dentro da classeManipuladorDeContas,vamoscriarumanovaclassecujaresponsabilidadeserálidarcomaescrita/ leitura de arquivos. Crie a classe RepositorioDeContas dentro do pacotebr.com.caelum.contasedeclareométodosalvaquedeverárecebera listadecontasaseremguardadas.Nestemétodovocêdevepercorreralistadecontasesalvá-lasseparandoasinformaçõesdetipo,numero,agencia,titularesaldocomvírgulas.Ocódigoficaráparecidocom:
publicclassRepositorioDeContas{
publicvoidsalva(List<Conta>contas){PrintStreamstream=newPrintStream("contas.txt");for(Contaconta:contas){stream.println(conta.getTipo()+","+conta.getNumero()+","+conta.getAgencia()+","+conta.getTitular()+","+conta.getSaldo());}stream.close();}}
O compilador vai reclamar que você não está tratando algumas exceções (como
JáconheceoscursosonlineAlura?
16.11EXERCÍCIOS:JAVAI/O
.
java.io.FileNotFoundException). Utilize o devido try/catch e relance a exceção comoRuntimeException.UtilizeoquickfixdoEclipseparafacilitar(ctrl+1).
Vale lembrarquedeixar todasasexceptionspassaremdespercebidasnãoéumaboaprática!Vocêpodeusaraqui,poisestamosfocandoapenasnoaprendizadodautilizaçãodojava.io.
Quandotrabalhamoscomrecursosquefalamcomaparteexternaànossaaplicação,éprecisoqueavisemosquandoacabarmosdeusaressesrecursos.Porisso,éimportantíssimo lembrardefecharoscanaiscomoexteriorqueabrimosutilizandoométodoclose!
3. Voltando à classe ManipuladorDeContas, vamos completar o método salvaDados para queutilizeanossanovaclasseRepositorioDeContascriada.
publicvoidsalvaDados(Eventoevento){List<Conta>contas=evento.getLista("listaContas");RepositorioDeContasrepositorio=newRepositorioDeContas();repositorio.salva(contas);}
Rodesuaaplicação,cadastrealgumascontaseveja seapareceumarquivochamadocontas.txtdentrododiretóriosrcdeseuprojeto.TalvezsejanecessáriodarumF5neleparaqueoarquivoapareça.
4. (Opcional,Difícil)Vamos fazercomquealémdesalvarosdadosemumarquivo,nossaaplicaçãotambém consiga carregar as informações das contas para já exibir na tela. Para que a aplicaçãofuncione, é necessário que a nossa classe ManipuladorDeContas possua um método chamadocarregaDados que devolva uma List<Conta>. Vamos fazer o mesmo que anteriormente eencapsularalógicadecarregamentodentrodaclasseRepositorioDeContas:
publicList<Conta>carregaDados(){RepositorioDeContasrepositorio=newRepositorioDeContas();returnrepositorio.carrega();}
Faça o código referente ao método carrega que devolve uma List dentro da classeRepositorioDeContasutilizandoaclasseScanner.ParaobterosvaloresdecadaatributovocêpodeutilizarométodosplitdaString.Lembre-sequeosatributosdascontassãocarregadosnaseguinteordem:tipo,numero,agencia,titularesaldo.Exemplo:
Stringlinha=scanner.nextLine();String[]valores=linha.split(",");Stringtipo=valores[0];
Alémdisso,acontadeveserinstanciadadeacordocomoconteúdodotipoobtido.Tambémfiqueatentopois osdados lidos virão sempre lidos em formadeString e para alguns atributos seránecessáriotransformarodadonostiposprimitivoscorrespondentes.Porexemplo:
StringnumeroTexto=valores[1];intnumero=Integer.parseInt(numeroTexto);
.
5. (opcional) A classe Scanner é muito poderosa! Consulte seu javadoc para saber sobre odelimitereosoutrosmétodosnext.
6. (opcional) Crie uma classe TestaInteger e vamos fazer comparações com Integers dentro domain:
Integerx1=newInteger(10);Integerx2=newInteger(10);
if(x1==x2){System.out.println("igual");}else{System.out.println("diferente");}
Esetestarmoscomoequals?Oquepodemosconcluir?
7. (opcional)Umdoublenãoestásendosuficienteparaguardaraquantidadedecasasnecessáriasemumaaplicação.Precisoguardarumnúmerodecimalmuitogrande!Oquepoderiausar?
Odoubletambémtemproblemasdeprecisãoaofazercontas,porcausadearredondamentosdaaritméticadepontoflutuantedefinidopelaIEEE754:
http://en.wikipedia.org/wiki/IEEE_754
Elenãodeveserusadosevocêprecisarealmentedemuitaprecisão(casosqueenvolvamdinheiro,porexemplo).
Consulteadocumentação,tenteadivinharondevocêpodeencontrarumtipoqueteajudariapararesolveressescasosevejacomoéintuitivo!Qualéaclassequeresolveriaessesproblemas?
Lembre-se:noJavahámuitojápronto.Sejanabibliotecapadrão,sejaembibliotecasopensourcequevocêpodeencontrarpelainternet.
Aplicarbemosconceitosdeorientaçãoaobjetosé sempreumagrandedúvida.Semprequeremosencapsular direito, favorecer a flexibilidade, desacoplar classes, escrever código elegante e de fácilmanutenção.EouvimosfalarqueaOrientaçãoaObjetosajudaemtudoisso.
Mas,ondeusarherançadeformasaudável?Comousarinterfaces?Ondeopolimorfismomeajuda?Comoencapsulardireito?Classesabstratassãousadasemquesituações?
Muitos anos atrás, grandes nomes domundo da orientação a objetos perceberam que criar bonsdesigns orientados a objetos era um grande desafio para muitas pessoas. Perceberam que muitosproblemas de OO apareciam recorrentemente em vários projetos; e que as pessoas já tinham certas
16.12 DISCUSSÃO EM AULA: DESIGN PATTERNS E O TEMPLATEMETHOD
.
soluçõesparaessesproblemasclássicos(nemsempremuitoelegantes).
O que fizeram foi criar soluções padrões para problemas comuns na orientação a objetos, echamaramissodeDesignPatterns, ouPadrõesdeProjeto.Oconceitovinhadaarquiteturaondeeramuitocomumteressetipodesolução.E,em1994,ganhougrandepopularidadenacomputaçãocomolivroDesign Patterns: Elements of Reusable Object-Oriented Software, um catálogo com várias dessassoluções escrito por Erich Gamma, Ralph Johnson, Richard Helm e John Vlissides (a Gangue dosQuatro,GoF).
DesignPatterns tornou-sereferênciaabsolutanobomusodaorientaçãoaobjetos.Outrospadrõessurgiram depois, em outras literaturas igualmente consagradas. O conhecimento dessas técnicas éimprescindívelparaobomprogramador.
DiscutacomoinstrutorcomoDesignPatternsajudamaresolverproblemasdemodelagememsistemas orientados a objetos. Veja como Design Patterns são aplicados em muitos lugares dopróprioJava.
OinstrutorcomentarádoTemplateMethodemostraráocódigofontedométodoread()daclassejava.io.InputStream:
publicintread(byteb[],intoff,intlen)throwsIOException{if(b==null){thrownewNullPointerException();}elseif(off<0||len<0||len>b.length-off){thrownewIndexOutOfBoundsException();}elseif(len==0){return0;}
intc=read();if(c==-1){return-1;}
b[off]=(byte)c;
inti=1;try{for(;i<len;i++){c=read();if(c==-1){break;}b[off+i]=(byte)c;}}catch(IOExceptionee){}returni;}
Discuta em aula como esse método aplica conceitos importantes da orientação a objetos epromoveflexibilidadeeextensibilidade.
.
CAPÍTULO17
"Aprimeiracoisaaentenderéquevocênãoentende."--SorenAabyeKierkegaard
Ondecontinuarao terminarosexercíciosde 'JavaeOrientaçãoaObjetos'?Aquiháumpost comsugestõesdecomoiniciarnacarreira:
http://blog.caelum.com.br/como-posso-aprender-java-e-iniciar-na-carreira/
Evocêpodeseguirnessescursoseáreas:
UmdosprincipaisusosdoJavaérodaraplicaçõesweb.EntramaquitecnologiascomoServlets,JSPseferramentasfamosasdomercado,comooStruts.
A Caelum oferece o curso FJ-21, onde você pode estudar os tópicos necessários para começar atrabalharcomJavanawebusandoasmelhorespráticas,designpatternsetecnologiasdomercado.Essaapostilatambémestádisponívelparadownload.
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
A melhor maneira para fixar tudo o que foi visto nos capítulos anteriores é planejar e montar
EAGORA?
17.1WEB
EditoraCasadoCódigocomlivrosdeumaformadiferente
17.2PRATICANDOJAVAEUSANDOBIBLIOTECAS
.
pequenos sistemas. Pense na modelagem de suas classes, como e onde usar herança, polimorfismo,encapsulamentoeoutrosconceitos.PratiqueousodasAPIsmaisúteisdo Java integrando-asao seussistemas.
O curso FJ-22 é um laboratório que alémde demonstrar o uso diversasAPIs e boas práticas, vaimostrardiversosdesignpatternseseuscasosdeuso.
Diversosprogramadorescomomínimooumáximodeconhecimentosereúnemonlineparaatrocadedúvidas,informaçõeseideiassobreprojetos,bibliotecasemuitomais.Sãoosgruposdeusuáriosdejava.
UmdosmaisimportanteseconhecidosnoBrasiléoGUJ:
http://www.guj.com.br
O'FalandoemJava'nãopáraporaqui.ACaelumofereceumagrandevariedadedecursosquevocêpodeseguir.Algunsdosmaisrequisitados:
FJ-21:JavaparadesenvolvimentoWeb
FJ-22:LaboratórioJavacomTestes,JSF,WebServiceseDesignPatterns
FJ-25:PersistênciacomJPA,HibernateeEJBlite
FJ-26:LaboratórioWebcomJSFeCDI
FJ-57:DesenvolvimentomóvelcomGoogleAndroid
FJ-91:ArquiteturaeDesigndeProjetosJava
Consulte mais informações no nosso site e entre em contato conosco. Conheça nosso mapa decursos:
http://www.caelum.com.br/mapa-dos-cursos/
17.3GRUPOSDEUSUÁRIOS
17.4PRÓXIMOSCURSOS
.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
JáconheceoscursosonlineAlura?
.
CAPÍTULO18
"Oúnicolugarondeosucessovemantesdotrabalhoénodicionário."--AlbertEinstein
Aotérminodessecapítulo,vocêserácapazde:
executartarefassimultaneamente;colocartarefasparaaguardaratéqueumdeterminadoeventoocorra;entenderofuncionamentodoGarbageCollector.
Emvárias situações, precisamos "rodarduas coisas aomesmo tempo". ImagineumprogramaquegeraumrelatóriomuitograndeemPDF.Éumprocessodemoradoe,paradaralgumasatisfaçãoparaousuário,queremosmostrarumabarradeprogresso.QueremosentãogeraroPDFeaomesmotempoatualizarabarrinha.
Pensando um pouco mais amplamente, quando usamos o computador também fazemos váriascoisassimultaneamente:queremosnavegarnainterneteaomesmotempoouvirmúsica.
Anecessidadedesefazerváriascoisassimultaneamente,aomesmotempo,paralelamente,aparecefrequentemente na computação. Para vários programas distintos, normalmente o próprio sistemaoperacionalgerenciaissoatravésdeváriosprocessosemparalelo.
Em um programa só (um processo só), se queremos executar coisas em paralelo, normalmentefalamosdeThreads.
EmJava,usamosaclasseThreaddopacotejava.langparacriarmoslinhasdeexecuçãoparalelas.AclasseThreadrecebecomoargumentoumobjetocomocódigoquedesejamosrodar.Porexemplo,noprogramadePDFebarradeprogresso:
publicclassGeraPDF{
APÊNDICE-PROGRAMAÇÃOCONCORRENTEETHREADS
18.1THREADS
"Duastarefasaomesmotempo"
ThreadsemJava
.
publicvoidrodar(){//lógicaparageraropdf...}}
publicclassBarraDeProgresso{publicvoidrodar(){//mostrabarradeprogressoevaiatualizandoela...}}
E,nométodomain, criamososobjetosepassamosparaaclasseThread.Ométodostart éresponsávelporiniciaraexecuçãodaThread:
publicclassMeuPrograma{publicstaticvoidmain(String[]args){
GeraPDFgerapdf=newGeraPDF();ThreadthreadDoPdf=newThread(gerapdf);threadDoPdf.start();
BarraDeProgressobarraDeProgresso=newBarraDeProgresso();ThreadthreadDaBarra=newThread(barraDeProgresso);threadDaBarra.start();
}}
Ocódigoacima,porém,nãocompilará.ComoaclasseThread sabequedeve chamarométodoroda?Comoelasabequenomedemétododaremosequeeladevechamaressemétodoespecial?FaltanaverdadeumcontratoentreasnossasclassesaseremexecutadaseaclasseThread.
EssecontratoexisteeéfeitopelainterfaceRunnable:devemosdizerquenossaclasseé"executável"e que segue esse contrato. Na interface Runnable, há apenas um método chamado run. Bastaimplementá-lo,"assinar"ocontratoeaclasseThreadjásaberáexecutarnossaclasse.
publicclassGeraPDFimplementsRunnable{publicvoidrun(){//lógicaparageraropdf...}}
publicclassBarraDeProgressoimplementsRunnable{publicvoidrun(){//mostrabarradeprogressoevaiatualizandoela...}}
AclasseThread recebe no construtor umobjeto que éumRunnable, e seumétodo startchamaométodorundanossaclasse.ReparequeaclasseThreadnãosabequaléotipoespecíficodanossaclasse;paraela,bastasaberqueaclassesegueocontratoestabelecidoepossuiométodorun.
Éobomusodeinterfaces,contratosepolimorfismonaprática!
.
ESTENDENDOACLASSETHREAD
A classe Thread implementa Runnable . Então, você pode criar uma subclasse dela ereescreverorunque,naclasseThread,nãofaznada:
publicclassGeraPDFextendsThread{publicvoidrun(){//...}}
E,comonossaclasseéumaThread,podemosusarostartdiretamente:
GeraPDFgera=newGeraPDF();gera.start();
Apesar de ser um código mais simples, você está usando herança apenas por "preguiça"(herdamosummontedemétodosmasusamosapenasorun),enãoporpolimorfismo,queseriaagrandevantagem.PrefiraimplementarRunnableaherdardeThread.
DORMINDO
Paraque a threadatualdurmabasta chamarométodoa seguir,por exemplo,paradormir3segundos:
javaThread.sleep(3*1000);
.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
Vejaaclasseaseguir:
publicclassProgramaimplementsRunnable{
privateintid;//colocargetteresetterproatributoid
publicvoidrun(){for(inti=0;i<10000;i++){System.out.println("Programa"+id+"valor:"+i);}}}
Éumaclasseque implementaRunnable e,nométodorun, apenas imprimedezmil números.Vamosusá-lasduasvezesparacriarduasthreadseimprimirosnúmerosduasvezessimultaneamente:
publicclassTeste{publicstaticvoidmain(String[]args){
Programap1=newPrograma();p1.setId(1);
Threadt1=newThread(p1);t1.start();
Programap2=newPrograma();p2.setId(2);
Threadt2=newThread(p2);t2.start();
SaberinglêsémuitoimportanteemTI
18.2ESCALONADORETROCASDECONTEXTO
.
}}
Serodarmosesseprograma,qual seráasaída?Deumamiledepoisdeumamil?Provavelmentenão, senão seria sequencial. Ele imprimirá 0 de t1, 0 de t2, 1 de t1, 1 de t2, 2 de t1, 2 de t2 e etc?Exatamenteintercalado?
Naverdade,não sabemos exatamentequal é a saída.Rodeoprogramavárias vezes eobserve: emcadaexecuçãoasaídaéumpoucodiferente.
Oproblemaéquenocomputadorexisteapenasumprocessadorcapazdeexecutarcoisas.Equandoqueremosexecutarváriascoisasaomesmotempo,eoprocessadorsóconseguefazerumacoisadecadavez?Entraemcenaoescalonadordethreads.
O escalonador (scheduler), sabendo que apenas uma coisa pode ser executada de cada vez, pegatodasas threadsqueprecisamser executadas e fazoprocessador ficar alternandoa execuçãodecadauma delas. A ideia é executar um pouco de cada thread e fazer essa troca tão rapidamente que aimpressãoqueficaéqueascoisasestãosendofeitasaomesmotempo.
Oescalonadoréresponsávelporescolherqualapróximathreadaserexecutadaefazeratrocadecontexto (context switch).Eleprimeiro salvaoestadodaexecuçãoda threadatualparadepoispoderretomar a execução da mesma. Aí ele restaura o estado da thread que vai ser executada e faz oprocessadorcontinuaraexecuçãodesta.Depoisdeumcertotempo,estathreadétiradadoprocessador,seuestado(ocontexto)ésalvoeoutrathreadécolocadaemexecução.Atrocadecontextoéjustamenteas operações de salvar o contexto da thread atual e restaurar o da thread que vai ser executada emseguida.
Quando fazer a troca de contexto, por quanto tempo a thread vai rodar e qual vai ser a próximathread a ser executada, são escolhas do escalonador. Nós não controlamos essas escolhas (emborapossamosdar"dicas"aoescalonador).Porissoquenuncasabemosaocertoaordememqueprogramasparalelossãoexecutados.
Vocêpodepensarqueéruimnãosaberaordem.Maspercebaqueseaordemimportaparavocê,seé importantequedeterminadacoisaseja feitaantesdeoutra,entãonãoestamos falandodeexecuçõesparalelas,massimdeumprogramasequencialnormal(ondeumacoisaéfeitadepoisdaoutra,emumasequência).
Todo esse processo é feito automaticamente pelo escalonador do Java (e,mais amplamente, peloescalonador do sistema operacional). Para nós, programadores das threads, é como se as coisasestivessemsendoexecutadasaomesmotempo.
.
EEMMAISDEUMPROCESSADOR?
AVMdoJavaeamaioriadosSOsmodernosconseguefazerproveitodesistemascomváriosprocessadoresoumulti-core.Adiferençaéqueagora temosmaisdeumprocessadorexecutandocoisaseteremos,sim,execuçõesverdadeiramenteparalelas.
MasonúmerodeprocessosnoSOeonúmerodeThreadsparalelascostumamsertãograndesque, mesmo com vários processadores, temos as trocas de contexto. A diferença é que oescalonadortemdoisoumaisprocessadoresparaexecutarsuasthreads.Masdificilmenteteráumamáquinacommaisprocessadoresquethreadsparalelasexecutando.
OGarbageCollector(coletordelixo, lixeiro)funcionacomoumaThread responsávelpor jogarfora todos os objetos que não estão sendo referenciados por nenhum outro objeto - seja demaneiradiretaouindireta.
Considereocódigo:
Contaconta1=newContaCorrente();Contaconta2=newContaCorrente();
Atéestemomento,sabemosquetemos2objetosemmemória.Aqui,oGarbageCollectornãopodeeliminarnenhumdosobjetos,poisaindatemalguémsereferindoaelesdealgumaforma.
Podemos, então, executar uma linha que nos faça perder a referência para um dos dois objetoscriados,como,porexemplo,oseguintecódigo:
conta2=conta1;
Quantosobjetostemosemmemória?
Perdemosareferênciaparaumdosobjetosqueforamcriados.Esseobjeto jánãoémaisacessível.Temos,então,apenasumobjetoemmemória?Nãopodemosafirmarisso!ComooGarbageCollectoréumaThread,vocênãotemgarantiadequandoelevairodar.Vocêsósabeque,emalgummomentonofuturo,aquelamemóriavaiserliberada.
Algumaspessoascostumamatribuirnullaumavariável,comointuitodeacelerarapassagemdoGarbageCollectorporaqueleobjeto:
for(inti=0;i<100;i++){Listx=newArrayList();//fazalgumascoisascomaarraylistx=null;}
18.3GARBAGECOLLECTOR
.
Isso rarissimamente é necessário. O Garbage Collector age apenas sobre objetos, nunca sobrevariáveis.Nessecaso,avariávelxnãoexistirámaisacadaiteração,deixandoaArrayListcriadasemnenhumareferênciaparaela.
SYSTEM.GC()
Vocênunca consegue forçar oGarbageCollector,mas chamandoométodo estáticogc daclasseSystem, você está sugerindo que a Virtual Machine rode o Garbage Collector naquelemomento.Sesuasugestãovaiseraceitaounão, istodependedeJVMparaJVM,evocênãotemgarantias. Evite o uso destemétodo.Você não deve basear sua aplicação em quando oGarbageCollectorvairodarounão.
FINALIZER
A classe Object define também ummétodo finalize, que você pode reescrever. Essemétodo será chamado no instante antes do Garbage Collector coletar este objeto. Não é umdestrutor, você não sabe em quemomento ele será chamado. Algumas pessoas o utilizam paraliberar recursos "caros"comoconexões, threadse recursosnativos. Issodeve serutilizadoapenasporsegurança:oidealéliberaressesrecursosomaisrápidopossível,semdependerdapassagemdoGarbageCollector.
1. Testeoexemplodestecapítuloparaimprimirnúmerosemparalelo.
EscrevaaclassePrograma:
publicclassProgramaimplementsRunnable{
privateintid;//colocargetteresetterproatributoid
publicvoidrun(){for(inti=0;i<10000;i++){System.out.println("Programa"+id+"valor:"+i);}}}
EscrevaaclassedeTeste:
publicclassTeste{publicstaticvoidmain(String[]args){
18.4EXERCÍCIOS
.
Programap1=newPrograma();p1.setId(1);
Threadt1=newThread(p1);t1.start();
Programap2=newPrograma();p2.setId(2);
Threadt2=newThread(p2);t2.start();
}}
RodeváriasvezesaclasseTesteeobserveosdiferentesresultadosemcadaexecução.Oquemuda?
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
É comum aparecer uma classe anônima junto com uma thread. Vimos como usá-la com oComparator.VamosvercomousaremumRunnable.
ConsidereumRunnablesimples,queapenasmandaimprimiralgonasaídapadrão:
publicclassPrograma1implementsRunnable{publicvoidrun(){for(inti=0;i<10000;i++){System.out.println("Programa1valor:"+i);}}}
Noseumain,vocêfaz:
AprendasedivertindonaAluraStart!
18.5EASCLASSESANÔNIMAS?
.
Runnabler=newPrograma1();Threadt=newThread(r);t.start();
Em vez de criar essa classe Programa1, podemos utilizar o recurso de classe anônima. Ela nospermitedarnewnumainterface,desdequeimplementemosseusmétodos.Comisso,podemoscolocardiretamentenomain:
Runnabler=newRunnable(){publicvoidrun(){for(inti=0;i<10000;i++)System.out.println("programa1valor"+i);}};Threadt=newThread(r);t.start();
LIMITAÇÕESDASCLASSESANÔNIMAS
O uso de classes anônimas tem limitações. Não podemos declarar um construtor. Comoestamosinstanciandoumainterface,entãonãoconseguimospassarumparâmetroparaela.Comoentão passar o id como argumento? Você pode, de dentro de uma classe anônima, acessaratributos da classe dentro da qual foi declarada! Também pode acessar as variáveis locais dométodo,desdequeelessejamfinal.
Dá para ir mais longe com o Java 8, utilizando o lambda. Como Runnable é uma interfacefuncional(contémapenasummétodoabstrato),elapodeserfacilmenteescritadessaforma:
Runnabler=()->{for(inti=0;i<10000;i++)System.out.println("programa1valor"+i);};Threadt=newThread(r);t.start();
A sintaxepode serumpouco estranha.Comonãoháparâmetros a serem recebidospelométodorun, usamoso() para indicar isso.Vale lembrar,maisumavez, queno lambdanãoprecisamosescreveronomedométodoqueestamos implementando,nonossocasoorun. Isso é possível poisexisteapenasummétodoabstratonainterface.
Querdeixarocódigomaisenxutoainda?PodemospassarolambdadiretamenteparaoconstrutordeThread,semcriarumavariáveltemporária!Elogoemseguidachamarostart:
newThread(()->{for(inti=0;i<10000;i++)System.out.println("programa1valor"+i);}).start();
EcomlambdadoJava8?
.
Obviamente o uso excessivo de lambdas e classes anônimas pode causar uma certa falta delegibilidade.Você deve lembrar que usamos esses recursos para escrever códigosmais legíveis, e nãoapenas para poupar algumas linhas de código.Caso nossa implementação do lambda venha a ser deváriaslinhas,éumfortesinaldequedeveríamosterumaclasseapartesomenteparaela.
.
CAPÍTULO19
"Olhoporolho,eomundoacabarácego."--MohandasGandhi
Conectando-seamáquinasremotas.
Nestecapítulo,vocêvaiconheceraAPIdeSocketsdojavapelopacotejava.net.
Mais útil que conhecer a API, é você perceber que estamos usando, aqui, todos os conceitos ebibliotecas aprendidas durante os outros capítulos. Repare, também, que é relativamente simplesaprenderautilizarumaAPI,agoraquetemostodososconceitosnecessáriosparatal.
Lembre-sedefazeresseapêndicecomojavadocabertoaoseulado.
AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,
Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno daCaelumtem15%dedescontonestelink!
ConheçaoscursosonlineAlura.
Da necessidade de dois computadores se comunicarem, surgiram diversos protocolos quepermitissemtaltrocadeinformação:oprotocoloquevamosusaraquiéoTCP(TransmissionControlProtocol).
AtravésdoTCP,épossívelcriarumfluxoentredoiscomputadores-comoémostradonodiagrama
APÊNDICE-SOCKETS
19.1MOTIVAÇÃO:UMAAPIQUEUSAOSCONCEITOSAPRENDIDOS
JáconheceoscursosonlineAlura?
19.2PROTOCOLO
.
abaixo:
É possível conectarmais de um cliente aomesmo servidor, como é o caso de diversos banco dedados,servidoresWeb,etc.
Ao escrever um programa em Java que se comunique com outra aplicação, não é necessário sepreocupar com um nível tão baixo quanto o protocolo. As classes que trabalham com eles já foramdisponibilizadasparaseremusadaspornósnopacotejava.net.
A vantagemde se usar TCP, em vez de criar nosso próprio protocolo de bytes, é que oTCP vaigarantir a entrega dos pacotes que transferirmos e criar um protocolo base para isto é algo bemcomplicado.
Acabamosdemencionarquediversoscomputadorespodemseconectaraumsó,mas,narealidade,émuito comum encontrarmáquinas clientes com uma só conexão física. Então, como é possível seconectaradoispontos?Comoépossívelserconectadopordiversospontos?
Todas as aplicações que estão enviando e recebendodados fazem isso através damesma conexãofísica, mas o computador consegue discernir, durante a chegada de novos dados, quais informaçõespertencemaqualaplicação.Mascomo?
19.3PORTA
.
AssimcomoexisteoIPparaidentificarumamáquina,aportaéasoluçãoparaidentificardiversasaplicaçõesemumamáquina.Estaportaéumnúmerode2bytes,variade0a65535.Setodasasportasdeumamáquinaestiveremocupadas,nãoépossívelseconectaraelaenquantonenhumaforliberada.
Ao configurar um servidor para rodar na porta 80 (padrão http), é possível se conectar a esseservidoratravésdessaportaque, juntocomo ip, vai formaro endereçodaaplicação.Por exemplo,oservidorwebdacaelum.com.brpodeserrepresentadopor:caelum.com.br:80
Masseumclienteseconectaaumprogramarodandonaporta80deumservidor,enquantoelenãosedesconectardessaporta,seráimpossívelqueoutrapessoaseconecte?
Acontece que, ao efetuar e aceitar a conexão, o servidor redireciona o cliente de uma porta paraoutra,liberandonovamentesuaportainicialepermitindoqueoutrosclientesseconectemnovamente.
EmJava,issodeveserfeitoatravésdethreadseoprocessodeaceitaraconexãodeveserrodadoomaisrápidopossível.
19.4SOCKET
.
NaAlura Língua você reforça e aprimora seuinglês! Usando a técnica Spaced Repetitions oaprendizado naturalmente se adapta ao seuconhecimento. Exercícios e vídeos interativosfazem com que você pratique em situações
cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entendercompletamente o que está aprendendo. Aprender inglês é fundamental para o profissional detecnologiadesucesso!
PratiqueseuinglêsnaAluraLíngua.
Iniciandoummodelodeservidordechat,oserviçodocomputadorquefuncionacomobasedeve,primeiro,abrirumaportaeficarouvindoatéalguémtentarseconectar.
importjava.net.*;
publicclassServidor{publicstaticvoidmain(String[]args)throwsIOException{
ServerSocketservidor=newServerSocket(12345);System.out.println("Porta12345aberta!");//acontinuaçãodoservidordeveserescritaaqui
}}
Seoobjeto for realmente criado, significaque aporta 12345 estava fechada e foi aberta. Seoutroprogramapossuiocontroledestaportanesteinstante,énormalqueonossoexemplonãofuncione,poiselenãoconsegueutilizarumaportaquejáestáemuso.
Após abrir a porta, precisamos esperar por um cliente através do método accept daServerSocket.Assimqueumclienteseconectar,oprogramacontinuará,porissodizemosqueessemétodoéblocante,seguraathreadatéquealgoonotifique.
Socketcliente=servidor.accept();System.out.println("Novaconexãocomocliente"+cliente.getInetAddress().getHostAddress());//imprimeoipdocliente
Porfim,bastalertodasasinformaçõesqueoclientenosenviar:
SaberinglêsémuitoimportanteemTI
19.5SERVIDOR
.
Scannerscanner=newScanner(cliente.getInputStream());
while(scanner.hasNextLine()){System.out.println(scanner.nextLine());}
Fechamosasconexões,começandopelofluxo:
in.close();cliente.close();servidor.close();
Oresultadoéaclasseaseguir:
publicclassServidor{publicstaticvoidmain(String[]args)throwsIOException{ServerSocketservidor=newServerSocket(12345);System.out.println("Porta12345aberta!");
Socketcliente=servidor.accept();System.out.println("Novaconexãocomocliente"+cliente.getInetAddress().getHostAddress());
Scanners=newScanner(cliente.getInputStream());while(s.hasNextLine()){System.out.println(s.nextLine());}
s.close();servidor.close();cliente.close();}}
Anossatarefaécriarumprogramaclientequeenviemensagensparaoservidor...oclienteéaindamaissimplesdoqueoservidor.
O código a seguir é a parte principal e tenta se conectar a um servidorno IP 127.0.0.1 (máquinalocal)eporta12345:
Socketcliente=newSocket("127.0.0.1",12345);System.out.println("Oclienteseconectouaoservidor!");
Queremoslerosdadosdocliente,daentradapadrão(teclado):
Scannerteclado=newScanner(System.in);while(teclado.hasNextLine()){//lêalinhaefazalgocomela}
Bastaleraslinhasqueousuáriodigitaratravésdobufferdeentrada(in),e jogá-lasnobufferdesaída:
PrintStreamsaida=newPrintStream(cliente.getOutputStream());
19.6CLIENTE
.
Scannerteclado=newScanner(System.in);while(teclado.hasNextLine()){saida.println(teclado.nextLine());}saida.close();teclado.close();
Reparequeusamosos conceitodejava.io aquinovamente, para leiturado teclado e enviodemensagensparaoservidor.ParaasclassesScannerePrintStream, tantofazdeondequese lêouescreveosdados:oimportanteéqueessestreamsejaumInputStream/OutputStream.Éopoderdasinterfaces,dopolimorfismo,aparecendonovamente.
Nossoprogramafinal:
publicclassCliente{publicstaticvoidmain(String[]args)throwsUnknownHostException,IOException{Socketcliente=newSocket("127.0.0.1",12345);System.out.println("Oclienteseconectouaoservidor!");
Scannerteclado=newScanner(System.in);PrintStreamsaida=newPrintStream(cliente.getOutputStream());
while(teclado.hasNextLine()){saida.println(teclado.nextLine());}
saida.close();teclado.close();cliente.close();}}
Paratestarosistema,precisamosrodarprimeirooservidore,logodepois,ocliente.Tudooquefordigitadonoclienteseráenviadoparaoservidor.
.
MULTITHREADING
Paraqueoservidorsejacapazdetrabalharcomdoisclientesaomesmotempoénecessáriocriarumathreadlogoapósexecutarométodoaccept.
A threadcriadaseráresponsávelpelo tratamentodessaconexão,enquantoo laçodoservidordisponibilizaráaportaparaumanovaconexão:
while(true){
Socketcliente=servidor.accept();
//criaumobjetoquevaitrataraconexãoTratamentoClasstratamento=newTratamentoClass(cliente);
//criaathreademcimadesteobjetoThreadt=newThread(tratamento);
//iniciaathreadt.start();
}
AsocketdoclientetemumInputStream,querecebedoOutputStreamdoservidor,e temumOutputStream, que transfere tudo para o InputStream do servidor. Muito parecido com umtelefone!
Reparequeclienteeservidorsãorótulosqueindicamumestado.Ummicro(oumelhor,umaJVM)podeserservidornumcaso,maspodeserclienteemoutrocaso.
19.7IMAGEMGERAL
.
Você conhece alguém que tem potencial paratecnologia e programação, mas que nuncaescreveuumalinhadecódigo?Podeserumfilho,sobrinho, amigo ou parente distante. NaAlura
Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada comprogramaçãoeaportadeentradaparaumapossívelcarreiradesucesso.Elavaiestudaremseupróprioritmoecomamelhordidática.AqualidadedaconceituadaAlura,agoraparaStarters.
ConheçaoscursosonlinedaAluraStart!
1. Crieumprojetosockets.
Vamosfazerumpequenosistemaemquetudoqueédigitadonomicroclienteacabaaparecendonomicroservidor.Istoé,apenasumacomunicaçãounidirecional.
CrieaclasseServidorcomovimosnessecapítulo.AbusedosrecursosdoEclipseparanãoterdeescrevermuito!
packagebr.com.caelum.chat;
importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;importjava.util.Scanner;
publicclassServidor{publicstaticvoidmain(String[]args)throwsIOException{ServerSocketservidor=newServerSocket(12345);System.out.println("Porta12345aberta!");
Socketcliente=servidor.accept();System.out.println("Novaconexãocomocliente"+cliente.getInetAddress().getHostAddress());
Scannerentrada=newScanner(cliente.getInputStream());while(entrada.hasNextLine()){System.out.println(entrada.nextLine());}
entrada.close();servidor.close();}}
AprendasedivertindonaAluraStart!
19.8EXERCÍCIOS:SOCKETS
.
2. CrieaclasseClientecomovistaanteriormente:
packagebr.com.caelum.chat;
importjava.io.IOException;importjava.io.PrintStream;importjava.net.Socket;importjava.net.UnknownHostException;importjava.util.Scanner;
publicclassCliente{publicstaticvoidmain(String[]args)throwsUnknownHostException,IOException{Socketcliente=newSocket("127.0.0.1",12345);System.out.println("Oclienteseconectouaoservidor!");
Scannerteclado=newScanner(System.in);PrintStreamsaida=newPrintStream(cliente.getOutputStream());
while(teclado.hasNextLine()){saida.println(teclado.nextLine());}
saida.close();teclado.close();}}
Utilizedosquickfixesecontrolespaçoparaosimportseothrows.
3. RodeaclasseServidor:reparenoconsoledoEclipsequeoprogramaficaesperando.RodeaclasseCliente:aconexãodeveserfeitaeoEclipsedevemostrarosdoisconsolesparavocê(existeumpequenoíconenaviewdeConsoleparavocêalternarentreeles).
Digitemensagensnoclienteevejaseelasaparecemcorretamentenoservidor.
4. Testeseuprogramacomumcolegadocurso,usandocomunicaçãoremotaentreasduasmáquinas.Combinementresiquemvairodaroclienteequemvairodaroservidor.Quemforrodaroclientedeve editar o IP na classe para indicar o endereço da outramáquina (verifique também se estãoacessandoamesmaporta).
DESCOBRINDOOIPDAMÁQUINA
NoWindows,abraoconsoleedigiteipconfigparasaberqualéoseuIP.NoLinux(ounoBSD,Mac,Solaris),vánoconsoleedigiteifconfig.
5. (opcional)Esevocêquisesse,emvezdeenviartudooqueoclientedigitou,transferirumarquivotextodomicrodoclienteparaservidor?Seriadifícil?
Abusedopolimorfismo!Façaocliente lerdeumarquivochamadoarquivo.txt (crie-o!)e faça
.
comqueoservidorgravetudoquerecebenumarquivoquechamarecebido.txt.
Quandooservidoraceitaumclientecomachamadaaoaccept, ele poderia chamarnovamenteeste método para aceitar um novo cliente. E, se queremos aceitar vários clientes, simultâneos, bastachamaroacceptváriasvezesetratarcadaclienteemsuaprópriaThread(senãoométodoacceptnãoseráinvocadonovamente!).
UmesboçodesoluçãoparaaclasseServidor:
ServerSocketservidor=newServerSocket(12345);
//servidorficaeternamenteaceitandoclientes...while(true){Socketcliente=servidor.accept();//disparaumaThreadquetrataesseclienteejáesperaopróximo}
[TODO:serialegalessasoluçãoparcialparaapenasessaparte!]
Agora que vários clientes podemmandar mensagens, gostaríamos que os clientes recebessem asmensagensenviadaspelasoutraspessoas.Aoinvésdoservidorsimplesmenteescreverasmensagensnoconsole,eledevemandarcadamensagemparatodososclientesconectados.
Precisamosmanterumalistadeclientesconectadose,quandochegarumamensagem(dequalquercliente),percorremosessalistaemandamosparatodos.
UseumListparaguardarosPrintStreamsdosclientes.Logodepoisqueoservidoraceitarumcliente novo, crie um PrintStream usando o OutputStream dele e adicione na lista. E, quandoreceberumamensagemnova,enviaparatodosnalista.
Umesboço:
Adicionandonalista:
while(true){Socketcliente=servidor.accept();this.lista.add(newPrintStream(cliente.getOutputStream()));
//disparaumaThreadquetrataesseclienteejáesperaopróximo}
Métodoquedistribuiasmensagens:
voiddistribuiMensagem(Stringmsg){for(PrintStreamcliente:lista){cliente.println(msg);
19.9DESAFIO:MÚLTIPLOSCLIENTES
19.10DESAFIO:BROADCASTDASMENSAGENS
.
}}
Masnossoclientetambémrecebemensagens.EntãoprecisamosfazercomqueoCliente,alémdelermensagensdotecladoeenviarparaoservidor,simultaneamentetambémpossarecebermensagensdeoutrosclientesenviadaspeloservidor.
Ouseja,precisamosdeumasegundaThreadnaclasseClientequeficarecebendomensagensdoInputStreamdoservidoreimprimindonoconsole.
Umesboço:
Scannerservidor=newScanner(cliente.getInputStream());while(servidor.hasNextLine()){System.out.println(servidor.nextLine());}
Lembre que você precisará de no mínimo 2 threads para o cliente e 2 para o servidor. Entãoprovavelmentevocêvaiterqueescrever4classes.
Melhoriaspossíveis:
Façacomoaprimeiralinhaenviadapeloclientesejasempreonickdele.Equandooservidorenviaramensagem,façaeleenviaronickdecadaclienteantesdamensagem.
Equandoumclientedesconectar?Comoretirá-lodalista?
Édifícil fazeroenviodearquivospelonossosistemadechats?Sabendoquea leituradeumarquivo é feita pelo FileInputStream , seria difícil mandar esse InputStream peloOutputStreamdaconexãoderede?
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
Seuslivrosdetecnologiaparecemdoséculopassado?
19.11SOLUÇÃODOSISTEMADECHAT
.
Umasoluçãoparao sistemadechatcliente-servidorcommúltiplosclientespropostonosdesafiosacima. Repare que a solução não está nem um pouco elegante: o main já faz tudo, além de nãotratarmosasexceptions.OcódigovisaapenasmostrarousodeumaAPI.Éumapéssimapráticacolocartodaafuncionalidadedoseuprogramanomainetambémdejogarexceçõesparatrás.
Nestalistagem,faltamosdevidosimports.
Primeiro, as duas classes para o cliente. Repare que a única mudança grande é a classe nova,Recebedor:
publicclassCliente{publicstaticvoidmain(String[]args)throwsUnknownHostException,IOException{//disparaclientenewCliente("127.0.0.1",12345).executa();}
privateStringhost;privateintporta;
publicCliente(Stringhost,intporta){this.host=host;this.porta=porta;}
publicvoidexecuta()throwsUnknownHostException,IOException{Socketcliente=newSocket(this.host,this.porta);System.out.println("Oclienteseconectouaoservidor!");
//threadpararecebermensagensdoservidorRecebedorr=newRecebedor(cliente.getInputStream());newThread(r).start();
//lêmsgsdotecladoemandaproservidorScannerteclado=newScanner(System.in);PrintStreamsaida=newPrintStream(cliente.getOutputStream());while(teclado.hasNextLine()){saida.println(teclado.nextLine());}
saida.close();teclado.close();cliente.close();}}
publicclassRecebedorimplementsRunnable{
privateInputStreamservidor;
publicRecebedor(InputStreamservidor){this.servidor=servidor;}
publicvoidrun(){//recebemsgsdoservidoreimprimenatelaScanners=newScanner(this.servidor);while(s.hasNextLine()){System.out.println(s.nextLine());
.
}}}
JáoServidorsofreubastantemodificações.AclasseTrataClienteéaresponsávelporcuidardecadaclienteconectadonosistema:
publicclassServidor{
publicstaticvoidmain(String[]args)throwsIOException{//iniciaoservidornewServidor(12345).executa();}
privateintporta;privateList<PrintStream>clientes;
publicServidor(intporta){this.porta=porta;this.clientes=newArrayList<PrintStream>();}
publicvoidexecuta()throwsIOException{ServerSocketservidor=newServerSocket(this.porta);System.out.println("Porta12345aberta!");
while(true){//aceitaumclienteSocketcliente=servidor.accept();System.out.println("Novaconexãocomocliente"+cliente.getInetAddress().getHostAddress());
//adicionasaidadoclienteàlistaPrintStreamps=newPrintStream(cliente.getOutputStream());this.clientes.add(ps);
//criatratadordeclientenumanovathreadTrataClientetc=newTrataCliente(cliente.getInputStream(),this);newThread(tc).start();}
}
publicvoiddistribuiMensagem(Stringmsg){//enviamsgparatodomundofor(PrintStreamcliente:this.clientes){cliente.println(msg);}}}
publicclassTrataClienteimplementsRunnable{
privateInputStreamcliente;privateServidorservidor;
publicTrataCliente(InputStreamcliente,Servidorservidor){this.cliente=cliente;this.servidor=servidor;}
.
publicvoidrun(){//quandochegarumamsg,distribuipratodosScanners=newScanner(this.cliente);while(s.hasNextLine()){servidor.distribuiMensagem(s.nextLine());}s.close();}}
.
CAPÍTULO20
"Quempoucopensa,engana-semuito."--LeonardodaVinci
OusodeThreadscomeçaaficarinteressanteecomplicadoquandoprecisamoscompartilharobjetosentreváriasThreads.
Imagineaseguintesituação: temosumBancocommilhõesdeContasBancárias.Clientessacamedepositamdinheiro continuamente, 24 horas por dia.No primeiro dia de cadamês, o Banco precisaatualizar o saldo de todas as Contas de acordo com uma taxa específica. Para isso, ele utiliza oAtualizadorDeContasquevimosanteriormente.
OAtualizadorDeContas,basicamente,pegaumaaumacadaumadasmilhõesdecontasechamaseumétodoatualiza.Aatualizaçãodemilhõesdecontaséumprocessodemorado,quedurahoras;éinviávelpararobancoportantotempoatéqueasatualizaçõestenhamcompletado.Éprecisoexecutarasatualizaçõesparalelamenteàsatividades,dedepósitosesaques,normaisdobanco.
Ouseja,teremosváriasthreadsrodandoparalelamente.Emumathread,pegamostodasascontasevamoschamandoométodoatualizadecadauma.Emoutra,podemosestarsacandooudepositandodinheiro.Estamoscompartilhandoobjetosentremúltiplasthreads(ascontas,nonossocaso).
Imagineaseguintepossibilidade(mesmoquemuitoremota):noexatoinstanteemqueoatualizadorestáatualizandoumaContaX,oclientedonodestaContaresolveefetuarumsaque.Comosabemos,aotrabalharcomThreads,oescalonadorpodepararumacertaThreadaqualquer instanteparaexecutaroutra,evocênãotemcontrolesobreisso.
VejaessaclasseConta:
publicclassConta{
privatedoublesaldo;
//outrosmétodoseatributos...
publicvoidatualiza(doubletaxa){doublesaldoAtualizado=this.saldo*(1+taxa);
APÊNDICE-PROBLEMASCOMCONCORRÊNCIA
20.1THREADSACESSANDODADOSCOMPARTILHADOS
.
this.saldo=saldoAtualizado;}
publicvoiddeposita(doublevalor){doublenovoSaldo=this.saldo+valor;this.saldo=novoSaldo;}}
ImagineumaContacomsaldode100reais.Umclienteentranaagênciaefazumdepósitode1000reais.IssodisparaumaThreadnobancoquechamaométododeposita();elecomeçacalculandoonovoSaldo que passa a ser 1100 (linha 13). Só que por algum motivo que desconhecemos, oescalonadorpáraessathread.
Nesteexatoinstante,elecomeçaaexecutarumaoutraThreadquechamaométodoatualizadamesmaConta,porexemplo,comtaxade1%.IssoquerdizerqueonovoSaldopassaavaler101reais(linha8).E,nesseinstanteoescalonadortrocadeThreadsnovamente.Eleexecutaalinha14naThreadquefaziaodepósito;osaldopassaavaler1100.Acabandoodeposita,oescalonadorvoltapraThreaddoatualizaeexecutaalinha9,fazendoosaldovaler101reais.
Resultado:odepósitodemilreaisfoitotalmenteignoradoeseuClienteficarápoucofelizcomisso.Perceba quenão é possível detectar esse erro, já que todo o código foi executadoperfeitamente, semproblemas.Oproblema,aqui,foioacessosimultâneodeduasThreadsaomesmoobjeto.
EoerrosóocorreuporqueoescalonadorparounossasThreadsnaquelesexatos lugares.Podeserquenossocódigofiquerodando1anosemdarproblemaalgumeemumbelodiaoescalonadorresolvealternar nossas Threads daquela forma. Não sabemos como o escalonador se comporta! Temos queprotegernossocódigocontraesse tipodeproblema.Dizemosqueessaclassenãoé threadsafe, issoé,nãoestáprontaparaterumainstânciautilizadaentreváriasthreadsconcorrentemente.
OquequeríamoseraquenãofossepossívelalguématualizaraContaenquantooutrapessoaestádepositandoumdinheiro.QueríamosqueumaThreadnãopudessemexeremumaConta enquantooutraThreadestámexendonela.Nãohácomoimpediroescalonadordefazertalescolha.Então,oquefazer?
.
Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.
CasadoCódigo,LivrosdeTecnologia.
Uma ideia seria criar uma trava e, no momento em que uma Thread entrasse em um dessesmétodos,ela trancariaaentradacomumachave.Dessamaneira,mesmoquesendocolocadade lado,nenhumaoutraThreadpoderiaentrarnessesmétodos,poisachaveestariacomaoutraThread.
Essaideiaéchamadaderegiãocrítica.Éumpedaçodecódigoquedefinimoscomocríticoequenãopodeserexecutadoporduasthreadsaomesmotempo.Apenasumathreadporvezconsegueentraremalgumaregiãocrítica.
PodemosfazerissoemJava.Podemosusarqualquerobjetocomoumlock(trava,chave),parapodersincronizar em cimadesse objeto, isto é, se umaThread entrar emumbloco que foi definido comosincronizadoporesse lock,apenasumaThreadpoderáestar ládentroaomesmotempo,poisachaveestarácomela.
Apalavrachavesynchronizeddáessacaracterísticaaumblocodecódigoerecebequaléoobjetoqueseráusadocomochave.AchavesóédevolvidanomomentoemqueaThreadquetinhaessachavesair do bloco, seja por return ou disparo de uma exceção (ou ainda na utilização do métodowait())..
Queremos,então,bloquearoacessosimultâneoaumamesmaConta:
publicclassConta{
privatedoublesaldo;
//outrosmétodoseatributos...
publicvoidatualiza(doubletaxa){synchronized(this){doublesaldoAtualizado=this.saldo*(1+taxa);this.saldo=saldoAtualizado;
Seuslivrosdetecnologiaparecemdoséculopassado?
20.2CONTROLANDOOACESSOCONCORRENTE
.
}}
publicvoiddeposita(doublevalor){synchronized(this){doublenovoSaldo=this.saldo+valor;this.saldo=novoSaldo;}}}
Observeousodosblocossynchronized dentrodosdoismétodos.Eles bloqueiamumaThreadutilizandoomesmoobjetoConta,othis.
Essesmétodossãomutuamenteexclusivosesóexecutamdemaneiraatômica.Threadsquetentampegarumlockquejáestápego,ficarãoemumconjuntoespecialesperandopelaliberaçãodolock(nãonecessariamentenumafila).
SINCRONIZANDOOBLOCOINTEIRO
Écomumsempresincronizarmosummétodointeiro,normalmenteutilizandoothis.
publicvoidmetodo(){synchronized(this){//conteúdodometodo}}
Paraestemesmoefeito,existeumasintaxemaissimples,ondeosynchronizedpodeserusadocomomodificadordométodo:
publicsynchronizedvoidmetodo(){//conteúdodometodo}
MAISSOBRELOCKS,MONITORESECONCORRÊNCIA
Se ométodo for estático, será sincronizado usando o lock do objeto que representa a classe(NomeDaClasse.class).
Alémdisso,opacotejava.util.concurrent,conhecidocomoJUC,entrounoJava5.0parafacilitarumasériedetrabalhoscomunsquecostumamapareceremumaaplicaçãoconcorrente.
Essepacoteajudaatémesmocriarthreadsepooldethreads,atravésdosExecutors.
20.3VECTOREHASHTABLE
.
Duas collections muito famosas são Vector e Hashtable, a diferença delas com suas irmãsArrayListeHashMapéqueasprimeirassãothreadsafe.
Vocêpodeseperguntarporquenãousamossempreessasclassesthreadsafe.Adquirirumlocktemumcusto,ecasoumobjetonãováserusadoentrediferentesthreads,nãoháporqueusaressasclassesqueconsomemmaisrecursos.Masnemsempreéfácilenxergarsedevemossincronizarumbloco,ousedevemosutilizarblocossincronizados.
Antigamenteocustodeseusar lockseraaltíssimo,hojeemdia issocustapoucoparaaJVM,masnãoémotivoparavocêsincronizartudosemnecessidade.
VocêpodemudaraprioridadedecadaumadesuasThreads,masistotambéméapenasumasugestãoaoescalonador.
ExisteummétodostopnasThreads,porquenãoéboapráticachamá-lo?
Um tópicomais avançado é a utilização dewait,notifiy e notifyAll para que asThreadscomuniquem-sedeeventosocorridos,indicandoquepodemounãopodemavançardeacordocomcondições
O pacote java.util.concurrent foi adicionado no Java 5 para facilitar o trabalho naprogramação concorrente. Ele possui uma série de primitivas para que você não tenha detrabalhardiretamentecomwaitenotify,alémdeterdiversascoleçõesthreadsafe.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
Exercícios só recomendados se você já tinha algum conhecimento prévio de programação
20.4UMPOUCOMAIS...
Agoraéamelhorhoraderespirarmaistecnologia!
20.5EXERCÍCIOSAVANÇADOSDEPROGRAMAÇÃOCONCORRENTEELOCKS
.
concorrente,locks,etc.
1. Vamosenxergaroproblemaaoseusarumaclassequenãoéthread-safe:aArrayListporexemplo.
Imaginequetemosumobjetoqueguardatodasasmensagensqueumaaplicaçãodechatrecebeu.VamosusarumaArrayList<String> para armazená-las.Nossa aplicação émulti-thread, entãodiferentes threads vão inserir diferentesmensagens para serem registradas.Não importa a ordemqueelassejamguardadas,desdequeelasumdiasejam!
Vamosusaraseguinteclasseparaadicionarasqueries:
publicclassProduzMensagensimplementsRunnable{privateintcomeco;privateintfim;privateCollection<String>mensagens;
publicProduzMensagens(intcomeco,intfim,Collection<String>mensagens){this.comeco=comeco;this.fim=fim;this.mensagens=mensagens;}
publicvoidrun(){for(inti=comeco;i<fim;i++){mensagens.add("Mensagem"+i);}}}
Vamos criar três threads que rodem esse código, todas adicionando as mensagens na mesmaArrayList.Emoutraspalavras,teremosthreadscompartilhandoeacessandoummesmoobjeto:éaquiquemoraoperigo.
publicclassRegistroDeMensagens{
publicstaticvoidmain(String[]args)throwsInterruptedException{Collection<String>mensagens=newArrayList<String>();
Threadt1=newThread(newProduzMensagens(0,10000,mensagens));Threadt2=newThread(newProduzMensagens(10000,20000,mensagens));Threadt3=newThread(newProduzMensagens(20000,30000,mensagens));
t1.start();t2.start();t3.start();
//fazcomqueathreadquerodaomainaguardeofimdessast1.join();t2.join();t3.join();
System.out.println("Threadsprodutorasdemensagensfinalizadas!");
//verificasetodasasmensagensforamguardadasfor(inti=0;i<15000;i++){if(!mensagens.contains("Mensagem"+i)){thrownewIllegalStateException("nãoencontreiamensagem:"+i);}
.
}
//verificasealgumamensagemficounulaif(mensagens.contains(null)){thrownewIllegalStateException("nãodeviaternullaquidentro!");}
System.out.println("Fimdaexecucaocomsucesso");}}
Rodealgumasvezes.Oqueacontece?
2. Testeocódigoanterior,masusandosynchronizedaoadicionarnacoleção:
publicvoidrun(){for(inti=comeco;i<fim;i++){synchronized(mensagens){mensagens.add("Mensagem"+i);}}}
3. SemusarosynchronizedtestecomaclasseVector,queéumaCollectioneéthread-safe.
Oquemudou?OlheocódigodométodoaddnaclasseVector.Oquetemdediferentenele?
4. Novamentesemusarosynchronized,testeusarHashSeteLinkedList,emvezdeVector.Façaváriostestes,poisasthreadsvãoseentrelaçarcadavezdeumamaneiradiferente,podendoounãoterumefeitoinesperado.
NocapítulodeSocketsusaremosthreadsparasolucionarumproblemarealdeexecuçõesparalelas.
.
CAPÍTULO21
"Quempoucopensa,engana-semuito."--LeonardodaVinci
Como vimos antes, aVM é apenas uma especificação e devemos baixar uma implementação.HámuitasempresasqueimplementamumaVM,comoaprópriaOracle,aIBM,aApacheeoutros.
AdaOracleéamaisusadaepossuiversõesparaWindows,LinuxeSolaris.VocêpodebaixaroSDKacessando:
http://www.oracle.com/technetwork/java/
NestapáginadaOracle,vocêdeveescolheroJavaSE,dentrodostopdownloads.Depois,escolhaoJDKeseusistemaoperacional.
CadadistribuiçãoLinuxtemsuaprópriaformadeinstalação.AlgumasjátrazemoJavajunto,outraspossibilitamquevocêinstalepelosrepositóriosoficiaiseemalgunscasosvocêprecisabaixardiretodaOracleeconfigurartudomanualmente.
NoUbuntu,adistribuiçãousadanaCaelum,ainstalaçãoébastantesimples.Bastairnoterminaledigitar:
sudoadd-apt-repositoryppa:webupd8team/javasudoapt-getupdatesudoapt-getinstalloracle-java8-installer
Casoprefirautilizaroopenjdk,adistribuiçãoopensource,bastafazer
sudoapt-getinstallopenjdk-7-jdk
Porenquantoelepossuiapenasaversão7.Nolinuxfedora,vocêfariacomsu-c"yuminstalljava-1.7.0-openjdk".
SevocêjátiveroutrasversõesinstaladasnoseuUbuntu,podeutilizarsudoupdate-alternatives--configjavaparaescolherentreelas.
Umainstalaçãomaisbraçal,semusarrepositório ,podeserfeitabaixandooinstaladornoprópriosite da Oracle. É um tar.gz que possui um .bin que deve ser executado. Depois, é necessário
APÊNDICE-INSTALAÇÃODOJAVA
21.1INSTALANDONOUBUNTUEEMOUTROSLINUX
.
apontarJAVA_HOMEparaessediretórioeadicionarJAVA_HOME/binnoseuPATH.
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
OMacOSXjátrazoJavainstaladojuntocomosistemaoperacionalatéaversão10.6.Asversõesmaisnovas,doLionemdiante,o instaladordoMacvaiperguntar sevocêdesejabaixá-loquando forrodarsuaprimeiraaplicaçãoJava,comooEclipse.
AversãoparaoJava8podeserbaixadanomesmosite:
http://www.oracle.com/technetwork/java/
Para instalar o JDK no Windows, primeiro baixe-o no site da Oracle. É um simples arquivoexecutávelquecontémoWizarddeinstalação:
http://www.oracle.com/technetwork/java/
EditoraCasadoCódigocomlivrosdeumaformadiferente
21.2NOMACOSX
21.3INSTALAÇÃODOJDKEMAMBIENTEWINDOWS
.
Dêumcliqueduplonoarquivojdk-<versão>-windows-i586-p.exeeespereatéeleentrarnowizarddeinstalação.
AceiteospróximosdoispassosclicandoemNext.Apósumtempo,o instaladorpediráparaescolher emquediretório instalaroSDK.Pode serondeele jáoferececomopadrão.Anotequalfoiodiretórioescolhido,vamosutilizaressecaminhomaisadiante.Acópiadearquivosiniciará:
Instalação
.
O instalador instalará também o JavaFX 2. Após isso, você será direcionado à uma páginaondevocêpode,opcionalmente,criarumacontanaOraclepararegistrarsuainstalação.
Precisamosconfiguraralgumasvariáveisdeambienteapósainstalação,paraqueocompiladorsejaacessível via linha de comando. Caso você vá utilizar diretamente o Eclipse, provavelmente não seránecessáriorealizaressespassos.
CliquecomobotãodireitoemcimadoíconeComputadoreselecioneaopçãoPropriedades.
Escolhaaaba "ConfiguraçõesAvançadasdeSistema"edepois cliquenobotão "VariáveisdeAmbiente"
Configurandooambiente
.
Nesta tela, você verá, na parte de cima, as variáveis de ambiente do usuário corrente e,embaixo,asvariáveisdeambientedocomputador(servemparatodososusuários).CliquenobotãoNovo...dapartedebaixo.
EmNomedaVariáveldigiteJAVA_HOMEe,emvalordavariável,digiteocaminhoquevocêutilizou na instalação do Java. Provavelmente será algo como: C:\Program
Files\Java\jdk1.8.0_03:
CliqueemOk.
Nãovamoscriaroutravariável,massimalterar.Paraisso,procureavariávelPATH,ouPath(dánomesmo),ecliquenobotãodebaixo"Editar".
.
Não altere o nome da variável! Deixe como está e adicione no final do valor;%JAVA_HOME%\bin,nãoesqueçadoponto-e-vírgula-assim,vocêestáadicionandomaisumcaminhoàsuavariávelPath.
Abraoprompt,indoemIniciar,Executaredigitecmd.
Noconsole,digitejavac-version.OcomandodevemostraraversãodoJavaCompilerealgumasopções.
VocêpodeseguirparaainstalaçãodoEclipse,conformevistonoseucapítulo,ouutilizarumeditordetextosimplescomooblocodenotasparaosprimeiroscapítulosdeapostila.
Qualquerdúvida,nãohesitedepostá-lanoGrupodeUsuáriosJava:
http://www.guj.com.br.
.
CAPÍTULO22
"Olhoporolho,eomundoacabarácego."--MohandasGandhi
Debugging(emportuguês,depuraçãooudepurar)éumprocessodereduzirouencontrarbugsnoseusistema.Deumaformageral,debuggingnãoéumatarefa fácildeserexecutada.Muitasvariaçõespodem atrapalhar esse processo, por exemplo, a linguagem que estamos utilizando e ferramentasdisponíveisparafazermosdebuggingdeumcódigo.
OJavaemsifacilitamuitonesteprocesso,poisnosfornecemaneirasdesabermosseocódigoestáerrado, por exemplo as exceptions. Em linguagens de baixo nível saber onde o bug estava eraextremamentecomplicado.Oquetambémfacilitanossotrabalhosãoasferramentasdedebug.Veremosqueelas sãonecessáriasnoscasosquenossos testesdeunidadede loggingnão foramsuficientesparaencontrararazãodeumproblema.
Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende
Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!
ConheçaaAluraCursosOnline.
No curso utilizamos o Eclipse como IDE para desenvolvermos nosso código. Como foi ditoferramentasdedebuggingfacilitammuitonossotrabalho,oEclipseéumadasIDEsmaispoderosasdomercadoenosforneceumaferramentaquetornaoprocessoextremamentesimples.
APÊNDICE-DEBUGGING
22.1OQUEÉDEBUGAR
Agoraéamelhorhoraderespirarmaistecnologia!
22.2DEBUGANDONOECLIPSE
.
O primeiro recurso que temos que conhecer quando começamos a debugar no Eclipse são osbreakpoints. Eles são pontos de partida em nosso código para iniciarmos o processo de debug. Porexemplo,no código abaixo, imaginequedesejamosdebugaro comportamentodométodosaca daclasseConta,mais especificamentedoif que verifica se saldo émenorqueo valor a ser sacado.Colocaríamosobreakpointexatamentenalinhaif(this.saldo<valor){:
publicclassConta{
privatedoublesaldo;
publicbooleansaca(doublevalor){if(this.saldo<valor){returnfalse;}else{this.saldo=this.saldo-valor;returntrue;}}}
Mascomofaçoisso?Muitosimples,bastaclicarnalinhaquedesejaadicionarobreakpoint,depoisclicarnomenuRun->ToogleBreakpoint.
.
Esseéotipomaisclássicodebreakpoint,veremosalgunsoutrosaolongodocapítulo.
Agora que já adicionamos o breakpoint que é o ponto de partida, vamos debugar nosso código.Precisamosrodarnossocódigo,ouseja,chamarométodosacaparaqueobreakpointsejaencontrado.Teremosumcódigosimilaraoseguinte:
publicclassTestaConta{publicstaticvoidmain(String[]args){Contaconta=newConta();conta.saca(200);}}
.
O processo normal para executarmos esse código seria clicar no menu Run -> Run As -> JavaApplication. Porém para rodar o nosso código emmododebug e ativar nosso breakpoint, devemosrodarocodigonomenuRun->DebugAs->JavaApplication.Quandoumbreakpointforencontradonocódigoqueestásendoexecutado,oeclipseexibiráumaperspectivaespecíficadedebug,apontandoparaalinhaquetemobreakpoint.
Temos várias informações disponíveis nessa perspectiva, algumas são essenciais e básicas paratrabalharmos com debug no nosso dia-a-dia, outras não tão relevantes e só usamos em casosmuito
22.3PERSPECTIVADEDEBUG
.
específicos.
Dentro da perspectiva de debug, temos uma aba chamada Variables. São exibidas todas asvariáveisencontradasdentrodocódigoquevocêestádebugando.Porexemplo,nodebugquefizemosserãoexibidasasvariáveisdométodosaca,nestecaso,valor.Alémdosatributosde instânciadoobjeto.
Podemosexibirmais informaçõessobreasvariáveis,bastaadicionarmosascolunasquedesejamosnatabelaexibida.
.
Épossíveltambémadicionarmosconstantesevariáveisestáticasdaclassequeestásendodebugada.
.
NaabaBreakpointssãoexibidostodososbreakpointsqueseuworkspacepossui.Masporqueissoéimportante?Éimportanteporquepodemosvertodosospontosdedebugpresentesemelhor,podemosdesabilitá-los um a um ou todos de uma só vez. Você pode até mesmo pedir para exportar osbreakpoints.
Paradesabilitar ouhabilitar todosbreakpoints basta clicarmosno íconeSkipAllBreakpoints. Sequisermosdesabilitarumaum,bastadesmarcarocheckboxeobreakpointserádesativado.Àsvezes,encontrarocódigoondeobreakpointfoicolocadopodesercomplicado,naabaBreakpointsissoficabemfácildefazer,bastadarumduplocliquenobreakpointeoeclipseautomaticamentenosmostraaclasse"dona"dele.
Quandoestamosdebugandocódigo,muitasvezeséinteressantesaberovalordealgumaexpressãooumétodo.Porexemplo,umacondiçãodentrodeumif,this.saldo>valor.Essevalornãoestáemumavariável,eleestáemumaexpressão,oquepodetornarsaberovalordelacomplicado.Afeaturede Expressions descomplica esse processo para nós. Na perspectiva de Debug temos a abaExpressions.Bastaclicarcomodireitodentrodaaba,eclicaremAddExpression:
.
Eoresultadodaexpressãoéexibido.
TemosoutraabaimportantechamadadeDebug.Dentreasfunçõesdelaestão:
Threads-Exibeasthreadsqueestãosendoexecutadas,emelhor,mostraqualthreadefetuouachamadaparaométodoondeestáodebug.Alémdissomostraapilhadeexecução,oquenospermitevoltarachamadadeummétodoBarradenavegação-Quepermitealterarmososcaminhosqueodebugseguirá.
.
Alistaaseguirmostraralgumasteclasebotõesquealteramocaminhonaturaldosnosssdebug:
F5 - Vai para o próximo passo do seu programa. Se o próximo passo for ummétodo, eleentraránocódigoassociado;F6 -Tambémvaiparaopróximopasso,porémseopróximopasso forummétodo,elenãoentraránocódigoassociado;F7-Voltaráemostraráométodoquefezachamadaparaocódigoqueestásendodebugado.NonossocasovoltaráparaométodomaindaclasseTestaConta;F8-Vaiparaopróximobreakpoint,senenhumforencontrado,oprogramaseguiráseufluxodeexecuçãonormal.
VocêtambémpodeusarosbotõesqueestãopresentesnaabaDebug.
.
Depoisquecolocamosumbreakpointemalgumpontodonossocódigo,podemoscolocaralgumaspropriedadesnele,porexemplo,usaralgumacondiçãopararestringirquandoobreakpointseráativadoemtempodeexecução.PodemosrestringirnapropriedadeHitCountqueobreakpointsóseráativadoquandoalinhaemqueeleencontra-seforexecutada'X'vezes.
22.4DEBUGAVANÇADO
.
Como na imagem acima o breakpoint só será ativado quando a linha de código em que ele seencontraforexecutada'2'vezes.Podemostambémcolocaralgumaexpressãocondicional,umif,porexemplo.
.
Obreakpoint, neste caso, somente será ativadoquandoo argumentovalor que foi passado aométodosaca formaior que 100.O importante aqui énotarmosquedevemos retornar sempre umvalorbooleano,senãoofizermos, teremosumerroemtempodeexecução.EssapropriedadeéválidaquandoqueremoscolocaraquelesfamososSystem.out.println("entrounoiftal")paraefeitode log, podemos fazer isso colocando o log dentro da expressão condicional nas propriedades dobreakpoint.
O display é uma das partes mais interessantes do debug do eclipse, ele provê uma maneira deexecutarmos qualquer código que quisermos quando estamos em debugging. Criar uma classe,instanciarobjetosdessaclasse,utilizarif's,for's,while's,todososrecursosdoJava,alémdepoderutilizarasvariáveis,métodos,constantesdaclassequeestamosdebugando.
Umexemploclássicoéquandoestamosemdebuggingequeremossaberoretornodealgummétododoqualnãotemosacesso,oquefaríamosantesseriacolocarumamontoadodeSystem.out.println,poluindo extremamente nosso código.Nodisplay o que fazemos é efetuar a chamadadesse código eautomaticamenteosresultadossãoexibidos.
Para vermos um efeito real disso, vamos alterar umpouco o comportamento da classeConta, demodoqueagoraosaldoparasaquetenhaqueserosaldorealmaisovalordolimite.Nossocódigofica
.
assim:
publicclassConta{
privatedoublesaldoReal;privatedoublelimite;
publicConta(doublelimite){this.limite=limite;}
publicbooleansaca(doublevalor){if(!isSaldoSuficiente(valor)){returnfalse;}else{this.saldoReal=this.saldoReal-valor;returntrue;}}
privatebooleanisSaldoSuficiente(doublevalor){return(this.saldoReal+this.limite)>valor;}}
Reparequeoif queverifica seo saldoé suficienteparaefetuarmoso saquechamaummétodoisSaldoSuficiente,oquepodeserumproblemaquandoestamosdebugando,afinalacondiçãodoiféummétodo.SeutilizarmosodisplaypodemosfazerachamadadométodoisSaldoSuficiente,verseuresultadoeomelhor,nãoafetamosodebug,apenasqueremosveroresultadodométodo,porexemplo.
Para exibirmos a abaDisplay é bem simples. TecleCtrl+ 3, digiteDisplay e a aba será exibida.Quandorodarmosnossocódigoemmododebug,podemosirnodisplay,digitarmosumachamadaparaométodoisSaldoSuficiente, executamos esse código que foi digitado selecionando-o dentro dodisplayeteclandoCtrl+Shift+Deoresultadoseráimpresso,assimcomonaimagemabaixo:
.
Muitasvezesqueremos "seguir"algumavariávelde instância,ouseja,qualquerchamadaparaessavariável(leituraouescrita)queremossernotificadosdisso.Podemosusarowatchpoint,quefaránossoprogramaentraremmododebug,quandoqualqueralteraçãonavariávelqueestamosseguindoocorrer,oprogramaentraráemdebugexatamentenalinhaquefezaalteração.Paracolocarmosumwatchpoint,bastadarumduplocliquenoatributodeinstânciaquedesejacolocá-lo.
.
Épossívelalteraressecomportamentopadrão,edefinirsevocêquerqueowatchpointsejaativadoparaleituraousomenteparaescrita.
.
Aidéiadesse tipodebreakpointé fazernossoprogramaentraremdebugquandoalgumaexceçãoespecífica ocorrer. Quando definirmos essa exceção no Exception Breakpoint e a mesma ocorrer,automaticamente nosso programa entra em debug na linha que gerou aquela exceção. Por exemplo,vamosalterarocodigodaclasseTestaContaparaqueamesmatenhaumaNullPointerException:
publicclassTestaConta{publicstaticvoidmain(String[]args){Contaconta=null;conta.saca(10);}}
Quando rodarmos o código acima, teremos uma NullPointerException. Pode ser útil nessescasosdebugaresaberondeaexceçãoestáocorrendodefato,emquallinhamaisespecificamente.Parafazermos isso podemos criar um Exception Breakpoint, que debugará códigos que eventualmentelancemumaNullPointerException,porexemplo.BastaabrirmosaabaBreakpointseclicarmosnoíconeabaixo:
.
Seráabertaumajanelaondepodemosbuscarporumaexceçãoespecífica.
Podemosdefinirumbreakpointqueé ativadoouantesoudepoisqueométodoé chamado.Paradefinirmosele,bastaestaremqualquerpartedométodoquedesejamosdebugar,clicarnomenuRun->ToogleMethodBreakpoint.Podemoseditaraspropriedadesdessebreakpointdizendosequeremosqueele seja ativado antes(default) ou depois da execução do método. Basta acessar as propriedades domethodbreakpointealterá-las.
.
Éutilquandodesejamosqueumbreakpointsejaativadoquandoumaclasseespecíficaforcarregadapelaprimeiravez, chamamosessebreakpointdeClassBreakpoint. Basta clicarmosnomenuRun ->AddClassLoadBreakpoint,umajanelaseráabertaebastadigitarmosonomedaclasseeadicionarmos:
.
Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.
CasadoCódigo,ebookcompreçodeebook.
Um dos principais hábitos que nós desenvolvedores devemos evitar é a questão da otimizaçãoprematura,ouseja,quandodesenvolvemosumaaplicaçãoparaumcliente,devemosnospreocuparematenderorequisitosfuncionaisdemaneiramaisrápidaemaissimplespossível.Opassoseguinteérefatorar seu código para que ele sejamelhorado e para que no futuro possa se adaptar as possíveismudanças.
Aregraé:"Deixeosproblemasdofuturo,paraseremresolvidosnofuturo".
Umadasferramentasquenosauxiliamnaquestãodenãootimizarnossocódigoprematuramente,sãoas ferramentasdeprofiling,que tornamaparentes,porexemplo,osproblemasdememóriaecpu,quepodemfazercomqueotimizemosnossocódigo.Atualmentedevidoastécnicasqueutilizamosparaentregaralgodevalorparaocliente,focamosprincipalmentenaqualidade,aspectosfuncionais,testes,etc.Porém,muitosproblemasquenão fazempartedosrequisitos funcionaispodemacontecerapenasquandoaaplicaçãoestáemprodução,nestepontoasferramentasdeprofilingtambémnosajudam.
JuntamentecomoEclipsetemosaopçãodeinstalareutilizarumaferramentadeprofilingconhecidacomoEclipseTPTP(EclipseTest&PerformanceToolsPlatform),quenosforneceopçõesparaisolareidentificarproblemasdeperformance,taiscomo:memória(memoryleak),recursoseprocessamento.OTPTPnospermiteanalisardesimplesaplicaçõesjavaatéaplicaçõesquerodamemmúltiplasmáquinaseemmúltiplasplataformas.
EditoraCasadoCódigocomlivrosdeumaformadiferente
22.5PROFILING
22.6PROFILINGNOECLIPSETPTP
.
ALTERNATIVASAOTPTP
Existem algumas alternativas ao TPTP, os mais conhecidos são Netbeans Profiler(http://profiler.netbeans.org/) que é gratuito, e o JProfiler (http://www.ej-technologies.com/products/jprofiler/overview.html)queépago.
O TPTP não vem por padrão junto com o Eclipse. Portanto, para utilizarmos é necessário ainstalaçãodomesmo.Podemosfazeroprocessodeinstalaçãodeduasmaneiras.Aprimeiraemaisfácilé utilizandooUpdate Site doEclipse que resolve as possíveis dependências e nos possibilita escolherquaisfeaturesqueremosinstalar.ParainstalaroTPTPatravésdesserecurso,bastairnomenu:Help->InstallNewSoftware,umajanelaseráaberta,bastaclicaremAdd...epreenchê-laconformeaimagemaseguir:
Basta adicionar as ferramentas do TPTP em nosso eclipse, para isto, selecione o repositório queacabamosdeadicionareaversãodoTPTPquequeremosinstalar,nestecaso,aversão4.6.2.
.
INSTALANDOPELOZIP
VocêtemaopçãodeinstalaroTPTPbaixandoozipdoprojetoecolocandomanualmentenodiretório de instalação do seu eclipse. Mais informações no link:http://www.eclipse.org/tptp/home/downloads/4.6.0/documents/installguide/InstallGuide46.html
Umproblemaquepodeaconteceremaplicaçõesequemuitaspessoasnãoconhecema fundo,éaquestãodopooldeStringsquepodeeventualmenteficarmuitogrande.Esteproblemapodesercausado
.
porqueobjetosdotipoStringsãoimutáveis,sendoassim,sefizermosconcatenaçõesdeStringsmuitasvezes,cadaumadessasconcatenaçõesproduziráumanovaString,queautomaticamenteserácolocadanopooldaJVM.
A alternativa neste caso, seria trabalhar com objetos do tipo StringBuilder ou StringBuffer quefuncionam como Strings,mas que não produzem Strings novas em caso de uma concatenação.MascomomedirotamanhodonossopooldeString?
O TPTP possui uma aba de estatísticas que nosmostra o tempo que ummétodo levou para serexecutado,quantoprocessamentoessemétodogastou,quantodememóriafoigastocomcadamétodo.VamosanalisaralgumasdessasestatísticascriandoumcódigoqueconcateneváriasStrings,demaneiraquesobrecarregueopool,gerebastanteprocessamentoeconsumodememória.
publicclassTeste{
publicstaticvoidmain(String[]args){for(inti=0;i<1000000;i++){Stringx="a"+i;System.out.println(x);}}
}
Paraanalisarmosoresultadodocódigo,vamosrodarocódigodomainatravésdomenuRun ->ProfileAs->JavaApplication.
VERSÕES
Infelizmente o TPTP funciona somente no Windows. Versões para MacOS e Linux sãoprometidas, mas até hoje estão em desenvolvimento. Uma alternativa paga para esses outrossistemasoperacionaiséoJProfiler.
.