public class Player {
private String name;
private String position;
private int age;
/* Muitos jogadores têm apenas um clube */
private Team team;
...
}
Os jogadores podem compartilhar do mesmo clube/time, mas só poderão ter apenas um. Ao contrário de um clube, que pode ter muitos jogadores associados a ele.
public class School {
private String name;
private String director;
private Student[] students;
...
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", director='" + director + '\'' +
", students=" + Arrays.toString(students) +
'}';
}
}
Uma escola pode ter múltiplos alunos associados a ela, mas um estudante só pode estar matriculado numa escola.
- A maioria dos casos de erros não são causados pelo nosso programa estes são devido à falta de recursos do sistema e estes não são recuperáveis.
- A maioria dos casos de exceções são causadas pelo nosso programa e estes são recuperáveis.
- São lançadas em tempo de compilação e herdam da Classe Exception.
- São lançadas em tempo de execução e herdam da Classe RuntimeException.
- A fim de evitar o uso do bloco finally{}, usa-se a seguinte estrutura:
try (Scanner input = new Scanner(System.in);
BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
...
} catch (Exception e) {
e.printStackTrace();
}
Essa estrutura abstrai a execução dos métodos input.close() e br.close(). Muito por conta disso, tem-se a seguinte regra de uso:
- Pode-se passar como recurso, somente objetos de classes que implementem Closeable ou AutoCloseable. Pois o objetivo desta implementação é sempre fechar algo, pode ser uma conexão com um banco, um arquivo, etc.
- Como a classe Scanner: public final class Scanner implements Iterator, Closeable {...}
- Multi-catch:
try {
...
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
- catch in line:
try {
...
} catch (InvalidLoginException | InputMismatchException e) {
if (e instanceof InputMismatchException) {
System.out.println("A senha informada contém caracteres diferentes do permitido.");
} else {
e.printStackTrace();
}
}
- Isso ocorre porque, no bloco catch (A | B e), o compilador trata e como efetivamente final, ou seja, você não pode reatribuir ou fazer downcast direto com segurança.
- Ao usar InputMismatchException e NoSuchElementException em linha, o programa retornará erro na primeira exceção, uma vez que ela é filha da segunda.
As classes especiais Wrappers, dão mais poder às variáveis primitivas. Transformando-as em um Objeto com diversos métodos úteis.
- Boxing ou autoboxing e unboxing:
Character character = '1'; // autoboxing
boolean bool = Character.isLetter(character);
char ch = character; // unboxing
System.out.println(bool + " | " + ch); // Saída esperada: false | 1
- String: Imutável. Toda modificação gera um novo objeto na memória.
- StringBuilder: Mutável e mais performática, indicada para uso em ambientes de thread única.
- StringBuffer: Mutável e segura para múltiplas threads, mas menos performática que o StringBuilder por conta da sincronização.
String nome = "Ana";
nome += " Silva"; // Cria um novo objeto: "Ana Silva"
"Ana"
(literal)" Silva"
(literal)"Ana Silva"
(objeto novo criado na concatenação)
O String Pool é uma área de memória especial usada para armazenar strings literais reutilizáveis. Exemplo:
String a = "Teste";
String b = "Teste";
System.out.println(a == b); // true, ambos apontam para o mesmo objeto no pool
String c = new String("Teste");
System.out.println(a == c); // false, c é um novo objeto no heap
String d = new String("Teste").intern();
System.out.println(a == d); // true, d foi movido para o pool
- Strings criadas com
new
não são automaticamente adicionadas ao pool. - O método
intern()
adiciona a string ao pool, se ainda não estiver lá.
- matches(): tenta casar o texto inteiro com o padrão.
- find(): procura ocorrências válidas num texto maior, mesmo que ele não obedeça 100% ao padrão.