Certificação Marco Antonio Introdução • A compreensão desse capítulo é muito importante pois trata de um assunto essencial em qualquer linguagem de programação, as diversas formas de se atribuir e manipular valores de uma variável. • Além de ser um dos elementos fundamentais de uma linguagem de programação, as variáveis tem um papel importante na geração de programas e suas peculiaridades serão abordadas nesse capítulo. Atribuição • A forma mais elementar de se atribuir um valor a uma variável é: int x = 0; Atribuições • byte x = 19; // ok byte y = x; // ok byte z = x + y; // deveria aceitar, mas necessita de uma conversão explícita. Objetos • • • • Button b = new Button(); O que b armazena? Um objeto do tipo Button? b armazena um conjunto de bits usados para acessar (referenciar) o objeto na memória. • Portanto, podemos dizer a rigor que b não é um objeto do tipo Button e sim uma forma (através de uma sequência de bits) usada para acessar esse objeto na memória. Atribuição de primitivos • byte a = 19; byte a = (byte)19; byte b = 128; // Não é possível sem uma conversão explícita byte c = (byte)128; // Ok Atribuições • O valor 128 não pode ser atribuído à variável b por ultrapassar a capacidade em bits do tipo byte - uma conversão se faz necessária. • Mas devemos ressaltar um acontecimento muito interessante nesse caso. Qual o valor da variável c da atribuição anterior? Atribuição de objetos class Carro { public double preco = 0; } class Audi extends Carro { } 1. public class Teste { 2. public static void main(String[] args) { 3. Carro a = new Carro(); 4. Audi b = new Audi(); 5. Carro c = new Audi(); 6. Audi d = new Carro(); 7. } 8. } Questão • Qual das linhas anteriores estão incorretas e não permitiriam que o programa fosse compilado ? a) 1, 3 b) 2, 3 c) 5 d) 6 e) o código será compilado Passagem de valores primitivos • Existe muita discussão quando o assunto é a forma como a Java passa um variável (primitiva ou referência) para um método. • Quando uma variável é passada para um método, SEMPRE será passado um cópia dos seus bits!! Classes public class Teste { public static void main(String[] args) { byte x = 10; System.out.println("X antes: "+x); altera(x); System.out.println("X depois: "+x); } public static void altera(byte a) { a = 2; } } Passando referências • Uma variável de referência nada mais é que um repositório de bits que representam um forma de se acessar um objeto na memória. • A variável é uma coisa o objeto que está na memória é outra. Classes public class Teste { public static void main(String[] args) { Carro c = new Carro(); c.preco = 13990.00; System.out.println("preço antes: "+c.preco); anula(c); System.out.println("preço depois: "+c.preco); } public static void anula(Carro p) { p = null; } } Resultado • preço antes: 13990.0 • preço depois: 13990.0 • A cópia da referência do objeto não se altera. Classes public class Teste { public static void main(String[] args) { Carro c = new Carro(); c.preco = 13990.00; System.out.println("preço antes: "+c.preco); aumento(c); System.out.println("preço depois: "+c.preco); } public static void aumento(Carro p) { p.preco = p.preco * 2; } } Resultado • preço antes: 13990.0 • Preço depois: ? • O valor alterado, mesmo na cópia da referência, altera o valor do objeto principal. Operador Condicional • O operador condicional é um operador ternário, ou seja, três operandos e deve ser usado quando se necessita realizar uma condição em uma única linha. • Veja o código abaixo: int tamanho = 19; String texto = (tamanho>=10)?"Maior ou igual a 10":"Menor que 10"; System.out.println(texto); Operador instanceof • Operador binário (dois operandos) que é utilizado para saber se um objeto é instância de uma classe. Código • String nome = "kuesley"; if (nome instanceof String) { System.out.println("nome é do tipo String"); } else { System.out.println("nome não é do tipo String"); } Classe public class Veiculo { } public class Audi extends Veiculo { } public class Teste { public static void main(String[] args) { Audi a = new Audi(); Veiculo v = new Veiculo(); if (a instanceof Audi) System.out.println("a é do tipo Audi"); if (v instanceof Veiculo) System.out.println("v é do tipo Veiculo"); if (v instanceof Audi) System.out.println("v é do tipo Audi"); if (a instanceof Veiculo) System.out.println("a é do tipo Veículo"); } } • a é do tipo Audi // a que é instância da classe Audi é membro de Audi • v é do tipo Veiculo // v que é instância da classe Veiculo é membro de Veiculo • a é do tipo Veiculo // a que é uma instância da classe Audi é membro de veículo, pois a classe Audi é uma sub-classe de Veiculo. Classes public interface Acao { } public class Veiculo implements Acao { } public class Audi extends Veiculo { } public class Moto { } public class Teste { public static void main(String[] args) { Audi a = new Audi(); Veiculo v = new Veiculo(); Moto m = new Moto(); if (a instanceof Acao) System.out.println("a é membro de Acao"); if (v instanceof Acao) System.out.println("v é membro de Acao"); if (m instanceof Acao) System.out.println("m é membro de Acao"); } } Resultado • a é membro de Acao • v é membro de Acao Arrays • Um array de primitivos (1,2,3,4) é, antes de qualquer coisa, um objeto. Arrays public class Teste { public static void main(String[] args) { boolean c = (new int[] { 1,2,3 } instanceof Object); System.out.println(c); } } • Aqui temos um array anônimo, conforme visto anteriormente. Resultado • Qual o resultado do instanceof? Classes class Veiculo { } class Audi extends Veiculo { } public class Teste { public static void main(String[] args) { Audi a = new Audi(); Veiculo v = new Veiculo(); boolean b1 = (a instanceof Audi); // ok - b1 é true boolean b2 = (a instanceof Veiculo); // ok - b2 é true boolean b3 = (v instanceof Audi); // ok - b3 é false boolean b4 = (a instanceof String); // erro de compilação } } Sombreamento de variáveis • Uma área interessante da Java é a forma como trata os sobreamentos de variáveis. • Pense em uma classe com um membro inteiro chamado tamanho, imagine ainda que você crie um método e internamente você também crie um variável local chamada tamanho, o que acontecerá? Classes public class Teste { static int tamanho = 0; public static void main(String[] args) { tamanho = 9; System.out.println("Antes: "+tamanho); crescer(2); System.out.println("Depois: "+tamanho); } public static void crescer(int tamanho) { tamanho = tamanho + 1; } } Resultado • A variável tamanho dentro do escopo do método que está sendo usada, não é a mesma declarada como membro da classe. • Agora se alterarmos um pouco o código como segue teremos um resultado diferente: Classes public class Teste { int tamanho = 0; public static void main(String[] args) { Teste t = new Teste(); t.tamanho = 9; System.out.println("Antes: "+t.tamanho); t.crescer(2); System.out.println("Depois: "+t.tamanho); } public void crescer(int tamanho) { this.tamanho = tamanho + 1; } } Observação • Você não pode colocar a palavra this no método crescer, porque uma variável static nunca poderá ser referenciado por um contexto não-estático, e a palavra this quer dizer que é de um objeto. Operadores matemáticos • Uma observação que é importante ser ressaltada é que toda operação envolvendo números inteiros resultarão em um tipo int, mesmo sendo byte * short, ou byte / int. • Como você sabe, não é possível realizar divisão por zero para números inteiros, mas em número de pontos flutuantes isso é possível podendo retornar um 0 positivo ou um 0 negativo. Operadores • Unários: -- ++ Binários: + - / * % int x = 10 + 10; int y = 10 / 0; // Uma exceção será lançada ! java.lang.ArithmeticException Divisão por zero public class Teste { public static void main(String[] args) { double sal = 140 / 0; System.out.println("Salario: "+sal); } } Atenção • Qual o resultado? • Anote a exceção. Classe public class Teste { public static void main(String[] args) { double d = 140; double sal = d / 0; System.out.println("Salario: "+sal); } } Resultado • E agora, o que acontece? Classe public class Teste { public static void main(String[] args) { double sal = -140.0 / 0; System.out.println("Salario: "+sal); } } Qual o resultado? • Viu as diferenças entre as classes? Classe public class Teste { public static void main(String[] args) { double sal = -0.0 / 0; System.out.println("Salario: "+sal); } } E agora? • Resultado: – Salario: NaN (atenha-se a saber o que resulta e não o porquê) Incremento e decremento • Atenção aos operadores unários. Pré-fixado • int x = 10; System.out.println("x é "+(++x)); Pós-fixado • int x = 9; System.out.println("x vale: "+x--); System.out.println("o valor final de x é "+x);