Classes e objectos em Java (introdução) PCO / PPO Departamento de Informática Faculdade de Ciências da Universidade de Lisboa Resumo ➡ Uso de classes e objectos em Java ➡ classes e objectos ➡ código cliente vs. código fornecedor ➡ O operador new, métodos construtores ➡ métodos de instância ➡ métodos de instância vs. métodos de classe ➡ modificador de visibilidade public ➡ Exemplos de classes da API do Java ➡ String StringBuilder Scanner Random 2 Classes ? Objectos ? (intuição da 1ª aula) Classe Instâncias (objectos) Super-heróis Homem-aranha, Batman, Hulk, Spiderman ... Hora 23:59, 12:00, 5:30, ... Cursos na FCUL TIC, Est. Aplicada, ... ➡ Classe: caracterização abstracta de uma entidade. ➡ Objecto: instância de uma classe. 3 Atributos e operações (intuição da 1ª aula) Classe Atributos Operações super-poderes() usa-super-poder(X) salva-o-mundo() Hora horas() minutos() acerta-hora(h) acerta-minutos(m) ... Cursos na FCUL nome() alunos() cadeiras() adiciona-aluno(a) remove-aluno(a) ... Super-heróis ➡ A uma classe podemos associar atributos e operações. 4 “Hello world!” revisitado package pco; public class HelloWorldAgain { public static void main(String[] args) { char chSeq[] = { 'H', 'e', 'l', 'l', 'o' , ' ', 'w', 'o', 'r', 'l', 'd' , '!'}; String s = new String(chSeq); for (int i=0; i < s.length(); i++) { char c = s.charAt(i); System.out.print(c); } System.out.print('\n'); } } ➡ Uso de um objecto da classe String, definida no pacote java.lang. 5 Definições correspondentes em java.lang.String package java.lang; HelloWorldAgain new String(chSeq); s.length() s.charAt(i) public class String ... { ... public String(char[] v) { ... } ... public int length() { ... } ... public char charAt(int index) { ... } ... } ➡ Relação cliente/fornecedor entre classes ➡ ➡ código cliente = pco.HelloWorldAgain (utiliza funcionalidade) código fornecedor = java.lang.String (fornece funcionalidade) 6 Operador new / construtores package pco; public class HelloWorldAgain { public static void main(String[] args) { char chSeq[] = { 'H', 'e', 'l', 'l', 'o' , ' ', 'w', 'o', 'r', 'l', 'd' , '!'}; String s = new String(chSeq); for (int i=0; i < s.length(); i++) { char c = s.charAt(i); System.out.print(c); } System.out.print('\n'); } } ➡ Operador new cria novo objecto da classe String, invocando um método construtor definido na classe para a inicialização do objecto. 7 Construtores package java.lang; public class String ... { public String(char[] v) { ... } public int length() { ... } public char charAt(int index) { ... } ... } ➡ Um construtor é um método especial para inicializar uma instância da classe em que está definido. ➡ O constructor tem o mesmo nome que a classe e pode ter vários argumentos. ➡ Podem existir vários construtores (graças ao mecanismo de sobrecarga). É esse o caso para String, como podemos verificar na sua documentação. 8 Métodos de instância package pco; public class HelloWorldAgain { public static void main(String[] args) { char chSeq[] = { 'H', 'e', 'l', 'l', 'o' , ' ', 'w', 'o', 'r', 'l', 'd' , '!'}; String s = new String(chSeq); for (int i=0; i < s.length(); i++) { char c = s.charAt(i); System.out.print(c); } System.out.print('\n'); } } ➡ Após a construção de um objecto, podemos invocar métodos de instância sobre este. ➡ No exemplo: chamada aos métodos length() e charAt() 9 Métodos de instância package java.lang; public class String ... { public String(char[] v) { ... } public int length() { ... } public char charAt(int index) { ... } ... } ➡ Cada execução de um método de instância tem sempre associado um objecto (instância) da classe. ➡ Métodos de instância não são declarados com o modificador static. 10 métodos de instância vs. métodos de classe (estáticos) package java.lang; public class String ... { public String(char[] v) { ... } public int length() { ... } public char charAt(int index) { ... } ... public static String valueOf(int v) { ... } } ➡ ➡ ➡ ➡ Métodos de classe (também chamados métodos estáticos) declarados com a palavra-chave static globais à classe, pelo que não definem operações sobre uma instância (objecto) particular da classe Invocação usa a sintaxe ClassName.methodName(args) por exemplo String.valueOf(999) 11 métodos de instância vs. métodos de classe (estáticos) package java.lang; public class String ... { ... public static String valueOf(int v) { ... } public String replace(char oldCh,char newCh) { ... } } String s1 = String.valueOf(999); // "999" String s2 = s1.replace('9', 'A'); // "AAA" 12 public visibilidade “pública” package java.lang; public class String ... { public String(char[] v) { ... } public int length() { ... } public char charAt(int index) { ... } ... } ➡ O modificador public torna a classe String visível (utilizável) por código cliente em qualquer outro pacote (“package”), para além do pacote java.lang ➡ HelloWorldAgain no pacote pco pode então referir-se à classe String no pacote java.lang. ➡ Analogamente, métodos public em String podem ser invocados por código cliente em qualquer outro pacote. ➡ Em aulas futuras, discutiremos outros modificadores de visibilidade … 13 Exemplo 2: Leitura de dados com Scanner package pco; import java.util.Scanner; public class ScannerExample { public static void main(String[] args) { Scanner s = new Scanner(System.in); System.out.print("How many values? "); int n = s.nextInt(); double sum = 0.0; for (int i = 1; i <= n; i++) { System.out.print("Value " + i + "? "); sum = sum + s.nextDouble(); } System.out.printf("Result = " + sum); s.close(); } } ➡ O programa começa por pedir ao utilizador o número de valores (n) que deverão ser lidos. Depois lê os valores (de tipo double) e apresenta no final a sua soma. 14 Exemplo 2: Leitura de dados com Scanner package pco; import java.util.Scanner; decl. importação public class ScannerExample { public static void main(String[] args) { Scanner s = new Scanner(System.in); criação System.out.print("How many values? "); int n = s.nextInt(); leitura de valor int double sum = 0.0; for (int i = 1; i <= n; i++) { System.out.print("Value " + i + "? "); sum = sum + s.nextDouble(); leitura de valor double } System.out.printf("Sum = " + sum); s.close(); fecho } } ➡ ➡ A declaração import acima é necessária para identificar o pacote onde está definida a classe Scanner … já que Scanner não faz parte de java.lang nem de pco (pacote onde está definido o código cliente neste caso) 15 Exemplo 3: uso de java.util.Random public class PiValueUsingMonteCarlo { y public static void main(String[] args) { Random rng = new Random(0); Scanner s = new Scanner(System.in); x System.out.print("How many iterations? "); int iterations = s.nextInt(); int inside = 0; for (int i = 1; i <= iterations; i++) { double x = rng.nextDouble(); // value within [0,1] double y = rng.nextDouble(); // value within [0,1] if (x * x + y * y <= 1) { inside++; } } double approx = 4 * (double) inside / (double) iterations; System.out.println("Pi approximation : " + approx); System.out.println("Pi value : " + Math.PI); System.out.println("Error : “ + Math.abs(Math.PI - approx)); } } 16 Mais sobre String (1) package pco; public class OneMoreStringExample { public static void main(String[] args) { String a = "aEiOu"; String b = a.toLowerCase(); // "aeiou" String c = a.toUpperCase(); // "AEIOU" String d = b + ' ' + c; // "aeiou AEIOU" String e = d.replace(' ', ','); // “aeiou,AEIOU” System.out.println("a: "+ a); System.out.println("b: "+ b); System.out.println("c: "+ c); System.out.println("d: "+ d); System.out.println("e: "+ e); } } ➡ ➡ Operador + : concatenação no contexto de objectos de tipo String (valores/objectos envolvidos convertidos implicitamente p/String). Nota: os objectos da classe String são imutáveis - o seu conteúdo não consegue ser modificado após criação; apenas podemos obter novas strings a partir de outras, ex. via métodos toLowerCase() e toUpperCase() , replace(), ou uso do operador ‘+’. 17 Mais sobre String (2) (switch-case) public static void main(String[] args) { for (String os : args) { String masterMind; switch (os) { case "Linux": masterMind = "Linus Torvalds"; break; case "MacOs": masterMind = "Steve Jobs"; break; case "Windows": masterMind = "Bill Gates”; break; default: masterMind = "????"; break; } System.out.println(os + " > “ + masterMind); } } 18 Vectores de referências package pco; public class StringVectorExample { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println(i + " " + args[i]); } String[] argsUC = new String[args.length]; for (int i = 0; i < args.length; i++) { argsUC[i] = args[i].toUpperCase(); } for (int i = 0; i < args.length; i++) { System.out.println(i + " " + argsUC[i]); } } } ➡ ➡ • • • • "a" "b" "c" • / • • • • "A" / / "B" "C" Um vector de tipo não primitivo mantém referências a objectos de determinada classe, no exemplo de tipo String. No exemplo, operador new cria um vector e inicializa-o com referências nulas (null), o valor por defeito. 19 java.lang.StringBuilder package pco; public class StringBuilderExample { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append('H'); sb.append('e'); sb.append('l'); sb.append('l'); sb.append(‘o’); sb.append(" world!"); String s = sb.toString(); System.out.println(s); } } ➡ ➡ O estado de um objecto StringBuilder vai sendo modificado progressivamente por forma a “construir” uma string, depois obtida via toString(). O seu uso é conveniente quando é desejável uma maior eficiência na construção de strings. 20 String vs. StringBuilder String s1 = "abc"; String s2 = s1; s2 = s2.concat("def"); StringBuilder sb1 = new StringBuilder("abc"); StringBuilder sb2 = sb1; sb2.append("def"); String s1 • s2 • "abc" StringBuilder sb1 • sb2 • String StringBuilder s1 • "abc" sb1 • s2 • "abcdef" sb2 • ➡ ➡ "abc" "abcdef" Funcionamento de variáveis/referências similar ao que já vimos para vectores. Objectos StringBuilder são mutáveis (funcionam como “acumuladores” de caracteres) 21