CodeGym /Blogue Java /Random-PT /Fiquei preso? Partes mais difíceis de aprender Java e com...
John Squirrels
Nível 41
San Francisco

Fiquei preso? Partes mais difíceis de aprender Java e como superá-las

Publicado no grupo Random-PT
Como você sabe, recomendamos iniciantes em codificação para começar a aprender linguagens de programação com Java, e o CodeGym tem tudo para tornar o processo de aprendizagem de Java digerível até para os alunos mais despreparados. Mas, por mais que os elementos de gamificação, a história descontraída e os personagens engraçados ajudem a facilitar esse processo, aprender os fundamentos de Java em sua plenitude raramente ocorre sem desafios para a maioria dos novos alunos. Fiquei preso?  Partes mais difíceis de aprender Java e como superá-las - 1Hoje vamos dar uma olhada em algumas das áreas mais difíceis dos fundamentos da programação Java, tentando entender por que muitas pessoas as acham difíceis e se há algo que você possa fazer a respeito.

1. Genéricos

Genéricos em Java são tipos que possuem um parâmetro. Ao criar um tipo genérico, você especifica não apenas um tipo, mas também o tipo de dados com o qual ele trabalhará. Os genéricos são freqüentemente mencionados pelos alunos de Java como uma das partes mais difíceis de entender para eles. “Meu principal problema ainda é lidar com os genéricos. É muito mais fácil quando você tem métodos com parâmetros a seguir, mas fica confuso quando você precisa escrever o seu próprio”, disse um aluno anônimo de Java.

Dicas e recomendações

Aqui está uma opinião sobre Generics in Java de Ravi Reddy, um programador experiente e professor universitário: “Java Generics faz uma coisa que os templates C++ não fazem — implementar segurança de tipos. A implementação de modelos C++ é um truque simples do pré-processador e não garante a segurança de tipo. Genéricos em Java são como modelos C++, mas com segurança de tipo adicional. E IMHO, a segurança de tipo é uma característica essencial de qualquer bom ambiente de desenvolvimento. E sim! Eles podem ser confusos por causa de nossas mudanças mentais entre os parâmetros e os tipos. Mas acredito que gastar tempo para dominá-los vale o esforço. Porque me vi "pensando" muito melhor em Java depois que entendi as interfaces e os genéricos."

2. Multithreading

Multithreading em Java é um processo de execução de dois ou mais threads simultaneamente para atingir a utilização máxima da CPU pelo aplicativo. Multithreading resolve tarefas muito importantes e pode tornar nossos programas mais rápidos. Muitas vezes, muitas vezes mais rápido. Mas é considerado um dos tópicos em que muitos novos alunos de Java tendem a ficar presos. Tudo porque o multithreading também pode criar problemas em vez de resolvê-los. Existem dois problemas específicos que o multithreading pode criar: deadlock e condições de corrida. Deadlock é uma situação em que vários threads estão esperando por recursos mantidos um pelo outro e nenhum deles pode continuar em execução. Uma condição de corrida é um erro de design em um sistema ou aplicativo multithread, em que a operação do sistema ou aplicativo depende da ordem na qual as partes do código são executadas.

Dicas e recomendações

Aqui está uma boa recomendaçãosobre como lidar com multithreading de S.Lott, um arquiteto de software e usuário ativo do StackExchange, um popular site de perguntas e respostas: “Multi-threading é simples. Codificar um aplicativo para multi-threading é muito, muito fácil. Há um truque simples, que é usar uma fila de mensagens bem projetada (não crie a sua própria) para passar dados entre threads. A parte difícil é tentar fazer com que vários threads atualizem magicamente um objeto compartilhado de alguma forma. É quando fica sujeito a erros porque as pessoas não prestam atenção às condições de corrida que estão presentes. Muitas pessoas não usam filas de mensagens e tentam atualizar objetos compartilhados e criar problemas para si mesmas. O que fica difícil é projetar um algoritmo que funcione bem ao passar dados entre várias filas. Isso é difícil.

3. Problemas de classpath

Erros de caminho de classe também são considerados um dos problemas mais reclamados que os desenvolvedores Java enfrentam em seu trabalho diário. “Problemas de caminho de classe podem ser demorados para depurar e tendem a acontecer nos piores momentos e lugares possíveis: antes dos lançamentos e frequentemente em ambientes onde há pouco ou nenhum acesso pela equipe de desenvolvimento. Podem também acontecer ao nível do IDE e tornarem-se uma fonte de redução de produtividade,” afirma Vasco Ferreira, um experiente programador Java/Javascript e autor de tutoriais relacionados com programação.

Dicas e recomendações

