POO – AULA 06 Objetivos da aula Diferenciar tipos primitivos de dados e tipos de referência a objetos Entender o uso dos operadores aritméticos, lógicos e relacionais Aprender a sintaxe e semântica das estruturas de controle de fluxo Tratar entradas de dados Recordando... Nas aulas passadas, criamos algumas aplicações Java para ilustrar os conceitos de POO apresentados. Nestas aplicações usamos variáveis de diversos tipos, operadores e alguns comandos de decisão e repetição. Hoje veremos esses tipos e comandos detalhadamente. Também veremos como ler dados do teclado, pois até agora só imprimimos dados. Tipos primitivos e tipos de referência Em Java, trabalhamos com dois tipos de dados: primitivos e de referência, estes também denominados como não primitivos. Primitivos: Tipo boolean byte char short int long float double Quant. bits 1 8 16 16 32 64 32 64 Valores armazenáveis na variável True ou False –128 até 127 ( -27 a 27-1 ) ‘\u0000’ a ‘\uFFFF’ (0 a 65535) –32768 até 32767 ( -215 a 215-1 ) –2.147.483.648 até 2.147.483.647 (-231 a 231-1 ) (-263 a 263-1 ) 1,40 X 10-45 a 3,40 X 1038 4,94 X 10-324 a 1,70 X 10308 Uma variável de tipo primitivo pode armazenar exatamente um valor do seu tipo declarado. Variáveis de tipo de referência são utilizadas para armazenar as localizações de objetos na memória do computador. Diz-se que estas variáveis referenciam objetos. Os atributos de tipo primitivo são iniciados por ocasião da instanciação do objeto. Os atributos de tipos byte, char, short, int, long, float e double são iniciadas com zero, as variáveis do tipo boolean com false. Podem ser especificados valores iniciais para variáveis destes tipos quando de sua declaração. Variáveis locais de métodos não são iniciadas automaticamente. As variáveis de instância de tipo de referência são iniciadas por padrão com o valor null – palavra reservada que representa uma “referência a nada”. Somente depois que o objeto é instanciado é que a variável contém uma referência para o objeto. Por exemplo, o comando: Curso meuCurso = new Curso(); cria uma instância (objeto) da classe Curso, e a variável meuCurso contém uma referência a esse objeto. A partir de então, a variável pode ser usada para chamar métodos do objeto ou referenciar seus atributos. 1 Usando Operadores Significado Ex. Op. Significado Ex. + Adição a+b % Resto da divisão a%b - Subtração a-b - Menos unário -a * Multiplicação a*b ++ Incremento unário ++a ou a++ / Divisão a/b -- Decremento unário --a ou a-- relacionais Tipo == Igual a==b >= Maior ou igual a>=b != Diferente a!=b < Menor que a<b > Maior que a>b <= Menor ou igual a<=b && E lógico a&&b ! Negação !a || OU lógico a||b aritméticos Op. lógicos O Java oferece um conjunto amplo de operadores aritméticos, relacionais e lógicos. Veja a tabela abaixo: Estruturas de Controle do Fluxo Java contém três tipos de estruturas de controle (instruções): seqüência, seleção e repetição. Um programa é formado pela combinação destas estruturas, de forma a implementar o que o algoritmo determina. A estrutura de seqüência permite aglutinar vários comandos em um bloco de comandos delimitado por chaves ({...}). Isto deve ser feito sempre que queiramos delimitar os comandos que façam parte de uma outra estrutura de controle de decisão ou repetição (if/else, switch, for, while, etc.). Instruções de Seleção Comando if O if é uma instrução que permite a seleção entre dois caminhos distintos, conforme a avaliação de uma condição lógica como falsa ou verdadeira. if (expressão lógica)comando1; else comando2; Exemplo: if ( nota >= 6 ) System.out. println (“Aprovado”); else System.out. println (“Reprovado”); A parte do else é opcional. Comando1 e Comando2 podem ser blocos de comandos. O 2 compilador Java sempre associa um else à instrução if imediatamente anterior, a menos que instruído de outro modo pela colocação das chaves Operador condicional ternário Como já vimos em aulas anteriores, em algumas situações podemos usar o operador “?”, que realiza a mesma operação do comando if. Ex: System.out.println(nota > 6 ? “Aprovado”:“Reprovado”); Comando switch Este comando equivale a um conjunto de if encadeados: switch (expressão ordinal) case ordinal1: comando1; case ordinal2: comando2; case ordinalN: comandoN; default: comandoDefault; } { break; break; break; Exemplo: switch (opcao) { case ‘a’: case ‘A’: System.out.println(“letra A”); break; case ‘b’: case ‘B’: System.out.println(“letra B”); break; default: System.out.println(“letra invalida”); } Estruturas de Repetição Comando for O comando for é indicado para repetirmos um trecho de código uma quantidade fixa de vezes. Sua sintaxe possui três seções opcionais: for (seção1; seção2; seção3) comando; a seção1 é executada apenas uma vez e geralmente é usada para iniciar uma variável de controle do for. A seção2 é executada antes de cada iteração do for e habilita a execução de mais uma iteração, caso verdadeira (true). Geralmente é usada para testar a variável de controle do for. A seção3 é executada ao final de cada iteração do for e geralmente é usada para incrementar a variável de controle. Exemplo: for (int i = 0; i < 4;i++) System.out.printf(“%d ”,i); //imprime de 0 a 3 Comandos while / do O comando while é indicado quando desejamos repetir um trecho de código uma quantidade indefinida de vezes, enquanto uma determinada condição for verdadeira. Sintaxe: 3 while (expressão lógica) comando1; Exemplo: while ( produto <= 100 ) produto = 3 * produto; Caso a condição seja inicialmente falsa, nenhuma iteração será executada. Nos casos em que desejamos executar pelo menos uma vez os comando da repetição, devemos usar o comando do / while, Cuja sintaxe é a que se segue: do comando1; while (expressão lógica); Veja o exemplo: do produto = 3 * produto; while ( produto <= 100 );// testa após ter executado // pelo menos uma vez Lendo Valores do Teclado Até agora, nossas aplicações apenas escreviam valores na tela de console. Fizemos isso usando (embora sem ter sido ainda explicado) um Stream de dados. Um Stream é um canal que conduz os dados de um lugar (um arquivo ou um dispositivo) para outro. A stream de saída padrão (out) está na classe Java.lang.System e é aberta automaticamente pela máquina virtual Java, já associada ao dispositivo de saída padrão (display). Já a stream de entrada padrão (in), disponível estaticamente através da mesma classe Java.lang.System, é de utilização bastante precária, na medida em que disponibiliza métodos apenas de acesso a bytes, de forma que, para que se leia valores inteiros, reais ou strings, é necessário ir concatenando bytes para formar a entrada desejada. Assim, não utilizaremos essa forma de entrada e sim uma classe mais elaborada, disponível na biblioteca java.util.Scanner, que permite a chamada de métodos para ler diretamente strings, números inteiros e números reais. Para utilizá-la, é necessário instanciar um objeto da classe Scanner e chamar um método apropriado para ler cada um dos tipos básicos ou String de um dispositivo qualquer. Por exemplo, para ler do dispositivo padrão de entrada, podemos ter o seguinte código: // cria Scanner para ler entrada na janela de comando Scanner entrada = new Scanner( System.in ); // faz Scanner ler variáveis de diferentes tipos palavra = entrada.next() // lê String até <branco> nome = entrada.nextLine() // lê String até <ENTER> valorI = entrada.nextInt() // lê valor inteiro valorF = entrada.nextFloat() // lê valor float valorD = entrada.nextDouble() // lê valor double valorB = entrada.nextBoolean() // lê valor boolean 4 Além de ler os valores, podemos também testar se o valor é do tipo esperado, através de métodos que retornam valores lógicos. Por exemplo: if if if if (entrada.hasInt()) { // true, se entrada inteira (entrada.hasFloat()) { // true, se entrada float (entrada.hasDouble()) { // true, se entrada double (entrada.hasBoolean()) { // true,se entrada boolean Aplicando os Conceitos Aprendidos Para consolidar os conceitos de operadores, estruturas de controle e criação de interfaces, vamos criar uma aplicação diferente da que vínhamos fazendo nas aulas passadas. Nossa aplicação possuirá apenas uma classe (Curso), que guardará seu próprio nome, o nome de um aluno e as notas das três avaliações desse aluno no curso. A classe oferece métodos de get e set para seus atributos e um método que avalia se o aluno foi aprovado ou reprovado, de acordo com as notas das avaliações, retornando um String com essa avaliação final. Para julgar se o aluno foi aprovado, é feita a média das duas maiores notas e o aluno estará aprovado se esta for maior ou igual a 6,0. public class Curso { private String nomeCurso; private String nomeAluno; private float notas[]; public Curso(String nomeCurso,String nomeAluno) { this.nomeCurso = nomeCurso; this.nomeAluno = nomeAluno; notas = new float[3]; } public void setNomeCurso( String nomeCurso ) { this.nomeCurso = nomeCurso; } public String getNomeCurso() return nomeCurso; } { public void setNomeAluno( String nomeAluno ) { this.nomeAluno = nomeAluno; } public String getNomeAluno() return nomeAluno; } { public void setNotas (float nota, int posicao){ notas[posicao] = nota; } public float calcularMedia() { int indNota=0; // indice das notas float piorNota=11; // valor da nota a descartar int indPiorNota=0; // indice da nota a descartar while ( indNota < 3 ) { // descobre a pior nota 5 if (notas[indNota] < piorNota){ piorNota = notas[indNota]; indPiorNota = indNota; } indNota++; } // fim do while switch (indPiorNota){//media das 2 melhores case 0: return ((notas[1]+notas[2])/2); case 1: return ((notas[0]+notas[2])/2); case 2: return ((notas[0]+notas[1])/2); } return 0; } // fim do método calcularMedia public String determinarSituacao() { String situacao; if (calcularMedia() >= 6.0) situacao = "APROVADO(A)"; else situacao = "REPROVADO(A)"; return String.format( "\n%s %s %s %s %s %s %s %.2f\n\n", "O(a) aluno(a)",getNomeAluno(),"foi", situacao,"no curso",getNomeCurso(), "com media",calcularMedia()); } // fim do método determinarSituacao } // fim da classe LivroNotas A classe da aplicação de teste possui o seguinte código: import java.util.Scanner; // Classe Scanner public class AppCurso { public static void main( String args[] ) { float nota; String curso="",aluno=""; //inicia Strings // cria Scanner para ler entrada do console Scanner entrada = new Scanner( System.in ); System.out.printf("\nEntre com nome do curso: "); curso = entrada.nextLine() ; System.out.printf("\nEntre com nome do aluno: "); aluno = entrada.nextLine(); Curso meuCurso = new Curso(curso,aluno); for (int cont=0; cont<3; cont++){ System.out.printf("\nDigite a nota %d: ",cont+1); nota = entrada.nextFloat(); // lê a próxima nota meuCurso.setNotas(nota,cont); } System.out.printf("%s", meuCurso.determinarSituacao()); } // fim de main 6 } // fim da classe AppCurso Compile e execute os códigos das classes acima. Desafios 1. Coloque na classe Curso um atributo frequencia, que represente o percentual de aulas assistidas pelo aluno. Modifique o método determinarSituacao para que considere um percentual mínimo de 75% para considerar o aluno aprovado. 2. Substitua o comando for da classe de teste pelo comando do/while. 7