50 dicas práticas para o exame SCJP Java 6
Motivado por ter passado no exame da SCJP recentemente, publico abaixo 50 dicas práticas para o exame da versão 6. Elas foram retiradas e adaptadas do livro Certificação SUN para Programador Java 6, de Kathy Sierra e Bert Bates, adicionadas em muitos casos de exemplos e comentários úteis.
- Saiba tudo sobre controle de acesso para o exame. Haverá uma boa quantidade de perguntas para as quais você deverá usar o seu conhecimento sobre o assunto. Quando vir uma questão com lógica complexa, certifique-se de olhar os modificadores de acesso primeiro;
- Procure questões com uma declaração de método que termine com ponto-e-vírgula em vez de chaves. Se o método estiver em uma classe – e não em uma interface -, então tanto o método como a classe devem ser marcados como abstract;
- Quando pensar em acesso padrão (default), pense em restrições de pacote, sem exceções. Mas quando pensar em protected, pense em pacote + filhos;
- Procure por classes concretas que não forneçam implementações para métodos abstratos da superclasse;
- Enums só podem ser declarados com acesso public ou default, assim como uma classe não interna;
- As chamadas de métodos polimórficos se aplicam somente a métodos de instâncias;
- Procure classes que afirmam implementar uma interface, mas não fornecem as implementações de método corretas. A menos que a classe de implementação seja abstract, ela terá que fornecer implementações de todos os métodos definidos na interface;
- Lembre-se: um método static de uma classe não pode acessar um membro – método ou variável – não estático (de instância) de sua própria classe;
- Procure perguntas que usem números onde os booleanos seriam obrigatórios. Você pode ver uma avaliação de instrução if que use um número, como na linha a seguir:
- Tome cuidado com variáveis sombreadas e com erros de escopo em blocos de código como switches, try-catches e loops;
- Lembre-se que quando duas referências apontem para o mesmo objeto, se uma delas for usada para alterá-lo, as duas saberão da alteração, porque ainda haverá somente um objeto. Mas sempre que forem feitas alterações em uma String, a VM atualizará a variável de referência para fazê-la apontar para um objeto diferente. Exemplo:
- No exame será esperado que você saiba, por exemplo, que o código abaixo produz apenas um objeto (o array atribuido a variável de referência inteiros). Nenhum objeto Integer foi realmente criado.
- As variáveis de referência wrapper podem ser null, portanto tome cuidado com algum código que pareça estar realizando operações seguras com primitivos, mas que lançam NullPointerException. Exemplo:
- Nenhuma das classes wrapper pode ser ampliada de uma para outra. Por exemplo: Byte não se amplia para Short, Short não se amplia para Long, etc. O código abaixo não vai funcionar:
- Tenha em mente que uma vez que o coletor de lixo entre em ação, não há garantia de que todos os objetos não utilizados serão realmente removidos da memória;
- Fique atento! A parte do exame referente aos operadores e atribuições normalmente é aquela em que os candidatos conseguem menos pontos. Por isso, muita atenção nas questões que envolvem esses assuntos;
- Você deve compreender de forma clara como a concatenação de Strings funciona, principalmente dentro de uma instrução print. Veja o exemplo abaixo:
- Procure questões que usem operadores de incremento e decremento em variáveis final. Obviamente que qualquer tentativa de utilizá-los nessa situação resulta em uma exceção.
- Os operadores && e || só funcionam com operadores booleanos. Você pode encontrar questões que usem inteiros com esses operadores (dando a impressão que estamos usando o operador bit a bit &). Exemplo:
- Retirando-se uma saída forçada (break, return, System.exit(), etc), as avaliações da expressão de iteração e, posteriormente, da expressão condicional, são sempre as duas últimas coisas a ocorrerem em um loop for.
- Procure códigos que invoquem métodos que declarem uma exceção, mas o método que estiver chamando não manipule ou declare a exceção verificada. Exemplo abaixo:
- Se você se deparar com a palavra expressão em uma pergunta sobre assertivas e ela não especificar se está se referindo à primeira expressão (teste booleado) ou à segunda (o valor a ser exibido no rastreamento da pilha), então assuma que sempre está se referindo ao teste booleano.
- Os arrays têm um atributo (não um método) chamado length. É possível que você encontre alguma pergunta que troque o atributo pelo método length(), da classe String, ou vice-versa. Exemplo:
- Criar diretórios em Java é diferente de criar arquivos. Ao se construir um Reader ou um Writer, automaticamente um arquivo é criado, caso não exista. Porém o mesmo não ocorre com diretórios, ou seja, o diretório não será criado caso estejamos tentando escrever em um novo arquivo daquele diretório que você deseja que exista. Veja o exemplo abaixo e observe que a linha que cria o diretório está comentada:
- Você deverá saber quais variáveis são restauradas com os valores apropriados e quais não são, quando um objeto é deserializado. Veja um exemplo:
- Atenção: a contagem dos meses em um Calendar começa em 0 (zero);
- Os objetos DateFormat e NumberFormat podem ter os seus locais definidos somente no momento da instanciação. Cuidado com códigos que tentam modificar o local de uma instância existente. Exemplo:
- Metacaracteres e Strings não trabalham bem juntos. Portanto, tome cuidado com código como o abaixo, pois ele não compila:
- Quando encontrar uma sobrescrição de equals(), hashCode() e toString() verifique se não houve uma mudança de visibilidade, pois o método deve ser public. Além disso, observe se não está sendo feita uma sobrecarga, ao invés de sobrescrita. O primeiro código abaixo, por exemplo, é inválido e o segundo é uma sobrecarga válida:
- Na prova, tenha cuidado com a interpretação de certas questões. Não confunda, por exemplo, o uso apropriado ou correto do código de hashing, com a validade ou eficiência da solução implementada;
- Cuidado para não confundir as classes Collections e Collection. Collection é uma interface com as declarações de métodos comuns a várias coleções e Collections é uma classe com métodos estáticos utilitários;
- É importante reconhecer o que é interface e o que é classe concreta quando se trata de coleções. O código abaixo não compila porque Map é uma interface:
- Entenda o funcionamento das classes Comparator e Comparable, pois elas são bastante parecidas. Analise principalmente a forma como elas trabalham e o método que utilizam para efetuar a comparação;
- Procure por questões no exame que tentem classificar um array de primitivos usando um Comparator, o que é inválido;
- Quando houver classificação de um array ou de uma coleção, os elementos contidos nesses objetos devem ser mutuamente comparáveis. Você não pode ter um Object[], colocar dentro dele um objeto Cachorro e um objeto Gato e depois efetuar uma classificação;
- Os erros mais comuns em busca e classificação são:
- Procurar em um array ou coleção que não tenha sido ordenado;
- Usar um Comparator ou só na classificação ou só na busca;
- Quando converter arrays em Collections ou Collections em arrays, lembre-se que a atualização em um dos objetos refletirá no outro. Observe o código abaixo:
- Certifique-se de que você entende bem a diferença entre “compilação falha”, “compila sem erros”, “compila sem avisos” e “compila com avisos”. Em genéricos e na mistura de código com e sem tipos específicos, os avisos podem fazer diferença;
- Ao declarar um conjunto não-genérico, o método get() irá retornar Object, portanto é necessário efetuar cast explícito. O código abaixo, por exemplo, não compila:
- Em genéricos, os coringas só podem ser usados para declarações de referências, ou seja, enquanto uma referência pode ser abstrata e polimórfica, o próprio objeto criado deve ser de um tipo específico. Você precisa definir o tipo quando cria o objeto usando new. O exemplo abaixo não é válido:
- Classes internas locais de métodos só podem ser instanciadas dentro do método onde foram criadas e acessam normalmente os membros privados da classe externa, entretanto não poderão usar as variáveis locais do método onde elas estiverem. A única exceção é no caso de as variáveis serem final. Veja o código a seguir:
- Em classes internas anônimas, tome cuidado com o ponto-e-vírgula de fechamento da definição da classe. Caso ele não esteja presente, o código não compila. Observe o exemplo:
- Saiba identificar uma classe interna anônima que, ao invés de sobrescrever um método da superclasse, define um método novo.
- Cuidado com instanciação de interface ou classes abstratas. O primeiro código a seguir não roda, mas o segundo sim.
- É muito importante você saber a maneira como uma thread funciona. O exame tem perguntas a respeito de “comportamento garantido” em concorrência que normalmente caem;
- Atenção com métodos run sobrecarregados. A classe Thread espera um método run() sem argumentos e o executará ao iniciá-la.
- A classe Thread implementa Runnable, portanto é perfeitamente fazer o seguinte:
- Lembre-se que uma vez uma thread tenha sido iniciada, ela jamais pode ser iniciada novamente;
- Ao terminar a execução do método sleep(), não significa que a thread retornará ao estado de execução, pois ela fica com o status de executável. O método sleep(), portanto, não deve ser encarado como um timer preciso;
- Entenda a estrutura dos comandos javac e java. No teste sempre caem perguntas simples do assunto.
int x = 1;
if (x) { } // Erro do compilador
String x = "Pablo";
String y = x; // y e x referenciam o mesmo objeto String
System.out.println("y = " + y); // Imprime 'Pablo'
x = x + " Nóbrega"; // Altera somente x. Foi criado um novo objeto e a referência foi atualizada
System.out.println("y = " + y); // Continua imprimindo 'Pablo'
A saída para esse código será:
y = Pablo
y = Pablo
Integer[] inteiros = new Integer[5];
class TesteTempo {
static Long tempo;
static void calculaTempo(int parametro) {
System.out.println(parametro + 5);
}
public static void main(String[] args) {
calculaTempo(tempo); // NullPointerException. 'tempo' não foi inicializada
}
}
class TesteAmpliacao{
void ampliar(Long parametro) {
System.out.println(parametro);
}
public static void main(String[] args) {
TesteAmpliacao teste = new TesteAmpliacao();
teste.ampliar(new Integer(10)); // impossível ampliar de Integer para Long
}
}
int b = 2;
System.out.println("" + b + 3); // Imprime '23'
System.out.println(b+3); // Imprime 5
if (5 && 6) // Erro de compilação.
void aumenta() { // falta método manipular ou declarar a exceção que deveria ser lançada por realizaCalculo()
realizaCalculo();
}
void realizaCalculo() { // falta método lançar com throws
throw new IOException();
}
String teste = "teste"; System.out.println(teste.length); // Erro de compilação }
File diretorio = new File("novoDir");
// diretorio.mkdir(); // Criação de diretório comentada
File arquivo = new File(diretorio, "meuArquivo.txt");
arquivo.createNewFile(); // Exceção por conta de o diretório não existir.
import java.io.*;
class SuperClasseNaoSerializada {
public static void main(String[] args) {
Leao leao = new Leao(120, "Juba");
System.out.println("antes de deserializar: " + leao.nome + " " + leao.tamanho);
try {
FileOuputStream fos = new FileOutputStream("arquivo.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(leao); oos.close();
} catch (Exception ex) { e.printStackTrace(); }
try {
FileInputStream fis = new FileInputStream("arquivo.txt");
ObjectInputStream ois = new ObjectInputStream (fis);
leao = (Leao) ois.readObject(); ois.close();
} catch (Exception ex) { e.printStackTrace(); }
System.out.println("depois de deserializar: " + leao.nome + " " + leao.tamanho);
}
}
class Leao extends Animal implements Serializable {
String nome;
Leao(int t, String n) {
tamanho = t; // herdado de Animal
nome = n; // não herdado
}
}
class Animal {
int tamanho = 105;
}
A saída para esse código será:
antes de serializar: Juba 120
depois de deserializar: Juba 105
class TestaLocal {
public static void main(String[] args) {
DateFormat df = DateFormate.getInstance();
df.setLocale(new Locale("it", "IT"));
}
}
class TestaPattern {
public static void main(String[] args) {
String patternInvalido= "\d"; // Pattern inválido. Não compila.
Pattern p = Pattern.compile(patternInvalido);
}
}
class ErroEquals {
boolean equals(Object o) { // visibilidade default: não compila
return false;
}
}
class Bola {
boolean equals(Bola bola) { // sobrecarga válida
return true;
}
}
class TestaMap {
public static void main(String[] args) {
Map<String, String> mapa = new Map<String, String>();
}
}
class TestaColecoes {
public static void main(String[] args) {
String[] nomes = {"Pablo", "Nóbrega"};
List nomesList = Arrays.asList(nomes);
System.out.println("Posição 1 = " + nomesList.get(1));
nomesList.set(1, " - Autor do Post");
for (String s : nomes) {
System.out.print(s);
}
}
}
A saída para esse código será:
Posição 1 = Nóbrega
Pablo – Autor do Post
class TestaGenericos {
public static void main(String[] args) {
List teste = new ArrayList();
teste.add(43);
int x = teste.get(0);
System.out.println(x);
}
}
class TestaGenericos {
public static void main(String[] args) {
List<?> animais = new ArrayList<? extends Animal>();
}
}
class TestaClasseLocalMetodo {
public void fazAlgo() {
int x = 1;
class ClasseInvalida {
public void naoRoda() {
System.out.println("x = " + x); // não compila. 'x' não está visível. Solução: declarar 'x' como final
}
}
}
}
public class Animal {
public void pula() {
System.out.println("pulou");
}
}
class Cachorro {
Animal a = new Animal() {
public void pula() {
System.out.println("pulo 2");
}
} // Não compila. Falta ponto-e-vírgula
}
Runnable r = new Runnable(); // Não compila. Tentando instanciar uma interface.
Runnable r = new Runnable() { // Compila. Classe anônima.
public void run() { }
};
Thread t = new Thread(new Thread()); t.start();
Categoriasprogramação
certificação, dicas, java, scjp
Muito bom Pablo.
Também sou certificado e muitas das coisas ditas aqui realmente caem no exame!!
Parabéns!!
Muito bom!
Parabéns Pablo. Eu vou dar uma olhada.
Muito bom o post! Simples e conciso.
Parabéns!
Muito bom!
Show,
excelentes dicas, muito valiosas e sem dúvida vão me ajudar bastante.
opa! Pablo, Parabens pelo post, realmente execelente. Simples e direto.
flw, abracos,
O material está muito interessante. Para quem está em dúvida sobre o quanto está preparado para o exame esse material já pode dar uma idéia. Parabéns mt bom!!
Olá, mto bom o post.
Parabéns.
Só uma obs. Vc diz “Runnable r = new Runnable(); // Não compila. Tentando instanciar uma classe abstrata.”.Porem Runnable não é classe abstrata e sim interface.
Parabéns pelo post eu li e ajuda mto…
Bem observado, João. Já corrigi.
muito bom o post! parabens !
Parabéns pelo seu blog e principalmente pelas dicas.
Quero tirar a certificação tb, e eu tenho o livro – ‘Certificação SUN para Programador Java 5′
A questão é, quero fazer a certificação p/SCJP6 e não p/5. O livro que eu tenho que é o guia p/certificação 5 é válido p/eu estudar p/prova SCJP6, sei que a versão 6 tem + 3 classes na API
Dá para tirar, sim, pelo livro SCJP5. São poucas diferenças, como essas 3 classes novas que você falou (e mais algumas interfaces). Eu apenas procuraria na internet uma fonte que explicasse o que veio de novo da versão 5 para a 6 para ficar informado. Aqui tem um link.