Revisão da linguagem Java Laboratório de Programação Pedro Vasconcelos, DCC/FCUP Fevereiro 2015 Java TM linguagem de programação de propósito genérico desenvolvida pela Sun (e agora Oracle) suporta tipos estáticos, classes, objetos e concorrência compilada para bytecode duma máquina virtual ( write-once, run anywhere ) sintaxe baseada no C/C++ mais alto nível: modelo de objetos mais simples que o de C++ libertação automática de memória (garbage collection) não suporta aritmética de apontadores tratamento de erros de execução usando exceções Platforma Java Java Standard Edition (JSE): compilador: javac interpretador JVM: java conjunto de biliotecas padrão ferramentas (jar, javadoc, etc.) Java Enterprise Edition (JEE): JSE + componentes extra para aplicações empresariais 1
Evolução da linguagem 1996 JDK 1.0 primeira versão 2000 J2SE 1.3 HotspotVM 2005 J2SE 5 tipos genéricos, enumerações, ciclos for implícitos 2011 JSE 7 melhorias na inferência de tipos genéricos 2014 JSE 8 expressões lambda, streams funcionais Em laboratório de programação: vamos usar o JSE 7. Outras linguagens A máquina virtual JVM pode também ser usada para executar outras linguagens; algums exemplos: Scala Clojure Python Ruby http://www.scala-lang.org http://clojure.org/ http://www.jython.org/ http://jruby.org/ NB: não suportadas oficialmente pela Oracle! Princípios da linguagem combina programação imperativa com objetos distingue entre valores básicos e objetos objetos são usados para estruturar programas valores básicos não são objectos execução em máquina virtual (facilita portabilidade) gestão automática de memória: a alocação de objetos é explícita a libertação é implícita (garbage collection) Objetos, classes e packages objetos são agregados de dados e operações associadas 2
as classes são moldes para criar objectos objectos da mesma classe suportam um conjunto de operações comuns packages são agregados de classes relacionadas (para facilitar distribuição) NB: em Java, classes também são usadas apenas para agrupar métodos e atributos estáticos. Ficheiros Java O nome do ficheiro duma classe pública deve ser igual ao nome da classe. // num ficheiro Rectangle.java public class Rectangle { NB: pode ter outras classes desde que não sejam públicas. Método main programa completo deve ter uma classe com um método estático main os argumentos de linha de comando são passados como um array de String // num ficheiro Hello.java class Hello { public static void main(string args[]) { System.out.println("Hello world!"); Compilação e execução 3
$ javac Hello.java # compilar $ java Hello # executar # alternativa com CLASSPATH $ java -cp ~/myclasses Hello Tipos básicos principais tipo valores literais int inteiros com sinal 32 bits 0, -7, 12345 long inteiros com sinal 64 bits -12345L float vírgula-flutuante simples 1.234f, -10.5e6f double vírgula-flutuante dupla -0.25, 1.234d boolean valores lógicos true, false char carateres Unicode 'A', '\u2764' Arrays int[] anarray; // declaração anarray = new int[10]; // inicialização (zeros) // inicialização com constantes int[] anarray = { 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 ; Arrays (2) os índices começam em zero (como em C/C++) arrays em Java têm associado um atributo length (ao contrário do C/C++) int[] someprimes = { 2, 3, 5, 7, 11, 13 ; for (int i=0; i<someprimes.length; i++) { System.out.println(somePrimes[i]); 4
Ciclo for implícito Também podemos percorrer arrays usando um ciclo for com o índice implícito ( for-each ou enhanced for ): int[] someprimes = { 2, 3, 5, 7, 11, 13 ; for (int prime : someprimes) { System.out.println(prime); NB: estes ciclos podem ser usados também noutras coleções (listas, conjuntos, etc.). Arrays (3) não há arrays multi-dimensionais alternativa: arrays de arrays permite dimensões internas não homogéneas String[][] names = { {"Mr. ", "Mrs. ", "Ms. ", {"Smith", "Jones" ; System.out.println(names[0][0] + names[1][0]); // Mr. Smith System.out.println(names[0][2] + names[1][1]); // Ms. Jones Cadeias de texto Cadeias são objetos da classe String. String s1 = "Hello"; // declarar e inicializar String s2 = new String("Hello") // alternativa Podemos obter o comprimento e concatenar. System.out.println(s1.length()); // output: 5 // NB: length() é um método System.out.println(s1 + " world!"); // output: "Hello world!" 5
Cadeias de texto (2) não são arrays de carateres mas podemos aceder aos carateres individuais usando charat() String pal = "Dot saw I was Tod"; int len = pal.length(); for (int i = 0; i < len; i++) { System.out.printlen(pal.charAt(i)); Cadeias de texto (3) não podemos modificar o comprimento ou os carateres duma cadeia (é um objeto imutável) mas podemos construir novas cadeias por concatenação alternativa: classe StringBuilder (mais tarde) Programação com objetos definimos classes para novos tipos objetos na definição da classe incluimos: atributos (i.e. valores de estado) métodos (i.e. operações suportadas) Exemplo: contas bancárias class Account { int balance = 0; // balanço (atributo) // depositar uma quantia void deposit(int amount) { balance = balance + amount; // obter o saldo atual int getbalance() { return balance; 6
Exemplo de uso class AccountDemo { public static void main(string args[]) { Account acc1 = new Account(); Account acc2 = new Account(); System.out.println(acc1.getBalance()); System.out.println(acc2.getBalance()); acc1.deposit(100); acc2.deposit(50); System.out.println(acc1.getBalance()); System.out.println(acc2.getBalance()); Controlo de acesso Podemos limitar o acesso a métodos ou atributos usando modificadores; os mais comuns são: public visível em todas as classes private vísivel apenas na própria classe Outros: protected visível na classe, sub-classes e no package (sem modificador) visível na classe e no package Contas bancárias (2) class Account { private int balance = 0; // depositar uma quantia public void deposit(int amount) { balance = balance + amount; // obter o saldo atual 7
public int getbalance() { return balance; Encapsulamento não podemos modificar balance fora da classe Account podemos apenas usar os métodos públicos // no método main() da classe AccountDemo acc = new Account() acc.balance = acc.balance + 100; // ERRO acc.deposit(100); // OK Construtores devemos definir construtores especializados para inicializar objetos um construtor tem o nome da classe e não tem tipo de retorno pode haver mais do que um construtor (com diferentes números de argumentos ou tipos) class Account { private int balance = 0; // construtor com saldo inicial public Account(int amount) { balance = amount; Métodos e atributos estáticos Por omissão, os atributos e métodos são associados a cada instância particular (i.e. cada objeto). O modificador static permite associar métodos ou atributos à classe em vez das instâncias. 8
class Account { // balanço (um por cada conta) private int balance = 0; // taxa de câmbio (todas as contas) static private float rate = ; Herança uma classe pode extender outra por herança se A extende B então A é sub-classe de B uma sub-classe: herda atributos e métodos da classe original pode definir novos métodos ou redefinir métodos existentes (override) class SavingsAccount extends Account { // novos atributos e métodos private float interestrate; A classe Object a classe Objet está no topo da hierarquia todas as outras classes herdam de Object (direta ou indiretamente) se não declaramos herança explícita para um nova classe, esta herda de Object: class Account { é equivalente a class Account extends Object { 9
Métodos da classe Object Alguns métodos definidos em Object: Object clone() criar uma cópia do objeto boolean equals(object other) comparar igualdade com outro objeto String tostring() converte o objeto numa string int hashcode() retornar o código de hash inteiro NB: por vezes é necessário re-definir estes métodos nas sub-classes. Cuidados com herança O (ab)uso da herança é desaconselhado: implica perda de flexibilidade porque compromete o programa com implementações específicas aumenta o acouplamento entre partes distintas do código uma alteração numa classe pode ter efeitos imprevistos noutras a integridade da relação de herança é bastante subtil: https://isocpp.org/ wiki/faq/proper-inheritance#circle-ellipse Interfaces especificações de um conjunto métodos relacionados representam um contrato entre uma classe e o mundo exterior uma interface pode ser implementada por várias classes uma classe pode implementar várias interfaces Exemplo interface Sizeable { float getarea(); // calcular área class Rect implements Sizeable { private float width, height; public float getarea() { 10
return width*height; Exemplo (cont.) class Circle implements Sizeable { private float radius; public float getarea() { return Math.PI*Math.pow(radius,2.0); Classes vs. interfaces classes podem conter atributos e métodos interfaces só podem declarar métodos (sem implementação) ou constantes uma classe só pode extender uma outra classe uma interface pode extender múltiplas interfaces public interface GroupedInterface extends Interface1, Interface2, Interface3 { // declarações de constantes // e assinaturas de métodos Enumerações tipos enum permitem definir valores constantes dum conjunto finito de alternativas o compilador verifica que valores dum tipo enum são corretamente atribuidos podem também ser usados em instruções switch public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY 11
Exemplo public void tellitlikeitis(day day) { switch (day) { case MONDAY: System.out.println("Mondays are bad."); break; case SATURDAY: case SUNDAY: System.out.println("Weekends are best."); break; default: System.out.println("Midweek days are so-so."); break; Outros cuidados valores null comparações de igualdade anotações de override implementações do método equals Valores null um array ou objeto sem inicialização toma o valor null podemos também atribuir explicitamente null null representa a ausência de um objeto invocar métodos ou atributos de null causa um erro: NullPointerException String s1; // inicializada com null System.out.println(s1.length()); // NullPointerException Comparações de igualdade O operador == compara: igualdade de valores para tipos básicos (int, char, etc.) igualdade de referências para arrays e objetos 12
int x = 1+2+3; int y = 2*3; // x==y dá true String s1 = "Hello " + "world"; String s2 = "He" + "llo world"; // s1 == s2 dá false Comparações de igualdade (2) Para comparar igualdade de valores entre objetos devemos usar o método equals: String s1 = "Hello " + "world"; String s2 = "He" + "llo world"; boolean r1 = s1.equals(s2); // true boolean r2 = s2.equals(s1); // true Igualdade entre Arrays Arrays são objetos da classe Array a igualdade está definida em java.util.arrays (não é o método equals) import java.util.arrays; int a[] = {1, 2, 3 ; int b[] = {1, 2, 3 ; boolean r1 = a == b; boolean r2 = a.equals(b); boolean r3 = Arrays.equals(a,b); // false // false // true Anotação de Override as anotações indicam meta-informação para o compilador, IDEs e outras ferramentas quando queremos redefinir um método numa sub-classe devemos anotá-lo com @Override 13
permite ao compilador/ide avisar se nos enganarmos no nome do método ou tipos de argumentos class Foo { @Override public String tostring() { // redefinir um método herdado de Object Implementação de equals o método equals definido em Object compara as referências dos objetos (como o operador ==) para comparar valores devemos redefinir este método possiveis armadilhas: assinatura de tipos demasiado restrita definir equals dependendo de atributos mutáveis definir equals sem respeitar uma relação de equivalência devemos também redefinir hashcode Mais informação: How to Write an Equality Method in Java Exemplo: rectângulos class Rect { private int width, height; // largura, altura @Override public boolean equals(object other) { if (other == null!(other instanceof Rect)) return false; Rect that = (Rect)other; // coerção return (this.width == that.width && this.height == that.height); 14
Redefinir também hashcode Para usar Rect em coleções baseadas em funções de hash (e.g. HashMap ou HashSet) devemos também redefinir hashcode. class Rect { @Override public int hashcode() { // produtos com um primo return (41 * (41 + width) + height); Os IDEs podem gerar automaticamente métodos equals e hashcode mas nem sempre corretos! 15