Implementações

LPOO 1 - Java


Prof. Rodrigo Noll @ IFRS Canoas



Versão para impressão

Collections Framework

Exercícios


LPOO 1 - Java

Collections Framework

  • A manipulação de arrays é muito trabalhosa:
    • Não é possível redimensionar um array em Java
    • Não é possível buscar diretamente um elemento cujo índice não seja conhecido
    • Não é possível saber quantas posições do array foram populadas sem utilizar métodos auxiliares (ou variáveis)

Coleções

  • É um objeto que representa um grupo de objetos
    • É simplesmente um objeto que agrupa múltiplos elementos em um simples unidade
  • Coleções são utilizadas para armazenar, recuperar, manipular e comunicar dados agregados
  • Exemplos:
    • Baralho: uma coleção de cartas
    • Caixa de correio: uma coleção de cartas
    • Lista telefônica: uma coleção de nomes e telefones

Implementação das Coleções

  • Interfaces na organização das coleções:
    • Conjuntos (sets)
    • Listas (Lists)
    • Queue (Pilhas)
    • Deque (Fila Dupla - FIFO/LIFO)
    • Mapas (Maps)

List

Listas

List

  • É uma coleção que permite elementos duplicados e mantém uma ordenação específica entre os elementos

  • Arrays com algumas capacidades adicionais, uma das quais é a capacidade de ter seu tamanho modificado de acordo com a necessidade
  • Existe uma interface java.util.List que especifica o que uma classe deve ser capaz de fazer para ser uma lista.
  • Ela declara que métodos podem ser utilizados para manipulação de listas e duas classes que implementam esta interface

List

List


//É recomendável abstrair a lista a partir da interface List:
List <ContaCorrente> contas = new ArrayList<>();
contas.add(c1);
contas.add(c3);
contas.add(c2);

for(int i = 0; i < contas.size(); i++) {
    ContaCorrente cc = contas.get(i); // sem casting!
    System.out.println(cc.getSaldo());
}

for(Conta conta: contas) { //foreach
	System.out.println(conta.getSaldo());
}

                        

List


List<String> myList =
    Arrays.asList("a1", "a2", "b1", "c2", "c1");

myList
    .stream()
    .filter(s -> s.startsWith("c"))
    .map(String::toUpperCase)
    .sorted()
    .forEach(System.out::println);

// C1
// C2
                        

Set

Conjuntos

Set

Set

  • Um conjunto (Set) funciona de forma análoga aos conjuntos da matemática, ele é uma coleção que não permite elementos duplicados.
  • Conjuntos podem ser vazios, mas não podem ser infinitos
  • Tamanho dos conjuntos pode variar dinamicamente
  • Em geral, os objetos em um conjunto não são ordenados explicitamente
  • Exemplos: números sorteados de uma loteria, conjunto de alunos de uma turma

Set

  • São encapsulados por uma instância de uma das classes que implementam a interface Set:

Set


public static void main(String[] args) {
	Set<String> cargos = new HashSet<>();
	cargos.add("Gerente");
	cargos.add("Diretor");
	cargos.add("Presidente");
	cargos.add("Secretária");
	cargos.add("Funcionário");
	cargos.add("Diretor"); // repetido, retorna false e não insere
	// imprime na tela todos os elementos
	System.out.println(cargos);

	if (cargos.contains("Secretária"))
		System.out.println("Cargo contém Secretária");
}

                        

Set


import java.util.*;
import java.util.stream.*;

public class BuscaDuplicadas {
    public static void main(String[] args) {
        Set<String> palavrasDistintas = Arrays.asList(args).stream()
		.collect(Collectors.toSet());
        System.out.println(palavrasDistintas.size()
                            + " palavras distintas: " + palavrasDistintas);
    }
}                        

Map

Mapa de Objetos

Map

Map

  • Mapas são conjunto de pares de objetos – um chamado "chave" (key) e o outro de "valor" (value)

  • Mapas não permitem chaves repetidas, mas permitem valores repetidos (chaves diferentes podem estar associadas a valores iguais)

Map

  • São encapsulados por uma instância de uma das classes que implementam a interface Map:

Map


	public static void main(String[] args) {
		ContaCorrente c1 = new ContaCorrente();
		c1.deposita(10000);
		ContaCorrente c2 = new ContaCorrente();
		c2.deposita(3000);
		// cria o mapa
		Map<String, ContaCorrente> mapaDeContas = new HashMap<>();
		// adiciona duas chaves e seus respectivos valores
		mapaDeContas.put("diretor", c1);
		mapaDeContas.put("gerente", c2);
		ContaCorrente contaDoDiretor = mapaDeContas.get("diretor");
		System.out.println(contaDoDiretor.getSaldo());
	}


                        