“Problemas de caminho de classe não são de baixo nível ou inacessíveis como podem parecer à primeira vista. É tudo sobre arquivos zip (jars) presentes ou ausentes em determinados diretórios, como encontrar esses diretórios e como depurar o caminho de classe em ambientes com acesso limitado. Conhecendo um conjunto limitado de conceitos, como Class Loaders, Class Loader Chain e modos Parent First / Parent Last, esses problemas podem ser resolvidos de forma eficaz”, explica o especialista.

4. Polimorfismo e seu uso correto

Quando se trata de princípios de OOP, muitas pessoas dizem que tiveram dificuldade em entender o polimorfismo. Polimorfismo é a capacidade de um programa tratar objetos com a mesma interface da mesma maneira, sem informações sobre o tipo específico do objeto. Apesar do polimorfismo ser um tópico bastante básico, ele é bastante extenso e forma uma boa parte da base do Java. Para muitos alunos, o polimorfismo é a primeira dificuldade no aprendizado de Java. Tudo porque existem diferentes formas de polimorfismo usadas em diferentes contextos, o que pode ser confuso.

Dicas e recomendações

Não há outra maneira de lidar com o polimorfismo além de aprendê-lo. Veja como Torben Mogensen, que ensina programação na Universidade de Copenhague, explicaeste conceito: “Sobrecarga simples: + pode significar adição de inteiro, adição de ponto flutuante e (em alguns idiomas) concatenação de strings. Polimorfismo de subtipo: Se B é um subtipo de (herda de) A, qualquer valor do tipo B pode ser usado em um contexto que espera um valor do tipo A. Polimorfismo paramétrico: Um tipo pode ser parametrizado com parâmetros de tipo, de modo que você diferentes contextos podem fornecer diferentes argumentos de tipo, então você instancia o tipo parametrizado para diferentes tipos concretos. Isso também é chamado de “templates” ou “genéricos” e é normalmente especificado em linguagens OO usando colchetes angulares (como T<A>). Polimorfismo de interface. Este é basicamente um mecanismo em que você restringe o polimorfismo de subtipo a subtipos que implementam uma determinada interface ou polimorfismo paramétrico a parâmetros de tipo que implementam uma determinada interface.”

5. Reflexão

A reflexão é um mecanismo para explorar dados sobre um programa enquanto ele está sendo executado. A reflexão permite explorar informações sobre campos, métodos e construtores de classes. Ele também permite que você trabalhe com tipos que não estavam presentes no tempo de compilação, mas que se tornaram disponíveis durante o tempo de execução. A reflexão e um modelo logicamente consistente para emitir informações de erro possibilitam a criação de um código dinâmico correto. Mas para muitas pessoas, não é tão fácil descobrir como usar o Reflection.

Dicas e recomendações

“No caso de reflexão e Java, a reflexão permite que Java, que é projetado para ser tipado estaticamente, seja tipado dinamicamente. A digitação dinâmica não é inerentemente má. Sim, ele permite que o programador quebre certos princípios OOP, mas ao mesmo tempo permite muitos recursos poderosos como proxy em tempo de execução e injeção de dependência. Sim, o Java permite que você dê um tiro no próprio pé usando a reflexão. No entanto, você deve apontar explicitamente a arma para o pé, tirar a trava de segurança e puxar o gatilho”, explica Jayesh Lalwani, um experiente programador Java e arquiteto de aplicativos.

6. Fluxos de entrada/saída

Os fluxos permitem que você trabalhe com qualquer fonte de dados: a Internet, o sistema de arquivos do seu computador ou qualquer outra coisa. Streams são uma ferramenta universal. Eles permitem que um programa receba dados de qualquer lugar (fluxos de entrada) e os envie para qualquer lugar (fluxos de saída). A tarefa deles é a mesma: pegar dados de um lugar e enviá-los para outro. Existem dois tipos de fluxos: fluxos de entrada (usados ​​para receber dados) e fluxos de saída (para enviar dados). O que torna difícil para muitas pessoas entender o uso de fluxos é o fato de Java ter várias classes de fluxo de E/S.

Dicas e recomendações

“Java tem tantas classes de fluxo de I/O principalmente devido a dois fatores contribuintes. Primeiro é o legado. Algumas classes ainda estão lá por razões históricas e não são obsoletas, pois não são consideradas prejudiciais. Segundo, flexibilidade. Aplicativos diferentes têm requisitos diferentes e, portanto, você tem várias opções dependendo de seus requisitos. Abstrações úteis trazem clareza quando você lê e com poucas linhas de código você pode fazer muito”, diz Jonas Mellin, um especialista em Java da Suécia. Quais aspectos do Java você achou mais difíceis de entender ou ficou preso por algum tempo? Compartilhe suas experiências nos comentários.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION