Observações sobre a sintaxe, boas práticas

Computação II - Ciência da Computação


Prof.: Danilo S. Carvalho

Nessa aula vamos falar sobre alguns pontos fundamentais da sintaxe da linguagem Java.


Ao final da aula, saberemos como escrever programas básicos e como criar nossos próprios métodos.


Como há bastante coisa em comum com a linguagem C, é importante notar certas diferenças para não causar confusão.

Os comentários no Java são escritos da seguinte forma:

Para uma linha, começamos a linha com // .

Para múltiplas linhas abrimos o comentário com /* e fechamos com */.

                        
                            // Comentários de uma linha são escritos assim.
                            /*
                                Para múltiplas linhas,
                                escrevemos assim.
                            */
                        
                    
                        
                            // Comentários de uma linha são escritos assim.
                            /*
                                Para múltiplas linhas,
                                escrevemos assim.
                            */
                        
                    
                        
                            // Comentários de uma linha são escritos assim.
                            /*
                                Para múltiplas linhas,
                                escrevemos assim.
                            */
                        
                    

A declaração e atribuição de variáveis é feita de forma similar ao C.

Para declarar, informamos o tipo e o nome.

Atribuimos com = .

Podemos declarar e atribuir uma variável na mesma linha.

                        
                            int quantidade;
                            quantidade = 5;
                        
                    
                        
                            int quantidade;
                            quantidade = 5;
                        
                    
                        
                            int quantidade = 5;
                        
                    

Os tipos em Java podem ser divididos entre primitivos e complexos.

Os tipos primitivos são listados abaixo:

boolean: verdadeiro ou falso.

byte: um byte inteiro [-128, +127].

char: um caracter Unicode de 16 bits.

short: um inteiro de 16 bits [-32,768, +32,767].

int: um inteiro de 32 bits [-2^31, +2^31 - 1].

long: um inteiro de 64 bits [-2^63, +2^63 - 1].

float: número real de 32 bits (IEEE 754).

double: número real de 64 bits (IEEE 754).

Não há tipos sem sinal (unsigned) em Java.

Todos os demais tipos do Java (classes, interfaces) são tipos complexos.

                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    
                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    
                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    
                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    
                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    
                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    
                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    
                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    
                        
                            boolean bool = false;
                            byte b = 0; // [-128, +127]
                            char c = '\u0000'; // Unicode 16 bits, de '\u0000' até '\uffff'
                            short sInt = 0; // [-32,768, +32,767]
                            int i = 0; // [-2^31, +2^31 - 1]
                            long l = 0L; // [-2^63, +2^63 - 1]
                            float f = 0.0f; // 32-bit IEEE 754 (igual ao C)
                            double d = 0.0d; // 64-bit IEEE 754 (igual ao C)
                        
                    

Quando um valor de tipo primitivo é atribuído a uma variável, esse valor é copiado para o espaço em memória ocupado pela variável.

Em um tipo complexo, como o tipo String, apenas a referência ao valor é copiada.

Dessa forma a variável atribuída passa a apontar para o mesmo espaço na memória do conteúdo que lhe foi atribuído.

                        
                            int x = 3;
                            float z = x;  // Valor de x recebe promoção de tipo para float, 
                                          // e é copiado para z.
                        
                    
                        
                            String ola = "Olá mundo";
                            String texto = ola;  // Apenas referência é copiada. Agora "ola" e "texto"  
                                                 // apontam para o mesmo espaço na memória
                        
                    

Strings no Java representam uma sequência imutável de caracteres.

Podemos acessar caracteres individuais da string usando o método charAt, mas não podemos alterá-los.

Atribuir uma string significa trocar a referência da variável.

                        
                            String str;
                            str = "Isso é uma string";
                        
                    
                        
                            String str;
                            str = "Isso é uma string";
                            str.charAt(5);  // == 'é'
                        
                    
                        
                            String str;
                            str = "Isso é uma string";
                            str.charAt(5);  // == 'é'
                            str = "Isso é uma nova string";  // Substituição da referência.
                        
                    

É importante também saber como escrever os literais apropriados para cada tipo.

Podemos escrever os tipos inteiros usando diferentes bases numéricas.

Podemos escrever literais double usando notação científica.

Os literais float devem ser terminados com "f".

                        
                            // O número 26, em decimal.
                            int decVal = 26;
                            // O número 26, em hexadecimal.
                            int hexVal = 0x1a;
                            // O número 26, em binário.
                            int binVal = 0b11010;
                            double d1 = 123.4;
                            // O mesmo valor que acima, mas em notação científica.
                            double d2 = 1.234e2;
                            // Literal float
                            float f1 = 123.4f;
                        
                    
                        
                            // O número 26, em decimal.
                            int decVal = 26;
                            // O número 26, em hexadecimal.
                            int hexVal = 0x1a;
                            // O número 26, em binário.
                            int binVal = 0b11010;
                            double d1 = 123.4;
                            // O mesmo valor que acima, mas em notação científica.
                            double d2 = 1.234e2;
                            // Literal float
                            float f1 = 123.4f;
                        
                    
                        
                            // O número 26, em decimal.
                            int decVal = 26;
                            // O número 26, em hexadecimal.
                            int hexVal = 0x1a;
                            // O número 26, em binário.
                            int binVal = 0b11010;
                            double d1 = 123.4;
                            // O mesmo valor que acima, mas em notação científica.
                            double d2 = 1.234e2;
                            // Literal float
                            float f1 = 123.4f;
                        
                    
                        
                            // O número 26, em decimal.
                            int decVal = 26;
                            // O número 26, em hexadecimal.
                            int hexVal = 0x1a;
                            // O número 26, em binário.
                            int binVal = 0b11010;
                            double d1 = 123.4;
                            // O mesmo valor que acima, mas em notação científica.
                            double d2 = 1.234e2;
                            // Literal float
                            float f1 = 123.4f;
                        
                    

Arrays são sequências de valores de um mesmo tipo (vetores).

Apesar da notação similar, funcionam de maneira diferente da linguagem C.

Em Java, é possível definir o tamanho de um array através de uma variável.

Entretanto, não é possível modificar o tamanho do array uma vez que foi criado.

O acesso aos elementos do array é feito através do índice do valor, tanto para leitura quanto para atribuição.

                        
                            int[] numeros = new int[30];
                            // Alocação dinâmica?
                            int n = 100;
                            float[] maisNumeros = new float[n];
                        
                    
                        
                            int[] numeros = new int[30];
                            // Alocação dinâmica?
                            int n = 100;
                            float[] maisNumeros = new float[n];
                        
                    
                        
                            int[] numeros = new int[30];
                            // Alocação dinâmica?
                            int n = 100;
                            float[] maisNumeros = new float[n];
                        
                    
                        
                            int[] numeros = new int[30];
                            // Alocação dinâmica?
                            int n = 100;
                            float[] maisNumeros = new float[n];
                            maisNumeros[2] = 12.3f;
                        
                    

Os operadores aritméticos funcionam da mesma maneira que em C.

As 4 operações básicas realizam promoção de tipo para operandos de tipos diferentes mas compatíveis.

Isso quer dizer que o resultado da operação será do tipo menos restritivo.

Por exemplo o resultado da multiplicação z * x abaixo é do tipo float (float * int = float).

A divisão entre inteiros tem resultado inteiro (truncado).

                        
                            int w;
                            int x = 3;
                            int y = 7;
                            float z = x + y;  // - *
                            z = z * x;
                            w = y / 2;  // truncamento
                            int modulo = y % 2;
                        
                    
                        
                            int w;
                            int x = 3;
                            int y = 7;
                            float z = x + y;  // - *
                            z = z * x;
                            w = y / 2;  // truncamento
                            int modulo = y % 2;
                        
                    
                        
                            int w;
                            int x = 3;
                            int y = 7;
                            float z = x + y;  // - *
                            z = z * x;  // promoção de tipo
                            w = y / 2;  // truncamento
                            int modulo = y % 2;
                        
                    
                        
                            int w;
                            int x = 3;
                            int y = 7;
                            float z = x + y;  // - *
                            z = z * x;
                            w = y / 2;  // truncamento
                            int modulo = y % 2;
                        
                    

Os operadores booleanos realizam comparações e operações lógicas com os operandos.

Todos funcionam como no C, mas é importante lembrar da diferença entre tipos primitivos e complexos.

Os operador de igualdade no Java (e sua negação) comparam o valor armazenado das variáveis.

O valor será uma referência no caso de uma variável de tipo complexo.

                        
                            int a = 3;
                            int b = 4;
                            boolean result;
                            result = a < b; // true
                            result = a > b; // false
                            result = a <= 3; // menor igual
                            result = b >= 5; // maior igual
                            result = a == b; // igualdade de valor
                            result = a != b; // diferença de valor
                            result = a > b || a < b; // OR lógico
                            result = 2 < a && a < 5; // AND lógico
                            result = !result; // NOT lógico
                        
                    
                        
                            int a = 3;
                            int b = 4;
                            boolean result;
                            result = a < b; // true
                            result = a > b; // false
                            result = a <= 3; // menor igual
                            result = b >= 5; // maior igual
                            result = a == b; // igualdade de valor
                            result = a != b; // diferença de valor
                            result = a > b || a < b; // OR lógico
                            result = 2 < a && a < 5; // AND lógico
                            result = !result; // NOT lógico

                        
                    

Outra coisa importante: expressões booleanas tem como resultado um tipo booleano.

Isso quer dizer que podem ser atribuídas a uma variável do tipo boolean.

Mas não podem ser atribuidas a uma variável de tipo inteiro.

                        
                            boolean test;
                            test = numeros[1] < numeros[5]; // um booleano "de verdade".
                        
                    
                        
                            boolean test;
                            test = numeros[1] < numeros[5]; // um booleano "de verdade".
                            int testInt = numeros[1] < numeros[5];  // Erro de compilação.
                        
                    

Métodos são, de maneira simplificada, funções associadas a uma classe.

Como todo o código Java está contido em classes, todas as nossas funções serão escritas como métodos.

O modificador public informa que o método estará visível (portanto disponível para uso) por outras classes, além daquela onde foi declarado.

Falaremos sobre o modificador static mais adiante. Ele é necessário aqui para que nossos métodos se comportem de forma similar à linguagem C.

Parâmetros e retorno de um método podem ser de qualquer tipo, tendo em mente as diferenças entre tipos primitivos e complexos.

Parâmetros primitivos passam valores e complexos passam referências. O mesmo ocorre com os retornos.

                        
                            public static int soma(int x, int y) {
                                // Retorna um valor inteiro.
                                return x + y;
                            }
                        
                    
                        
                            public static String concat(String x, String y) {
                                // Retorna referência para nova string.
                                return x + y;  // Operador "+" concatena strings.
                            }
                        
                    

O if .. else if .. else é a principal estrutura condicional do Java, funcionando da mesma forma que em C.

                        
                            if (a == b) {
                                // Faz alguma coisa
                            }
                            else if (a == c) {
                                // Faz alguma outra coisa
                            }
                            else {
                                // Faz o que não pôde ser feito nas condições anteriores
                            }
                        
                    

A estrutura de condicional ternária também pode ser utilizada.

As duas condicionais abaixo são equivalentes:

                        
                            String saudacao = (turno == "dia") ? "Bom dia!" : "Boa tarde";
                        
                    
                        
                            String saudacao = (turno == "dia") ? "Bom dia!" : "Boa tarde";

                            String saudacao;
                            if (turno == "dia") {
                                saudacao = "Bom dia!";
                            }
                            else {
                                saudacao = "Boa tarde";
                            }
                        
                    

O bloco de seleção switch também existe no Java.

E funciona inclusive com strings (se a JDK >= 7).

                        
                            int x = numeros[3];
                            switch(x) {
                                case 9:
                                    System.out.println("Oi!");
                                    break;
                                case 11:
                                    System.out.println("Tchau!");
                                    break;
                                default:
                                    System.out.println("Muito estranho");
                            }
                        
                    
                        
                            
                            switch(fase) {
                                case "Início":
                                    System.out.println("Oi!");
                                    break;
                                case "Fim":
                                    System.out.println("Tchau!");
                                    break;
                                default:
                                    
                            }
                        
                    

Os loops for, while e do .. while estão presentes no Java de forma idêntica ao C.

Mas o Java também possui outras formas de loop,

por exemplo, o chamado loop for-each, que executa as instruções do corpo do loop para cada elemento de um tipo iterável, tal como um array.

                        
                            int soma = 0;

                            for(int i = 0; i <= 30; i++) {
                                if(i == 12) {
                                    continue; // vai direto para a próxima iteração
                                }
                                if(i == 15) {
                                    break; // sai completamente do loop
                                }
                                else {
                                    soma += numeros[i];
                                }
                            }
                        
                    
                        
                            int soma = 0;

                            for (int x : numeros) {
                                soma += x;
                            }
                        
                    

Por fim, vamos escrever um método usando loops e condicionais.

Nosso método vai calcular os divisores de um número inteiro dado e imprimí-los no terminal.

Colocamos um nome e parâmetro apropriado no método.

Em seguida iteramos a partir de 1 até o número dado...

verificando para cada valor se esse divide o número...

e caso sim imprimindo o valor.

Podemos então chamar o método imprimirDivisores dentro do método main.

                        
                            public static void imprimirDivisores(int numero) {

                            }
                        
                    
                        
                            public static void imprimirDivisores(int numero) {
                                for(int i=1; i <= numero; i++) {
                                    
                                }
                            }
                        
                    
                        
                            public static void imprimirDivisores(int numero) {
                                for(int i=1; i <= numero; i++) {
                                    if(numero % i == 0) {
                                        
                                    }
                                }
                            }
                        
                    
                        
                            public static void imprimirDivisores(int numero) {
                                for(int i=1; i <= numero; i++) {
                                    if(numero % i == 0) {
                                        System.out.println(i);
                                    }
                                }
                            }
                        
                    
                        
                            public class Divisores {
                                public static void imprimirDivisores(int numero) {
                                    for(int i=1; i <= numero; i++) {
                                        if(numero % i == 0) {
                                            System.out.println(i);
                                        }
                                    }
                                }

                                public static void main (String[] args) {
                                    imprimirDivisores(35);
                                }
                            }
                            
                        
                    

Com o que vimos até aqui, é possível criar vários tipos de programa que não dependem de entrada do usuário.


Tentem criar novos métodos com parâmetros e retornos de tipos diferentes.

Perguntas:

  1. O que acontece se tentarmos criar um array com tamanho negativo?
  2. E se tentarmos criar um array com mais elementos que a memória do computador pode armazenar?
  3. Quando atribuimos um int a uma variável, o que acontece com o valor anterior da variável? E uma String?

Até a próxima aula!