Map


Map<Integer, String> map = pessoas
    .stream()
    .collect(Collectors.toMap(
        p -> p.idade,
        p -> p.nome,
        (nome1, nome2) -> nome1 + ";" + nome2));

System.out.println(map);
// {18=Rodrigo, 23=Peter;Pamela, 12=David}
                        

Implementações

Collections Framework

Exercícios


LPOO 1 - Java

Tratamento de Exceções

Exercícios


LPOO 1 - Java

Tratamento de Exceções

  • Problemas em programas
    • Entradas inválidas, problemas de acesso a arquivos, ...

  • Erros e Exceções
    • Situações anormais (exceções) ou inválidas (erros) durante o processo de execução
    • Uma exceção interrompe o fluxo de execução do programa
    • Este fluxo segue a exceção e se o método onde ela ocorrer não capturar, ela será propagada para o método que chamar este método e assim por diante
    • Se não houver captura da exceção, ela irá causar o término do programa
    • Mas se ela for capturada o controle pode ser recuperado

Tratamento de Exceções

  • Mecanismo de processamento de erros em tempo de execução
  • Mecanismo flexível para passar o controle do ponto de detecção de erro para um tratador competente de recuperação
  • É utilizado um mecanismo de try-catch para capturar as exceções
  • As exceções são objetos criados a partir de classes especiais que são lançados quando ocorre uma exceção

Erros de tempo de execução

  1. Erros de lógica de programação
    • Limites de vetores
    • Divisões por zero

  2. Erros devido a condições do ambiente de execução
    • Arquivo não encontrado
    • Rede fora do ar

  3. Erros graves, sem possibilidade de recuperação
    • Falta de memória
    • Erro interno da JVM
    • Falta de espaço em disco

Classificação das Exceções

  • Dois tipos de exceções:
    • Verificadas
    • Não verificadas

  • Exceções verificadas
    • Ao chamar um método que lança uma exceção verificada, o programador deve dizer ao compilador o que está fazendo sobre a exceção se ela for lançada
    • Se devem a circunstâncias externas que o programador não pode evitar
    • Em geral, estendem a classe Exception
    • Exemplos: IOException, FileNotFoundException

Classificação das Exceções

  • Exceções não verificadas
    • Em geral, estendem a classe RuntimeException ou Error
    • Exemplos: NumberFormatException, IllegalArgumentException, NullPointerException

  • Algumas considerações
    • As categorias não são perfeitas
    • Exemplo: o programador não tem culpa se um usuário digitar um número incorreto e lançar uma exceção NumberFormatException

Classificação das Exceções

Lançando uma exceção

  • No mecanismo de tratamento de exceções:
    • As exceções não podem ser negligenciadas
    • Elas podem ser tratadas por um tratador competente

  • Detecção de condição de Erro
    • É necessário “lançar” (com throw) um objeto de exceção apropriado
    • throw: lançar uma exceção e transferir o controle para um tratador para esse tipo de exceção
    • Procurar uma classe apropriada de exceção (a API possui muitas classes para sinalizar todos os tipos de condições excepcionais)

Passos para lançar uma exceção

  1. Criar um objeto derivado da classe Exception
  2. Lançar a exceção através da cláusula throw
  3. Quando a exceção é lançada o método termina imediatamente
  4. O mecanismo de tratamento de exceção repassa o objeto “Exception” para o manipulador de exceção apropriado
  5. Sempre prefira escolher classes de exceção da própria API

Exemplo


...

public class ContaBancaria {
	public void saca (double valor){
	    if (valor > saldo) {
                 IllegalArgumentException exception = new
                          IllegalArgumentException(“O valor ultrapassa o saldo !”);
	          throw exception;
	    }
            saldo = saldo – valor;
	}
   ...
}
...
                        

Capturando uma exceção

  1. Um exceção deve ser detectada e tratada
  2. O código que potencialmente poderá gerar uma exceção é delimitada pelo bloco try
  3. Cada bloco try contém uma ou mais chamadas de método que podem causar uma exceção e cláusulas catch para todos os tipos de exceção que o bloco try pode tratar

Exemplo 1


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ExemploExcecao {

	public static void main(String[] args) {
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					System.in));
			System.out.println("Quantos anos voce tem ?");
			String inputLine = in.readLine();
			int idade = Integer.parseInt(inputLine);
			idade++;
			System.out.println("No proximo ano voce tera: " + idade);
		} catch (IOException exception) {
			System.out.println("Erro de I/O: " + exception);
		}
	}

}

                        

Considerações - Exemplo 1:

  • Caso não ocorra uma exceção
    • As linhas de código dentro do bloco try são executadas normalmente
    • O bloco catch é ignorado
  • Caso ocorra a exceção:
    • As linhas de código dentro do bloco try são executadas até o ponto que gerou a exceção (as demais linhas são ignoradas)
    • As instruções do bloco catch são executadas

Exemplo 2


package br.edu.ifrs.canoas.java.aula15;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ExemploExcecao2 {
	public static void main(String[] args) {
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					System.in));
			System.out.println("Quantos anos voce tem ?");
			String inputLine = in.readLine();
			int idade = Integer.parseInt(inputLine);
			idade++;
			System.out.println("No proximo ano voce tera: " + idade);
		} catch (IOException exception) {
			System.out.println("Erro de I/O: " + exception);
		} catch (NumberFormatException exception) {
			System.out.println("A entrada nao eh um numero ! ");
		}
	}
}

                        

Considerações - Exemplo 2:

  • Caso não ocorra uma exceção
    • As linhas de código dentro do bloco try são executadas normalmente
    • Os blocos catch são ignorado
  • Caso ocorra a exceção:
    • As linhas de código dentro do bloco try são executadas até o ponto que gerou a exceção (as demais linhas são ignoradas)
    • As instruções do bloco catch correspondente são executadas

Exemplo 3


pimport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ExemploExcecao3 {
	public static void main(String[] args) {
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					System.in));
			System.out.println("Quantos anos voce tem ?");
			String inputLine = in.readLine();
			int idade = Integer.parseInt(inputLine);
			idade++;
			System.out.println("No proximo ano voce tera: " + idade);
		} catch (IOException exception) {
			System.out.println("Erro de I/O: " + exception);
		} catch (NumberFormatException exception) {
			exception.printStackTrace();
			System.exit(1);
		}

	}
}
                        

Considerações - Exemplo 3:

  • Quando ocorre a exceção a cláusula catch pode analisar esse objeto para descobrir mais detalhes sobre a falha
  • Exemplo: exception.printStackTrace() obtêm a impressão da cadeia de chamadas de método que leva à exceção

Exemplo 4


package br.edu.ifrs.canoas.java.aula15;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ExemploExcecao4 {
	public static void main(String[] args) {
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					System.in));
			System.out.println("Quantos anos voce tem ?");
			String inputLine = in.readLine();
			int idade = Integer.parseInt(inputLine);
			idade++;
			System.out.println("No proximo ano voce tera: " + idade);
		} catch (Exception exception) {
			// detonamos as excecoes
			// na verdade elas nao foram tratadas
		}
	}

}
                     

Considerações - Exemplo 4:

  • Quando ocorre a exceção a cláusula catch não determina com precisão qual exceção ocorreu
  • Muito utilizado para o compilador não reclamar do verificação de exceções (porém não é bom utilizar)
  • Este tratador é fictício
  • Já as exceções foram projetadas para transmitir relatórios do problema para um tratador competente

Exemplo 5


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ExemploExcecao5 {
	public static void main(String[] args) {
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					System.in));
			System.out.println("Quantos anos voce tem ?");
			String inputLine = in.readLine();
			int idade = Integer.parseInt(inputLine);
			idade++;
			System.out.println("No proximo ano voce tera: " + idade);
		} catch (IOException exception) {
			System.out.println("Erro de I/O: " + exception);
		} catch (NumberFormatException exception) {
			System.out.println("A entrada nao eh um numero ! ");
		} finally {
			System.out.println("Eh sempre executado independentemente de ocorrer
	          				uma excecao ! ");
		}
	}
}
                     

Considerações - Exemplo 5:

  • Uso da cláusula finally
  • Quando é necessário fazer algo no caso de ocorrência de qualquer exceção
  • O código da cláusula finally é executado sempre que o fluxo de código sai do bloco try de qualquer uma das maneiras:
    • Após completar a última instrução do bloco try;
    • Quando uma exceção foi lançada no bloco try que está sendo passado para esse chamador do método;
    • Quando uma exceção foi lançada no bloco try que foi tratado por uma das cláusulas catch

Criando classes de exceção

  • Projetando seus próprios tipos de exceção
  • Nenhum tipo de exceção-padrão descreve com a clareza um erro específico
  • Projetar o seu próprio tipo de exceção pode projetar suas próprias subclasses de tipos de exceção Exception ou RuntimeException
  • Exemplo: saque em uma conta bancária

Exemplo 5

Exemplo: saque de uma conta bancária

...

public class Conta {
	public void saca (Double valor){
		if (valor > saldo) {
		      throw new InsufficientFundsException(
			“Saque de ” + valor + “ excede o saldo de ” + saldo);
		}
                    saldo = saldo – valor;
	}
   ...
}
...

                     

Criando classes de exceção

  • Criando a classe de exceção: Verificada ou não verificada ?
  • Estender Exception ou RuntimeException ?
  • Classe de exceção costuma fornecer dois construtores: default e outro que aceita uma string de mensagem descrevendo a razão da exceção

Classe InsufficientFundsException

Exemplo: saque de uma conta bancária

public class InsufficientFundsException extends RuntimeException {
	public InsufficientFundsException(){
	}
	public InsufficientFundsException(String reason){
		super(reason);
	}
}
                     

Implementações

Tratamento de Exceções

Exercícios


LPOO 1 - Java

Strings e Wrappers


LPOO 1 - Java

Strings

O Pacote java.lang

Strings

  • São objetos anônimos da classe String
  • São definidos por texto envolto em aspas duplas: "Isto é uma String literal"
  • Não necessitam ser instanciadas (new)
  • Podem ser atribuídas para variáveis String
  • Podem ser passadas como parâmetros
  • Possuem métodos que podem ser chamados

Strings

  • Um objeto da classe String representa uma string de caracteres

  • Como as outras classes, String possui construtores e métodos

  • Diferente de outras classes, String possui 2 operadores, + e +=, usados para concatenação

Strings


// Define um literal para uma variável String
String nome = "Rodrigo";

// Executando um método que pega o primeiro
// caractere da string "Rodrigo"
char primeiro = "Rodrigo".charAt(0);

// Executando um método na variável
char primeiro = nome.charAt(0);

                        
IMUTABILIDADE:
Uma vez criada, uma String não pode ter seu valor alterado, nenhum dos métodos altera o valor

Vantagem da Imutabilidade

Usa menos memória

Desvantagem da Imutabilidade

Menos eficiente – Necessário criar outro objeto para pequenas mudanças na String

  String word = “java";
  char ch = Character.toUpperCase(word.charAt (0));
  word =  ch + word.substring (1);
                        

String Vazia

  • Uma String vazia não possui caracteres, seu tamanho é zero

String word1 = "";
String word2 = new String();
                        
  • Não é o mesmo que uma String não-inicializada

  String word1; //não inicializada
private String errorMsg;

                        

Construtor sem argumentos

  • Construtor sem argumentos cria uma String vazia

String empty = new String();
                        
  • Geralmente utilizamos através de literal

String empty = "";      //nada entre as aspas
                        

Construtores para cópia

  • Cria uma cópia da String existente.
  • Não é o mesmo que uma atribuição

Construtores e Métodos

  • Possibilidade de transformar um array de char em uma String

char[] palavra = {‘J’, ‘a’, ‘v’, ‘a’};
String word = new String(palavra);//”Java”
                        
  • int length() – Retorna o tamanho da String
  • char charAt(i) – Retorna o caractere da posição i na String (iniciam em 0)

"Trabalho".length(); // retorna 8
"IFRS".charAt(2);    // retorna 'R'
                        

Métodos - substring

Retorna uma nova String copiando caracteres de uma String existente

Métodos - Concatenação


String word1 = "re", word2 = "think", word3 = "ing";
int num = 2;

String result = word1 + word2;
//concatena word1 e word2   "rethink"

String result = word1.concat (word2);
// o mesmo que word1 + word2  "rethink"

result += word3;
// concatena word3 à result  "rethinking"

result += num;
//converte num para String e concatena à result "rethinking2"
                        

Métodos - Pesquisa

Métodos - Igualdade e Case


b = "Teste".equals("Teste");//true
b = "Teste".equals("teste");//false
b = "Teste".equalsIgnoreCase("teste");//true

if("teste".equalsIgnoreCase(team))
	System.out.println(“Este é um “ + team);
                        

                        String word1 = "HeLLo";
                        String word2 = word1.toUpperCase();//”HELLO”
                        String word3 = word1.toLowerCase();//”hello”
                        //word1 ainda é “HeLLo“
                        

Métodos - Trim e Replace


String word1 = " Oi Bob ";
String word2 = word1.trim();
//word2 é "Oi Bob" – sem espaços no início ou no final, não remove espaços do meio
//word1 ainda é " Oi Bob " – com espaços
                        

//String word2 = word1.replace(oldCh, newCh);
//retorna uma nova string formada de word1 substituindo todas as ocorrências de oldCh por newCh

String word1 = "raro";
String word2 = "raro".replace('r', 'd');
//word2 é "dado", mas word1 ainda é "raro"

                        

Números em Strings


//3 maneiras para converter:
//String s = “” + num
s = “” + 123;//”123”

//String s = Integer.toString (i)
//String s = Double.toString (d)
s = Integer.toString(123);//”123”
s = Double.toString(3.14); //”3.14”

//String s = String.valueOf(num)
s = String.valueOf(123);//”123”
                        

Wrappers

Wrappers

  • Objetos que tem relação direta com dados primitivos
  • Objetos permitem a passagem por referência
  • Conjunto de métodos para manipulação
  • Para cada dado primitivo existe um empacotador correspondente
  • Consultar documentação da API (pertencem ao pacote java.lang)

Wrappers x Tipos Primitivos

Tipo Primitivo Classe Wrapper
boolean Boolean
char Character
int Integer
long Long
float Float
double Double

Integer


                        public class WrapperTest {

                        public static void main(String[] args) {

                        // criando um objeto Integer a partir de um int
                        int i1 = 1; //int --> Integer
                        Integer objInt1 = new Integer(i1);


                        // criando um int a partir de um objeto Integer
                        int i2 = objInt1.intValue(); //Integer --> int
                        ...
                        

Integer


	Integer num1 = new Integer(10);
	Integer num2 = new Integer(10);
	// testando valores
	if (num1.equals(num2) == true)
      System.out.println("Valores sao iguais !");
	else
       System.out.println("Valores sao diferentes !");
	// testando referencias
	if(num1==num2)
	   System.out.println("As referencias sao iguais !");
	else
	   System.out.println("As referencias sao diferentes !");
    //Valores sao iguais !
    //As referencias sao diferentes !

                        

Funções Úteis

  • Integer.parseInt(String)
  • Integer.toOctalString(int)
  • Float.parseFloat(String)
  • Float.toHexString(Float)
  • Boolean.getBoolean(String)
  • Double.parseDouble(String)

Autoboxing / Unboxing

Esse processo de wrapping e unwrapping é entediante. O Java 5 em diante traz um recurso chamado de autoboxing, que faz isso sozinho para você, custando legibilidade.
  • Autoboxing:
    • Cast implícito de um tipo primitivo para a classe wrapper correspondente;
    • Integer x = 5;
  • Unboxing:
    • Inverso do autoboxing, transformação de um objeto wrapper em tipo primitivo.
    • Integer x = 5;
    • int y = x;

Autoboxing / Unboxing


Integer i1 = 1000;
Integer i2 = 1000;
if(i1 != i2)
    System.out.println("objetos diferentes");
if(i1.equals(i2))
    System.out.println("mesmo significado");
//objetos diferentes
//mesmo significado
                        

Exercícios

  1. Escreva um método que usa os métodos charAt e length de uma String para imprimir a mesma caractere a caractere, de trás para frente, com cada caractere em uma linha diferente. Exemplo: palavra “terra” retorna em linhas diferentes ‘a’, ‘r ‘, ‘r’, ‘e’, ‘t’
  2. Dada uma frase, reescreva essa frase com as palavras na ordem invertida. "Seria cômico, se não fosse trágico” deve retornar "trágico fosse não se cômico, Seria”. Pesquise e utilize o método split da String para te auxiliar.

Implementações

Strings e Wrappers


LPOO 1 - Java

Pacotes


LPOO 1 - Java

Pacotes

Os pacotes estão diretamente relacionados com os diretórios e costumam agrupar classes de funcionalidades similares ou relacionadas.

Padrão de Nomenclatura de Pacotes

O padrão da Sun para nomear aos pacotes é relativo ao nome da empresa que desenvolveu a classe:

  • br.com.nomedaempresa.nomedoprojeto.subpacote
  • br.com.nomedaempresa.nomedoprojeto.subpacote2
  • br.com.nomedaempresa.nomedoprojeto.subpacote2.subpacote3

Os pacotes só possuem letras minúsculas, não importa quantas palavras estejam contidas nele.

Referência Oracle: https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html

Implementações

Pacotes


LPOO 1 - Java

Implementações

Exercícios: Coleções e Exceções


LPOO 1 - Java