Revisão da linguagem Java

Propaganda
Revisão da linguagem Java
Laboratório de Programação
Pedro Vasconcelos, Manuel Barbosa, DCC/FCUP
Fevereiro 2016
Java
• linguagem de programação de propósito genérico inicialmente desenvolvida
pela Sun, atualmente pela 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
2000
2005
2011
2014
JDK 1.0
J2SE 1.3
J2SE 5
JSE 7
JSE 8
primeira versão
HotspotVM
tipos genéricos, enumerações, ciclos for implícitos
melhorias na inferência de tipos genéricos
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
long
float
double
boolean
char
inteiros com sinal 32 bits
inteiros com sinal 64 bits
vírgula-flutuante simples
vírgula-flutuante dupla
valores lógicos
carateres Unicode
0, -7, 12345
-12345L
1.234f, -10.5e6f
-0.25, 1.234d
true, false
'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
Download