Introdução ao Java FEUP>DEEC>MRSC>Programação em Comunicações v1.4 Isidro Vila Verde <[email protected]> Jaime Sousa Dias <[email protected]> O que é o JAVA? • É uma Linguagem de Programação • • • • • Orientada aos objectos ÆClass Based Concorrente High Level Strongly Typed Portável • Um programa em JAVA é independente da arquitectura • Em principio pode correr em qualquer plataforma • Uma máquina virtual (JVM) • Biblioteca de Classes • API 2 Comparação com outras linguagens Diferenças para o C++ • Cada classe (pública) é gravada num ficheiro respectivo com o mesmo nome da classe* e extensão .java • * Na realidade esta afirmação só se aplica a Top Level Classes • O que existe em Java • Run Time Type Check • Array bounds • Null pointers access • Interfaces • Concorrência (Multi-thread) nativa • Garbage Collector • Os recursos dos objectos são automaticamente libertados quando o sistema detecta que já não são necessários (referenciados) 4 Diferenças para o C++ (2) • O que não existe em Java • Estruturas (struct) • Uniões (union) • Apontadores ou ponteiros (pointers) • Apenas referências • Apontadores para funções (Function Pointers) • Funções globais • Incluindo a função do C/C++ main Æ Em java o main é uma função membro estática • Variáveis/Objectos globais • Malloc’s ou delete’s ÆA gestão de memória é automática (Garbage Colector) • Herança múltipla 5 Diferenças para o C++ (3) • O que não existe em Java (cont.) • • • • • Sobrecarga de operadores (operator overloading) Templates Header Files (.h) Directiva de pré-processamento (ex: #pragma) Variáveis-objecto Æ Em java tudo o que não seja tipo primitivo é manuseado como referência 6 Java vs. outras linguagens • PERL, TCL, Python • • • • São interpretadas O código fonte é distribuído aos utilizadores Obriga à instalação prévia do interpretador Se fizer uso de primitivas/comandos do sistema terá de haver uma versão de código para cada S.O. • Execução lenta 7 Java vs. outras linguagens (2) • C, C++, Pascal • São linguagens compiladas • O código fonte não é distribuído aos utilizadores, apenas o código binário • Se fizer uso de primitivas/comandos do sistema terá de haver uma versão de código para cada S.O. 8 Java vs. outras linguagens (3) • C, C++, Pascal (cont.) • Necessita de uma versão binária por cada ambiente (S.O. + CPU) • Windows • Eventualmente: 95, NT, 2000 • Necessáriamente: Intel, Alpha, Mips • Unix • Eventualmente: BSD, Linux, AIX, HP-UX, SCO • Necessariamente: Sparc, Intel, Alpha, Mips • Execução Eficiente • Em C ou C++ é possível controlar ao nível do assembly a eficiência • O programador pode controlar/garantir eficiência 9 Java vs. outras linguagens (4) • JAVA • É compilado para uma máquina virtual • O compilador gera Bytecodes • O Código fonte não é distribuído • Uma só versão de código independente da plataforma (CPU e/ou S.O.) • O código binário (Bytecodes) é carregado e interpretado na JVM (Java Virtual Machine) • $> java codigodaclass • Obriga à existência ou instalação prévia do JRE (Java RunTime Enviroment) • Incluí a JVM • Execução lenta 10 Ambiente JAVA WRITE USE JRE Java Source App.java Class loader bytecode verifier Java Libraries JDK System Library classes Compile Java Byte Codes App.class Java Interpreter Just in Time Compiler Runtime System J V M Operating System Hardware 11 Tipos de programas Java • Aplicações • programas “Standalone” • Applets • Componentes de código que correm num ambiente WEB • Servlets • São componentes de código que correm num servidor WEB por oposição às Applets que correm no cliente (navegador) • JSP • Java Server Pages – Directivas embutidas em páginas HTML que permitem executar código JAVA intercalado com HTML 12 Exemplo de Utilização Executar uma aplicação escrita em Java • O JRE • java, javaw, appletviewer • O código da aplicação • App.class • Executar • $> java App • Omite-se a extensão “.class” • Nota: o ficheiro App.class deve estar o directório corrente ou num dos directórios incluídos na variável de ambiente CLASSPATH. 14 JRE instalado? • Verificar se já está instalado • Executar java -version • Se corre então deve estar (devidamente?) instalado • Nas distribuições recentes dos S.O.s já é fornecido e instalado por omissão • Se não encontrou o programa java • http://java.sun.com • Seleccionar o J2SE (última versão) • Selecionar o JRE • O SDK só é necessário para fazer desenvolvimento • Fazer o download e instalar 15 Criar uma aplicação em Java • Um editor de texto • vi, pico, notepad, wordpad, etc. • O java JDK (SDK) • Verificar se já está instalado • Executar javac -version • Se corre então deve estar (devidamente?) instalado • Nota: não é java é javac (Java Compiler) • Se não encontrou o comando • http://java.sun.com • Seleccionar o J2SE (última versão) • Seleccionar o SDK • Fazer o download e instalar 16 Escrever a aplicação • Criar um ficheiro com o nome da aplicação e extensão .java • Ex: App.java • Editar o ficheiro App.java e criar uma classe (class) App pública (public) public class App { } 17 Escrever a aplicação (2) • Incluír na definição da classe um método estático (static) público (public) e sem tipo (void), de nome main com um argumento do tipo array de strings (String[]) public class App { public static void main(String[] args) { } } 18 Escrever a aplicação (3) • Definir o método main para executar o código pretendido • Ex: Escrever “Hello World” public class App { public static void main(String[] args) { System.out.println("Hello World"); } } 19 Compilar o código • Gravar o ficheiro • Compilar o código em linha de comando • Usar o “comando” javac • $> javac App.java • Verificar que foi criado o ficheiro App.class • Testar o código • $> java App 20 Análise do “Hello World” O Hello World public class App { public static void main(String[] args) { System.out.println("Hello World"); } } • Componentes do “Hello world” • • • • • • Declaração da classe (class) método main Classe String System.out.println Modificador de acesso public Modificador static 22 Class • O formato mais simples para definir uma classe é este: [<acessibilidade>] class <Nomeclass> { <declaração e definição dos membros aqui> } • No caso do exemplo “Hello World”: • Nomeclass é o nome que quiser, tendo em atenção que: • Deve ter o mesmo nome que o ficheiro onde está • É sensivel à capitulação dos caracteres • A visibilidade tem de ser public para ser visível do exterior 23 Método • Os métodos são funções ou procedimentos membros de uma dada classe que permitem manusear o objecto • Um caso especial dos métodos é o método public static void main (String[] argv). • Por se chamar main, ser estático (static) e público (public) é invocado sempre que se carrega a classe (programa standalone) • $> java App 24 Classe String • A classe String • É uma classe do ‘core’ do Java • Está definida na API • Está incluída na package java.lang • Como o próprio nome indica fornece um conjunto de métodos para trabalhar com cadeias de caracteres 25 System.out.println • • • A classe System está definida na package java.lang Tem uma variável membro out do tipo PrintStream out é o standard output e está aberto e pronto a receber caracteres 26 System.out.println • System.out • É uma instância /objecto da classe java.io.PrintStream • A classe PrintStream está definida na package java.io • Tem um método membro println(String) 27 Modificador public • public é um modificador de acesso (visibilidade ) • permite que a classe App esteja acessível de fora da package (neste caso o ficheiro) • Além da classe ser acessível também é preciso dar acessibilidade pública ao método main para poder ser invocado a partir do exterior da package 28 Modificador static • O modificar static permite que o método main seja invocado sem haver ainda qualquer instância da classe já criada • Aplica-se à classe e não a um objecto em particular 29 A linguagem Java Componentes da Linguagem Java [<package>] <Classe>* <Membros>* <Campos>* <Métodos>* <Classes>* <Interfaces>* <Interfaces>* <IMembros>* <Campos>* <IMétodos>* 31 Java Keywords abstract boolean break byte case catch char class const Continue default do double else extends final finally float for goto if implements import instanceof int interface long native new null package private protected public return short static super switch synchronised this throw throws try void while volatile 32 Class Class • A declaração de uma classe é a principal declaração em JAVA • Em Java tudo é implementado em Classes • Uma classe é uma colecção de dados e/ou código que define intrinsecamente as características e comportamento de um certo conjunto de objectos. • Uma classe está para os objectos como um esquema electrónico está para um equipamento fabricado em série. 34 Class • A declaração de uma classe define um novo tipo e descreve as suas características e comportamento. • O formato mínimo para declarar uma classe deve obedecer à seguinte regra <modificador>* class <ClassName>{ <membros>* } • Por convenção o nome da classe (<ClassName>) deve começar por uma maiúscula 35 Class Ex1\A.java class A { Membros das Classes int j = 6; } class B { int j = 66; } Ex1\Ex0.java public class Ex0 { public static void main(String[] args) { A a = new A(); B b = new B(); System.out.println(a.j); System.out.println(b.j); } } 36 Membros da Classe Membros da Classe • Uma classe é composta por: • • • • • Campos Métodos Classes Interfaces Inicializadores • Os campos são: • Variáveis de tipos primitivos • Ou referências para objectos 38 Tipos Primitivos • Estes são os tipos primitivos do Java. Tudo o resto são referências • Inteiros • • • • byte short int long (1 byte, -128 to 127) (2 bytes) (4 bytes) (8 bytes) • Vírgula flutuante • • float (4 bytes, 6-7 significant decimal digits) double (8 bytes, 15 significant decimal digits) 39 Tipos Primitivos (2) • • char boolean (2 byte, Unicode) (ASCII 1 byte) (true or false) • Não se pode converter booleanos em inteiros e vice-versa 40 Métodos • Os métodos são funções ou procedimentos membros da classe • A declaração dos métodos obedece a esta regra <modificador>* <tipo> <nome>(Arg*){ <codigo aqui> } • No caso dos construtores a regra muda para: <modificador>* <nome>(Arg*){ <codigo aqui> } • O modificador pode assumir vários valores 41 Métodos – Exemplo Ex2\Counter.java public class Counter { int n = 0; //campo membro //método membro estático public static void main(String[] argv) { Counter c = new Counter(); c.print(); mark("v = " + c.n); c.go(5); mark("v = " + c.inc()); c.go(7); } //método membro que retorna um int int inc(){ return n++; } Continua 42 Métodos – Exemplo (2) Ex2\Counter.java (cont.) //método membro estático static void mark (String s){ System.out.println(s); } //método membro void print (){ System.out.println ("Counter = " + n); } //método membro void go (int k){ while (k-- > 0){ inc(); print(); } } } 43 Operador de acesso aos membros • O acesso aos membros da classe é feito com o operador “.” <Nome da instância>.<nome do membro> • Acesso aos métodos membro c.print(); • Acesso aos campos membro c.n • Dentro de um método (não static) o nome da instância está implícito e como tal é desnecessário int inc(){ return n++; } 44 Construtor • Dentro dos métodos há uma situação particular designada por Constructor • Os construtores são métodos mas com algumas particularidades • Têm o mesmo nome da classe e não têm um tipo definido explicitamente • São invocados quando se instancia um novo objecto (com o operador new) • Não podem ser invocados explicitamente com o operador “.” • Racional para isto: • Se o objecto ainda não foi criado não se pode invocar métodos sobre o mesmo • Se já foi criado então não faz sentido cria-lo novamente 45 Construtor – Exemplo Ex3\Counter2.java public class Counter2 { int n = 0; Counter2 (int x){ n = x; } public static void main(String[] argv) { Counter2 c = new Counter2(5); mark("v = " + c.n); c.inc(); mark("v = " + c.n); } int inc(){ return n++;} static void mark(String s){ System.out.println(s);} void print(){System.out.println("Counter = " + n);} } 46 Métodos especiais • Há dois métodos que têm um tratamento especial derivado do seu nome • O método public static main (String[] argv) • Se declarado dentro de uma classe publica é o primeiro a ser invocado quando se carrega a classe • $> java Counter2 • O método protected void finalize() • É invocado pelo sistema quando este detecta que o objecto já não é usado • Não é garantida a ordem de invocação deste método 47 Métodos especiais (por convenção) • Convencionou-se que as seguintes regras de atribuição de nome aos métodos traduzem acções bem definidas • Métodos de atribuição de valores void setQualquerCoisa(tipo1){ variavelQualquerCoisa = arg1; } • Métodos de inspecção de valores tipo1 getQualquerCoisa(){ return variavelQualquerCoisa; } 48 Classe vs. Objecto Classe vs. Objecto • Um objecto é uma instância de uma classe • Num programa em Java cada classe é única mas pode haver (e normalmente há) vários objectos da mesma classe • A classe define as características e o comportamento do conjunto de objectos do seu tipo 50 Classe vs. Objecto (2) • Em Java não há variáveis-objecto. • Todas as variáveis de algum tipo não primitivo são na realidade referências para o objecto e não o objecto em si mesmo ClasseT a = new ClasseT; • Consequências Æ A atribuição não copia o objecto ClasseT b = a; • Algumas análogias • Esquema electrónico Ù Equipamento produzido • Planta Ù Habitações (iguais) construídas 51 Herança Herança • A herança é uma técnica para derivar novas classes a partir de classes já existentes • As novas classes assim criadas são chamadas subclasses e herdam das superclasses • A subclasse herda os membros da superclasse e pode: • Acrescentar mais membros • Redefinir os métodos da superclasse (sobreposição) 53 Herança (2) • Um objecto do tipo de uma subclasse é automaticamente também do tipo da superclasse • O inverso é falso • Os objectos instanciados da subclasse formam um subconjunto dos objectos da superclasse • O formato base para declarar uma subclasse é este <modificador>* class <SubClassName> extends <SuperClassName>{ <membros>* } 54 Herança – Exemplo Ex4\Comp.java class Storage{ private int cap; void setCap(int c){cap = c;}; int getCap(){return cap;} int getCar(){return 0;} } //Disco é uma subclasse de Storage class Disco extends Storage{ private int rpm = 7800; int getCar(){return rpm;}//sobreposição do método } //Memoria é uma subclasse de Storage class Memoria extends Storage{ private int vel = 233; int getCar(){return vel;}// sobreposição do método int getDataWidth(){return 64;} } Continua 55 Herança – Exemplo (2) Ex4\Comp.java (cont.) public class Comp{ static public void main(String[] s){ Disco d = new Disco(); Memoria m = new Memoria(); d.setCap(80); //setCap é membro de Disco por herança m.setCap(512); System.out.println("ds = " + d.getCap()); //Chama o membro getCar() de Disco porque foi sobreposto //nesta classe ao getCar() de Storage System.out.println("r = " + d.getCar()); System.out.println("ms = " + m.getCap()); System.out.println("v = " + m.getCar()); System.out.println(“dw = " + m.getDataWidth()); } } $>java Comp ds = 80 r = 7800 ms = 512 v = 233 dw = 64 56 Polimorfismo Polimorfismo • Um nome, várias formas. • Em Java o polimorfismo manifesta-se na forma de múltiplos métodos (diferentes implementações) com o mesmo nome. • Dois tipos • Polimorfismo por sobrecarga de métodos: múltiplos métodos com o mesmo nome mas diferentes listas de parâmetros. • Polimorfismo por sobreposição de métodos: múltiplos métodos com o mesmo nome, a mesma lista de parâmetros e devolvem o mesmo tipo. 58 Sobrecarga • Os métodos são identificados pelo seu nome e pela sua assinatura • A assinatura é a combinação do tipo de argumentos com o seu número e a sua ordem • Algumas assinaturas possíveis para o método estenome • • • • • void void void void void estenome estenome estenome estenome estenome (String s) (int n) (Strint s, int n) (int n, String s) () • A sobrecarga de um método é feita definindo um outro método com o mesmo nome mas com assinatura distinta 59 Sobrecarga – Exemplo Ex11\comp.java public class Comp{ private int n; private String nome; /** A sobrecarga também se aplica aos Construtores. /* Por omissão o Java fornece um construtor nulo se não houver qualquer construtor /* definido. No entanto, se isso acontecer e quisermos continuar a ter um construtor /* nulo, temos de o definir public Comp(){} public Comp(String s){nome = s;} public Comp(String s, int x){nome = s; n = x;} public Comp(int x){n = x; nome ="";} public void setCaract(String s){nome = s;} public void setCaract(String s,int x){nome = s; n = x;} public void setCaract(int x){n = x;} static public void main(String[] s){ Comp c0 = new Comp(); Comp c1 = new Comp(5); Comp c2 = new Comp("garfield"); Comp c3 = new Comp("snoopy",6); c0.setCaract(3); c0.setCaract("alf",3); c1.setCaract("bunny"); } 60 } Sobreposição • Quando a superclasse e a subclasse implementam um método com o mesmo nome e a mesma assinatura. • Com a sobreposição, a escolha do método a executar baseia-se no tipo do objecto cuja referência está guardada na variável de referência e não no tipo da variável de referência através da qual o método é invocado. • Ao contrário da sobrecarga, onde a decisão do método a invocar é feita durante a compilação, na sobreposição a decisão só pode ser feita em run-time (late binding ou Dynamic Bind). 61 Sobreposição • Permite que os métodos de objectos de subclasses diferentes com uma superclasse comum sejam uniformemente invocados • resultando na invocação de diferentes métodos de acordo com a sua subclasse de forma transparente para o programador e para o compilador • Permite o uso do mesmo código para manipular dados cujo tipo (subclasse) ainda não é conhecido 62 Sobreposição – Exemplo Ex5\Comp.java class Storage{ private int cap; void setCap(int c){cap = c;}; int getCap(){return cap;} int getCar(){return 0;} String getCarUnits(){return "desconhecidas";} } class Disco extends Storage{ private int rpm = 7800; //métodos sobrepostos int getCar(){return rpm;} String getCarUnits(){return "Rpm";} } class Memoria extends Storage{ private int vel = 233; int getDataWidth(){return 64;} //métodos sobrepostos int getCar(){return vel;} String getCarUnits(){return "Mhz";} } Continua 63 Sobreposição – Exemplo (2) Ex5\Comp.java (cont.) public class Comp{ static public void main(String[] s){ Storage s0 = new Disco(); Storage s1 = new Memoria(); s0.setCap(80); s1.setCap(512); System.out.println("ds = " + s0.getCap()); System.out.print("r = " + s0.getCar()); System.out.println(" " + s0.getCarUnits()); System.out.println("ms = " + s1.getCap()); System.out.print("v = " + s1.getCar()); System.out.println(" " + s1.getCarUnits()); //System.out.println("dw = " + s1.getDataWidth()); /**Erro! s1 é do tipo Storage e esta classe não *define qualquer membro getDataWidth() System.out.println("dw = " + ((Memoria)s1).getDataWidth()); //OK: foi feito o downcasting da referência para o tipo Memoria } } $>java Comp ds = 80 r = 7800 Rpm ms = 512 v = 233 Mhz dw = 64 64 Package Package • Cada classe em Java é compilada para um ficheiro distinto mesmo que tenha sido definida no mesmo ficheiro • Ex.: no exemplo anterior (ficheiro fonte Comp.java) a compilação produziu os seguintes ficheiros $>dir 01-09-2003 01-09-2003 01-09-2003 01-09-2003 01-09-2003 13:45 13:45 13:45 13:45 13:45 1.140 Comp.class 1.348 Comp.java 454 Disco.class 532 Memoria.class 621 Storage.class • Um só ficheiro .java, mas um ficheiro .class por cada classe definida 66 Package • Cada classe pública precisa de ser definida num ficheiro independente • Se várias classes públicas precisarem de partilhar entre si determinadas características o elemento de armazenamento (isto é, o ficheiro), não é uma solução • Para atender a essa funcionalidade existe, em Java, o conceito de Package • Várias classes podem pertencer à mesma package se antes da declaração de classe incluírem a identificação da package package <nomedapackage>; 67 Package (2) • As packages tem uma estrutura hierárquica e reflectem uma árvore de directórios onde as classes são armazenadas • Para se usar uma classe de uma package é necessário importá-la • Alternativamente pode-se usar o nome completo da classe (qualified name) 68 Package (3) • A ordem de declaração tem de obedecer a esta regra Package <Nomedapackage> [Import <Nomedapackageimportada>] Classe* | Interfaces* • Qualquer classe (ou interface) declarada sem package pertence a uma package especial designada por “unnamed” • O import vai buscar as classes a partir das subdirectórias definidos em CLASSPATH 69 Package – Exemplo Ex6\info\componentes\abstractos\Storage.java package info.componentes.abstractos; public class Storage{ private int cap = 16; public void setCap(int c){cap = c;}; public int getCap(){return cap;} public int getCar(){return 0;} public String getCarUnits(){return "desconhecidas";} } info\componentes\Disco.java package info.componentes; import info.componentes.abstractos.Storage; //Só importa a classe Storage public class Disco extends Storage { private int rpm = 7800; public int getCar(){return rpm;} public String getCarUnits(){return "Rpm";} } info\componentes\Memoria.java package info.componentes; import info.componentes.abstractos.*; //Importa tudo o que estiver declarado nesta package public class Memoria extends Storage { private int vel = 233; public int getCar(){return vel;} public int getDataWidth(){return 64;} 70 public String getCarUnits(){return "Mhz";} } Package – Exemplo (2) Ex6\info\Comp.java //declaração da package package info; //importação das classes definidas na subpackage import info.componentes.*; //declaração dos tipos public class Comp{ private Disco d; private Memoria m; Comp(){ d = new Disco(); m = new Memoria(); } //Esta classe não foi previamente importada public info.componentes.abstractos.Storage getStor(){ return m; } public static void main(String[] s){ Comp c = new Comp(); int cap = c.getStor().getCap(); System.out.println("capaciade (memoria) = " + cap); } } 71 Operador this Operador this • Refere-se ao próprio objecto • auto-referência • Pode ser usada nos: • métodos não estáticos • Construtores • Serve para aceder aos campos membros quando há variáveis locais ou argumentos com o mesmo nome • Nos construtores serve ainda para invocar outros construtores da mesma classe (polimorfismo) 73 Operador this – Exemplo Ex16\Counter.java public class Counter{ private int n = 0; private String nome; public Counter(String nome){ this.nome = nome; //Sem o this o campo nome ficava inacessível por //causa do nome do argumento ser igual ao nome do campo } public Counter(int n){ this.n = n; } public Counter(int n, String nome){ this(n); //chama o construtor Counter(int n) //O this(...) só pode ser usado na 1ª instrução; e esta tem //de pertencer a um construtor //this(nome); //ERRO! só pode ser usado uma vez this.nome = nome; } public Counter(){ this(100,"sem nome"); } Continua 74 Operador this – Exemplo (2) Ex16\Counter.java (cont.) public void print(){ // Aqui é desnecessário porque não há qualquer outra variável com // o mesmo nome System.out.println("n = " + this.n); System.out.println("nome = " + this.nome); } static public void main(String[] s){ Counter c0 = new Counter(), c1 = new Counter(20); Counter c2 = new Counter("C2"); Counter c3 = new Counter(50,"C3"); c0.print(); c1.print(); c2.print(); c3.print(); } } 75 Operador super Operador super • Refere-se à superclasse • É uma referência para os membros da superclasse do objecto • Serve para aceder aos membros da superclass quando há sobreposição (nos campos e nos métodos) • Nos construtores serve ainda para seleccionar e invocar os construtores da superclasse 77 Operador super – Exemplo Ex17\Counter.java public class Counter{ private int n = 0; protected String nome; public Counter(String nome){this.nome = nome;} public Counter(int n){this.n = n;} public Counter(int n, String nome){ this(n); this.nome = nome; } public Counter(){} public void inc(){++n;} public int getVal(){return n;} public void reset(){n = 0;} } 78 Operador super – Exemplo (2) Ex17\ModCounter.java public class ModCounter extends Counter { public int n; public void inc(){ super.inc(); // acede/invoca o inc de Counter if (getVal() > n){reset();} } ModCounter(String nome, int i, int n){ //chama o construtor Counter(int,String) super(i,nome); //O super(...) só pode ser usado na 1ª instrução; e esta //tem de pertencer a um construtor this.n = n; } ModCounter(int n){ this.n = n; } } 79 Modificadores Modificadores • Um modificador é uma keyword que afecta o tempo de vida (lifetime) ou a acessibilidade de uma classe, variável ou método. 81 Modificadores de acesso Modificadores de acesso • public, protected e private • Recorrendo aos modificadores de acesso é possível controlar quem tem acesso a uma classe ou aos respectivos membros. • Este modificadores são mutuamente exclusivos • É desejável e aconselhável que o acesso se restrinja apenas ao necessário 83 Modificadores de acesso – Classes Modificador Quem tem acesso <omisso> Classes na mesma package public Universo – classes de todas as packages • Uma classe declarada sem package que não tenha modificador de acesso (<omisso>) fica acessível apenas pelas classes também elas declaradas sem package. • Só pode haver uma classe pública por ficheiro. 84 Modificadores de acesso – Membros • O controlo de acesso dos membros funciona como um encapsulamento, onde é possível controlar que membros estão acessíveis/visíveis para o exterior da classe • Cada classe deve declarar privado/protegido o que não precisa de ser visto pelo exterior • Do exterior só deve ser visível o estritamente necessário, escondendo os pormenores de implementação 85 Modificadores de acesso – Membros • Uma classe pode ter como membros • • • • Campo Método Classe Interface • No caso de uma classe ou interface estas são consideradas inner class e inner interface respectivamente. • Os modificadores aplicam-se à inner class ou inner interface da mesma forma que se aplicam a qualquer outro membro. 86 Modificadores de acesso – Membros Modificador Quem tem acesso <omisso> Classes na mesma package public Universo – classes de todas as packages protected Subclasses e classes na mesma package private Só dentro da própria classe 87 Modificadores de acesso – Exemplo Ex7\info\componentes\abstractos\Storage.java package info.componentes.abstractos; public class Storage{ int cap = 16; public int base = 2; protected String origem = "Portugal"; public void setCap(int c){cap = c;} public int getCap(){return cap;} int getCar(){return 0;} public String getCarUnits(){return "desconhecidas";} } Ex7\info\componentes\Memoria.java package info.componentes; import info.componentes.abstractos.*; public class Memoria extends Storage { private int vel = 233; int getCar(){return vel;} public int getDataWidth(){return 64;} public String getCarUnits(){return "Mhz";} public String getOrigem(){return origem;} //tem acesso a origem por herança } 88 Modificadores de acesso – Exemplo (2) Ex7\info\componentes\Teste.java package info.componentes; import info.componentes.abstractos.*; public class Teste{ static public void main(String[] args){ Storage s = new Storage(); Memoria m = new Memoria(); System.out.println("s.base: "+s.base); //System.out.println(s.cap); //Erro: cap não apresenta modificador de acesso (<omisso>) //System.out.println(s.origem); //Erro: origem é um campo protegido de Storage System.out.println("m.getOrigem(): "+m.getOrigem()); //OK: Memoria tem acesso ao campo origem porque é //uma subclasse de Storage //System.out.println(m.vel); //Erro: vel é um campo privado de Memoria System.out.println("getCar(): "+m.getCar()); //OK: o método getcar está acessível às classes da mesma package } } 89 Modificador static Modificador static • Só se aplica aos membros da classe • Permite que o método/campo seja invocado/acedido sem haver qualquer instância criada do objecto • Aplica-se à classe e não a um objecto em particular • Dito de outro modo, aplica-se às características comuns ao conjunto de objectos deste tipo, presentes ou futuros. • Um membro estático é partilhado por todos os objectos 91 Modificador static – Exemplo 1 Ex10\Comp3.java public class Comp3 { private int n; static private int ncomp = 0; public Comp3(){ n = ++ncomp; } static public int getNumOfInstances(){ //isto produz um erro de compilação //return n; return ncomp; //OK: ncom é um campo estático } public int getInstanceNumber(){return n;} public String getInstancesRel(){ String s = "Instance " + n + " of "+ ncomp + " Instances"; //OK! Os membros não estáticos podem aceder a membros estáticos return s; } } 92 Modificador static – Exemplo 1 (2) Ex10\Test3.java public class Test3 { private static Comp3 c0, c1, c2; public static void showAndCreate(Comp3 c){ int n = Comp3.getNumOfInstances(); print("N Of I (antes) = " + n); c = new Comp3(); //int i = Comp3.getInstanceNumber(); //Erro: Um método não estático só pode ser invocado para um objecto int i = c.getInstanceNumber(); //int n = c.getNumOfInstances; //Erro: Um método estático só pode ser invocado para uma Class print("Instance Number = " + i); print(c.getInstancesRel()); } public static void main(String[] args) { showAndCreate(c0); showAndCreate(c1); showAndCreate(c2); } private static void print(String s){ System.out.println(s); } } 93 Modificador static – Exemplo 2 Ex10a\Comp3.java public class Comp{ private int n; static private int ncomp = 0; public Comp(){n = ++ncomp;} public static void main(String[] s){ Comp c1 = new Comp(); c1.printn("c1."); c1.printncomp("c1."); Comp c2 = new Comp(); c2.printn("c2."); c2.printncomp("c2."); c1.printn("c1."); c1.printncomp("c1."); } void printn(String s){System.out.println(s + "n = " + n);} void printncomp(String s){ System.out.println(s + "ncomp = " + ncomp); } } //O campo ncomp é partilhado por c1 e c2. Se c2 alterar ncomp essa alteração reflecte-se em c1 $>java Comp c1.n = 1 c1.ncomp = 1 c2.n = 2 c2.ncomp = 2 94 c1.n = 1 c1.ncomp = 2 Modificador final Modificador final • Quando usado na declaração da classe esta não pode ser derivada (superclasse) • Quando usado num método este não pode ser sobreposto • Usado da declaração de um campo este não pode ser actualizado (mas deve ser inicializado) • Usando em conjunto com o static serve para implementar constantes 96 Modificador final – Exemplo Ex18\Counter.java final public class Counter{ private int n = 0; final protected String nome; //o campo nome tem de ser inicializado no construtor final protected String ID = "a0"; //inicialização do campo void serveParaNada(String lixo){ //nome = lixo; //um campo final não pode ser alterado //ID = lixo; //a atribuição a um campo final dá sempre erro } public Counter(int n){ this.n = n; /* dentro do construtor a inicialização é possível e, * no caso do nome, necessária*/ nome = "sem nome"; //ID = "zero"; // Erro: ID já foi inicializado } public Counter(int n, String nome){ this(n); //chamado outro construtor //this.nome = nome; //Erro: nome já foi inicializado } final public void inc(){++n;} //não pode ser sobreposto } 97 Modificador final – Exemplo (2) Ex18\ModCounter.java final public class ModCounter extends Counter { public int n; //public void inc(){}//ERRO! o inc é um método final em Counter ModCounter(String nome, int i, int n){ super(i,nome); this.n = n; } ModCounter(int n){ super(0); this.n = n; } } //class ExtModCounter extends ModCounter{} //Erro: ModCounter é final 98 Modificador abstract Modificador abstract • Permite indicar que uma classe não foi totalmente implementada. • Quando usado na declaração da classe esta não pode ser instanciada • Uma classe abstract não tem instâncias (objectos) • Uma classe abstract tem de ser derivada • Quando usado num método este tem de ser obrigatoriamente sobreposto na subclasse • • • • Não tem corpo Só existe a sua declaração A implementação é deixada para a subclasse Implica que a classe também seja declarada como abstract 100 Modificador abstract – Exemplo Ex19\Counter.java abstract public class Counter{ protected int c = 0; final protected String nome; public Counter(int n){ c = n; nome = ""; } public Counter(int n, String nome){ c = n; this.nome = nome; } abstract public void inc(); //inc() não tem corpo public int getVal(){return c;} } 101 Modificador abstract – Exemplo (2) Ex19\ModCounter.java abstract class AbsModCounter extends Counter { public int n; //public void inc(){} //não precisa de ser implementada nesta classe AbsModCounter(String nome, int i, int n){ super(i,nome); this.n = n; } } public class ModCounter extends AbsModCounter{ //nesta class é obrigatorio implementar o método inc() public void inc(){c = ++c % n; } public ModCounter(String nome, int i, int n){super(nome,i,n);} public static void main(){ Counter c; //c = new Counter(0,"teste"); //Erro: Counter é abstract //c = new AbsMoCounter("teste",0,16); //Erro c = new ModCounter("teste",0,16); c.inc(); System.out.println("c = " + c.getVal()); } } 102 Inicialização dos Campos Inicialização • A inicialização dos campos membro pode ser feita de 4 modos: • • • • Omissão Explícita Blocos de inicialização Construtor 104 Inicialização • Inicialização por omissão • Declarando apenas as variáveis estas são inicializadas pelo java de acordo com a tabela anexa Tipo Valor inicial númerico 0 booleano false referência null 105 Inicialização • Explícita • Ao declarar o campo atribui-se-lhe um valor fixo ou o resultado de uma expressão • Blocos de inicialização • O Java permite definir blocos de código como membros da classe. Estes blocos são executados quando: • a classe é carregada (blocos estáticos) • o objecto é criado (blocos não estáticos) • Construtor • A inicialização é feita no corpo do construtor 106 Inicialização omissa – Exemplo Ex12\Comp.java public class Comp{ private int n; private String nome; static private int ncomp; private boolean activo; static public void main(String[] s){ System.out.println("ncomp = " + ncomp); Comp c = new Comp(); System.out.println("n = " + c.n); System.out.println("nome = " + c.nome); System.out.println("activo = " + c.activo); } } $>java Comp ncomp = 0 n = 0 nome = null activo = false 107 Inicialização explicita – Exemplo Ex14\Comp.java public class Comp{ //pode ser o valor de um método membro estático private int n = initN(); //pode ser uma constante private String nome = "madrinha precisa-se"; //pode ser uma expressão static private int ncomp = 100 * 2; static private int initN(){ return ++ncomp; } static public void main(String[] s){ System.out.println("ncomp = " + ncomp); Comp c = new Comp(); System.out.println("n = " + c.n); System.out.println("nome = " + c.nome); } } 108 Inicialização por bloco – Exemplo Ex13\Comp.java public class Comp{ private int n; private String nome; {//bloco de inicialização para cada objecto nome = "madrinha precisa-se"; n = initN(); /* A inicialização pode ser feita recorrendo a * métodos membro mas estes têm de ser estáticos*/ } static private int ncomp; static private int initN(){return ++ncomp;} static { //bloco de inicialização para a class ncomp = 100; } static public void main(String[] s){ System.out.println("ncomp = " + ncomp); Comp c = new Comp(); System.out.println("n = " + c.n); System.out.println("nome = " + c.nome); } } 109 Inicialização por Construtor – Exemplo Ex15\comp.java public class Comp{ private int n; private String nome; static private int ncomp; public Comp(int x){ n = x; nome = "Madrinha precisa-se"; } static public void main(String[] s){ System.out.println("ncomp = " + ncomp); Comp c = new Comp(5); System.out.println("n = " + c.n); System.out.println("nome = " + c.nome); } } 110 Interfaces Interfaces • Uma interface é um conjunto de requisitos para as classes que quiserem ser conformes • Uma interfaces consiste numa colecção de constantes e declarações de métodos com as respectivas assinaturas • Os métodos não têm corpo (são apenas declarados mas não implementados) • As interfaces fornecem um mecanismo para impor à(s) classe(s) determinados métodos. • Assegura que os objectos disponibilizam certos métodos sem impor à partida qual a acção resultante 112 Interfaces (2) • As interfaces são similares às classes mas: • Os campos são sempre public static final • Na declaração dos campos pode-se omitir estes modificadores • Obriga à inicialização explicita • Os métodos são sempre public abstract • Na declaração dos métodos pode-se omitir estes modificadores • Uma interface nunca tem instâncias (tal como uma classe abstracta) • Uma interface não tem construtores 113 Interfaces (3) • A declaração de um interface obedece a esta regra: <modificador>* interface <InterfaceName> { [public final satic] <camposestaticosfinaispublicos>* [public abstract] <membrossemcorpo>* } • Uma interface também pode herdar de outra interface: <modificador>* interface <SubInterfaceName> [extends<SuperInterfaceName>]{ [public final static] <camposestaticosfinaispublicos>* [public abstract] <membrossemcorpo>* } 114 Interfaces – Exemplo Ex20\SO.java public interface SO{ String getName(); String getVersion(); //String getVersion2(){}; //SO(){} String WIN = "Windows"; String UNIX = "Unix"; } //os métodos são sempre public abstract //Não tem corpo //Erro: os métodos são abstractos //Erro: as interfaces não tem construtores //os campos são sempre public static final //logo tem de ser inicialização explicita Ex20\Unix.java //uma interface pode herdar de outra public interface Unix extends SO { String LINUX = "Linux"; String HPUX = "HP-UX"; String AIX = "AIX"; String getVariante(); } 115 Interfaces (4) • Uma interface é implementada numa ou mais classes • Uma classe, não abstracta, que implemente uma interface tem sempre de implementar todos os métodos da interface • A declaração de implementação de uma interface é feita na declaração da classe <modificador>* class <SubClassName> [extends <SuperClassName>] implements <InterfaceName1>, InterfaceName2,... { <membros>* } 116 Interfaces – Exemplo (2) Ex20\Windows.java public class Windows implements SO { private final String version; public String getName() {return WIN;} public String getVersion() {return version;} Windows(String v){version = v;} } Ex20\Dist.java public interface Dist { String REDHAT = "RedHat"; String MANDRAKE = "Mandrake"; String getDist(); } Ex20\Linux.java //Como a classe é abstracta, pode mas não precisa de implementar os métodos das interfaces abstract public class Linux implements Unix, Dist{ protected final String kernelversion; Linux(String k){kernelversion = k;} // dois métodos implementados. Um de Unix e outro de SO public String getName(){return UNIX;} public String getVariante(){return LINUX;} // As subclasses já só precisam de implementar os restantes métodos 117 } Interfaces – Exemplo (3) Ex20\Mandrake.java public class Mandrake extends Linux { private final String version; public String getVersion(){ return "dv = "+version+"\nkv = "+kernelversion; } Mandrake(String v, String kv){ super(kv); version = v; } public String getDist(){return MANDRAKE;} } • A class Mandrake implementa implicitamente as interfaces Unix e Dist, logo tem de implementar os métodos : • • • • getName() e getVersion() de SO; getVariante() de Unix; getDist() de Dist; Visto que a superclasse Linux já implementou os métodos getName() e getVariante() aqui é suficiente definir o getVersion() e o getDist() 118 Interfaces – Teste do Exemplo Ex20\Teste.java public class Teste { static void print(String s){System.out.println(s);} static void showSO(SO so){ print(so.getName()); print(so.getVersion()); } static void showUnix(Unix u){ showSO(u); print(u.getVariante()); } static void showDist(Linux l){ showUnix(l); print(l.getDist()); } public static void main(String[] args) { Mandrake m = new Mandrake("8.2","2.4"); Windows w = new Windows("XP"); showDist(m); print("-----------"); showSO(w); } } $>java Teste Unix dv = 8.2 kv = 2.4 Linux Mandrake ----------Windows XP 119 Interfaces (4) • Em Java a herança múltipla é conseguida com o recurso a interfaces public class Linux implements Unix, Dist • Diferenças entre as interfaces e as classes abstractas • As interfaces não podem ter: • • • • Métodos estáticos Construtores Os métodos não podem ter implementação Membros não públicos • Um classe pode herdar de múltiplas interfaces mas não de múltiplas classes abstractas 120 Excepções Excepções • As Excepções permitem definir o comportamento dos métodos em circunstâncias excepcionais • Ocorrendo uma excepção o código abandona o percurso normal do método e salta para o código de tratamento da excepção método(){ try{ código onde não ocorreu qualquer excepção código onde ocorreu a excepção E código que não chegou a ser corrido }catch (Excepção E){ código que vai tratar a excepção E } } 122 Excepções (2) • O segmento de código onde podem ocorrer excepções é delimitado pela construção try{código onde podem ocorrer excepções} • Para apanhar as excepções usa-se a construção catch(Excepção E){código para tratar a excepção} • É possivel ter vários “catches” para tratar diferentes tipos de Excepções try{código onde ocorrem diversas excepções} catch(Excepção E) {código para tratar a excepção} catch(Excepção F) {código para tratar a excepção} catch(Excepção G) {código para tratar a excepção} finally{este código é executado sempre quer haja ou não excepções} 123 Excepções (3) • Após uma excepção os diversos “catchs” são percorridos por ordem até ser encontrado um com uma excepção do tipo da ocorrida • Depois de encontrar o “catch” respectivo os restantes são ignorados • Se F é uma subclasse de E então o “catch” do F deve ser incluído antes do “catch” de E • Uma instância de F é uma instância de E logo ao passar pelo “catch” E a condição é verificada e o código de E executado • Uma técnica para evitar multiplos “catchs“ é colocar um “catch” de uma superclasse de todas as possíveis excepções Æ Perde-se o tratamento especializado de cada excepção mas pode ser uma opção em estágios preliminares de desenvolvimento 124 Excepções (4) • O finally é opcional. • O código do finally é sempre executado • Mesmo que seja encontrado um return no código do try ou do catch 125 Classes para excepções Object Throwable Checked Unchecked Não são verificadas pelo compilador A inexistência de código de tratamento não gera erros na compilação ... Error RuntimeException ... São verificadas pelo compilador. A inexistência de código de tratamento gera erros na compilação NullPointerException Exception ... IOException EOFException ... SocketException ... BindException 126 Excepções (4) • Uma excepção é gerada por disparo de um objecto “throwable” if (cond) throw new Exception() • Uma excepção é sempre um objecto de uma subclasse da classe throwable • Normalmente da classe Exception ou das suas derivadas 127 Excepções (5) • Na compilação as excepções dividem-se em dois tipos: • Checked • É verificado na compilação se há tratamento, ou redisparo destas excepções • Numa aplicação Java as excepções checked tem de ser sempre tratadas • Unchecked • Não é verificado pelo compilador. O que não implica que em runtime não seja possível dar lugar à paragem da aplicação 128 Excepções – Exemplo 1 Ex21\ModCounter.java public class ModCounter{ private int c = 0; private int n; public void inc(){c = ++c % n; } public ModCounter(int i, int n){ try{ if (i > n) throw new Exception(i + " > "+ n); if (i < 0) throw new Exception(i + " < 0"); c = i; this.n = n; } catch(Exception e){ e.printStackTrace(); } } public int getVal(){return c;} public void setVal(int i) throws Exception{ if (i > n) throw new Exception(i + " > " + n); c = i; } } 129 Excepções (6) • Um método no qual podem ocorrer excepções checked tem duas opções • Ou faz o tratamento com try e catch • Ou redispara as excepções, declarando no método quais as Excepções que podem ocorrer <modificadores> <tipo> <nomedometodo>(Args) throws Exception1, Exception2,...{ ... } • É da responsabilidade de quem chama o método fazer o tratamento das excepções • Um método pode tratar algumas excepções e (re)disparar outras • Um “catch” pode redisparar a mesma excepção 130 Excepções – Exemplo 2 Ex22\ModCounter.java public class ModCounter{ private int c = 0; private int n; public void inc(){c = ++c % n; } public ModCounter(int i, int n) throws InitException { if (i > n) throw new InitException(i + " > " + n); if (i < 0) throw new InitException(i + " < 0"); c = i; this.n = n; } public int getVal(){return c;} public void setVal(int i) throws ModException{ if (i > n) throw new ModException(i + " > " + n); c = i; } } 131 Excepções – Exemplo 2 (2) Ex22\InitException.java public class InitException extends Exception { public final String s; public InitException(String a){ s = "Erro na inicialização:\n\t" + a; } } Ex22\ModException.java public class ModException extends Exception { public ModException(String s){super(s);} } 132 Excepções – Exemplo 2 (3) Ex22\Teste.java class NegativeException extends ModException { NegativeException(String s){super(s);} String getMoreInfo(){ return "Erro:\n\tO argumento do setVal”+ “ tem de ser positivo"; } } public class Teste{ static ModCounter c; static void setVal(int v) throws ModException, NegativeException{ if (v < 0) throw new NegativeException( v + " < 0"); c.setVal(v); } public static void print(String s){ System.out.println(s); } public static void print(int n){ System.out.println(n); } Continua 133 Excepções – Exemplo 2 (4) Ex22\Teste.java (cont.) } $>java Teste Erro na inicialização: 20 > 16 finally: Por aqui passo sempre,haja ou não erro public static void main(String[] s){ try{ c = new ModCounter(0,16); c = new ModCounter(20,16); //as linhas que se seguem não serão processadas devido à //ocorrência de uma excepção do tipo InitException setVal(7); print(c.getVal()); c.setVal(18); print(c.getVal()); setVal(-10); print(c.getVal()); return; }catch (NegativeException te){ // o Negative Exception tem de surgir antes do ModException print(te.getMoreInfo()); }catch (ModException me){ print ("ERRO: " + me.getMessage()); //O getMessage é membro da superclass Trowable me.printStackTrace(); //O printStackTrace é membro da }catch(InitException ie){ // superclass trowable print(ie.s); }finally{print("finally: Por aqui passo sempre, haja ou não erro");} } 134 Classes do Java Classes Java Java API Object Class ... String ... ... Throwable Excepion Number Character ... Servlet PrinterWriter Subclasse2 Applet Minhaclasse Subclasse2 Math ... System ... Integer Socket PrinterStream Outraclasse InputStream Classes do utilizador Subclasse1 Qualquer classe é automaticamente subclasse de Object 136 API do Java • • A utilização de qualquer classe das packages obriga a utilizar o import No entanto a package java.lang não precisa de ser explicitamente “importada” Package Classes java.lang Classes “core” do Java java.util Classes e Interfaces utilitárias java.math Matemáticas java.io Entrada e Saída – acesso a ficheiros, etc java.awt GUI javax.swing GUI usando swing java.applet Creates applets java.net Classes para acesso aos protocolos de rede Etc… Ver a API do Java 137 API do Java • http://java.sun.com/j2se/1.4.2/docs/api/index.html 138 Arrays Arrays • Os arrays em Java são objectos mas são manipulados de forma especial pelo programador • Declaração int v[]; Ou int[] v; • Alocação de espaço (memória) v = new int[n]; • n não precisa de ser uma constante. Pode ser uma variável ou uma expressão • Ou numa só instrução int[] v = new int[n]; 140 Arrays – Exemplo Ex23\Test.java public class Test{ public static void main(String[] s){ print(s); } private static void print(String[] s){ for (int n = 0; n < s.length; n++){ System.out.println("s["+n+"]="+s[n]); } } } $>java Test primeiro argumento e, julgo eu, o segundo argumento s[0]=primeiro s[1]=argumento s[2]=e, s[3]=julgo s[4]=eu, s[5]=o s[6]=segundo s[7]=argumento 141 Arrays • Inicialização v[2] = 3; • Declaração, reserva de espaço e inicialização int[] v = {3,7,6,8}; • Podem ser multidimensionais int[][] vv={{1,3},{7,4,5}}; int[][] vw= new int[5][3]; • Um arrays de arrays pode conter arrays de dimensão diferente • Pode-se declarar arrays de objectos Obj[] ov = new Obj[4]; ov[2] = new Obj(); 142 Arrays – Exemplo 2 Ex24\Test.java public class Test{ public static void main(String[] s){ int[][] v = {{3,4},{5,3,8}}; for(int n = v.length; n-- > 0;) for(int k = v[n].length; k-- > 0;) print("v[" + n + "][" + k + "]=" + v[n][k]); } private static void print(String s){ System.out.println(s); } } $>java Test v[1][2]=8 v[1][1]=3 v[1][0]=5 v[0][1]=4 v[0][0]=3 143 Arrays – Exemplo 2 Ex25\Test.java class MeuObjecto{ private int k; private int n; MeuObjecto(int a, int b){k = a; n = b;} int getProd(){return n * k;} } public class Test{ public static void main(String[] s){ int n = 2, k = 3; MeuObjecto[][] mov = new MeuObjecto[n][k]; while (n-- > 0){ int j = k; while(j-- > 0) mov[n][j] = new MeuObjecto(n+1,j+1); } while(k-- > 0) print(mov[1][k].getProd()); } $>java Test private static void print(int i){ 6 4 System.out.println(i); 2 } } 144 Arrays • Os arrays são implementados internamente com objectos de uma classe “built-in” (não listada na API Java) • São subclasses de Object e herdam, naturalmente, todos os membros deste • • • • clone equals finalize ... • Adiciona aos métodos de Object o campo final length 145 Strings Strings • As Strings são objectos definidos na classe java.lang.String mas tem algumas particularidades não partilhadas por outros objectos • Podem ser inicializados sem recurso ao operador new String s = “Esta é uma String”; • Tem definida a operação de concatenação com o operador + String s1 = s + “ concatenada”; • Como objectos que são, as variáveis do tipo String são referências • O teste s == s1 compara se s e s1 se referem ao mesmo objecto e não se as strings são iguais 147 Entrada/Saída Classe File • Usada para representar o sistema de ficheiros • É apenas uma abstracção: a existência de um objecto File não significa a existência de um ficheiro ou uma directoria. • Contém métodos para testar a existência de ficheiros, para definir permissões (nos S.O.s onde for aplicável), para apagar ficheiros, criar directorias, listar o conteúdo de directorias, etc.. 149 Classe File (2) • Alguns métodos • • • • • • • • • String getAbsolutePath() String getParent(): devolve a directoria (objecto File) superior boolean exists() boolean isFile() boolean isDirectory() boolean delete(): tenta apagar a directoria ou ficheiro long length(): devolve o tamanho do ficheiro em bytes boolean mkdir(): cria uma directoria String[] list(): lista dos ficheiros contido na directoria 150 Classe File – Exemplo Ex26\Fileteste.java import java.io.*; public class FileTeste { public static void main(String[] args){ try { File directoria = new File("teste"); directoria.mkdir(); // cria, se possível File ficheiro = new File(directoria, "lixo.txt"); FileOutputStream out= new FileOutputStream(ficheiro); // se ficheiro não existe, tenta criar out.write( new byte[]{'l','i','x','o'} ); //escrever uma sequência de bytes out.close(); Continua 151 Classe File – Exemplo (2) Ex26\Fileteste.java (cont.) File subdir = new File(directoria, "subdir"); subdir.mkdir(); String[] ficheiros = directoria.list(); for (int i = 0; i<ficheiros.length; i++) { File filho = new File(directoria, ficheiros[i]); System.out.println(filho.getAbsolutePath()); } if (ficheiro.exists()) { ficheiro.delete(); } } catch (IOException e){ System.exit(1); } } } 152 Fluxos de Entrada/Saída • Um fluxo (stream) é um conceito abstracto. Representa uma sequencia linear de bytes ou caracteres de uma entrada ou para uma saída. • Existem várias fontes de onde se deseja ler ou destinos para onde se deseja escrever ou enviar dados • • • • Ficheiros Conexões de rede Consola (teclado / Monitor) Memória • Existem várias formas diferentes de ler/escrever dados • Sequencialmente / aleatoriamente • Como bytes / como caracteres • Linha por linha / palavra por palavra, ... 153 Classes e Interfaces para fluxos de E/S • A package java.io fornece objectos que abstraem • fontes/destinos (nós) e fluxos de bytes e caracteres • Dois grupos • orientado ao byte: InputStream e OutputStream • orientado ao caractere (char): Reader e Writer 154 E/S orientada ao byte • InputStream • Classe abstracta para lidar com fluxos de bytes de entrada e nós de fonte (dados para leitura). • Método principal: read() • OutputStream • Classe abstracta para lidar com fluxos de bytes de saída e nós de destino (dados para gravação). • Método principal: write() 155 E/S orientada ao byte (2) • Principais implementações • Entrada/leitura no nó fonte: • FileInputStream (ficheiros), • ByteArrayInputStream (memória) e • PipedInputStream (pipe). • Entrada/tratamento de fluxo: • FilterInputStream (abstract) e respectivas subclasses • Saída/escrita no nó destino: • FileOutputStream (ficheiros), • ByteArrayOutputStream (memória) e • PipedOutputStream (pipe). • Saída/tratamento de fluxo: • FilterOutputStream (abstract) e respectivas subclasses. 156 E/S orientada ao byte – Exemplo Ex27\FileCopia.java import java.io.*; //Esta aplicação copia um ficheiro: fonte -> destino public class FileCopia { public static void main(String[] args){ if (args.length>1){ try { String nomeFonte = args[0]; String nomeDestino = args[1]; File fonte = new File(nomeFonte); File destino = new File(nomeDestino); if (fonte.exists() && !destino.exists()) { FileInputStream in = new FileInputStream(fonte); FileOutputStream out = new FileOutputStream(destino); byte[] buffer = new byte[8192]; //array de bytes int length = in.read(buffer); while ( length != -1) { // -1 sinaliza o EOF //grava apenas os bytes lidos e não o buffer completo out.write(buffer, 0, length); length = in.read(buffer); } Continua 157 E/S orientada ao byte – Exemplo (2) Ex27\FileCopia.java (cont.) in.close(); out.flush(); out.close(); } } catch (IOException e){System.exit(1);} //é necessário tratar as excepções } else {System.out.println("java FileCopia ffonte fdestino");} } } 158 FilterInputStream • Recebe fonte de bytes e oferece métodos para ler dados filtrados. Implementações (subclasses): • DataInputStream: • readInt(), • readUTF(), • readDouble() • BufferredInputStream: • read() mais eficiente • ObjectInputStream: • readObject() lê objectos serializados 159 FilterOutputStream • Recebe destino de bytes e escreve dados via filtro. Implementações: • DataOutputStream: • writeUTF(), • writeInt(), etc. • BufferedOutputStream: • write() mais eficiente • ObjectOutputStream: • writeObject() serializa objectos • PrintStream: • classe que implementa println() 160 E/S orientada ao caractere • Reader • Classe abstracta para lidar com fluxos de caracteres de entrada: método read() lê um caractere (16 bits) de cada vez. • Writer • Classe abstracta para lidar com fluxos de caracteres de saída: método write() grava um caractere de cada vez. 161 E/S orientada ao caractere (2) • Principais implementações • Entrada/leitura no nó fonte: • • • • FileReader (ficheiro), CharArrayReader (memória), PipedReader (pipe) e StringReader (memória). • Entrada/tratamento de fluxo: • • • • FilterReader (abstract), BufferedReader, InputStreamReader (conversor de byte para char), LineNumberReader 162 E/S orientada ao caractere (3) • Principais implementações (cont.) • Saída/escrita no nó destino: • • • • FileWriter (ficheiro), CharArrayWriter (memória), PipedWriter (pipe) e StringWriter (memória). • Saída/tratamento de fluxo: • • • • FilterWriter (abstract), BufferedWriter, OutputStreamWriter (conversor de char para byte), PrintWriter 163 E/S orientada ao caractere – Exemplo Ex28\InputCmd.java import java.io.*; //permite ler da consola. Faz echo para o monitor daquilo que lê public class InputCmd { public static String readCmd(String inputMsg){ System.out.print(inputMsg); //InputStream/byteÆInputStreamReader/charÆBufferedReader/char BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); String input = null; try { input = br.readLine(); // lê uma linha } catch (IOException ioe) { System.out.println("IO error trying to read from the cmd!"); System.exit(1); } return input; } public static void main (String[] args) { String s = readCmd("Input: "); System.out.println("Echo input: "+s); } } 164 Concorrência Threads • Threads Æ dividem o problema em tarefas independentes • Threads vs. Processos • Processos: tarefas em espaços de endereços diferentes que comunicam entre si através de pipes fornecidos pelo S.O. • Threads: tarefas dentro do espaço de endereços da aplicação que comunicam entre si através de pipes fornecidos pela JVM • Em Java o suporte de threads é nativo • Um thread é um objecto que parece e age como um programa individual. 166 Como criar um thread • Há duas estratégias • Herdar da classe java.lang.Thread • Implementar a interface java.lang.Runnable • Herdar da classe Thread • O objecto é um thread, e sobrepõe o comportamento associado à classe Thread • Implementar a interface Runnable • O objecto, que define o comportamento da execução, é passado para um objecto Thread que o executa. • Em ambos os casos • É necessário sobrepor o método run() que é o "main()" do Thread • A invocação do método start() inicia o thread (invoca run()) 167 • Quando o método run() termina, o thread morre. Criação de threads – Exemplo Ex29\EstThread.java class EThread extends Thread { int n; EThread(int i){n=i;} public void run(){ for (int i=0; i<5;i++){ System.out.println("Thread"+n+": "+i); try{ Thread.sleep(10); //10ms } catch(InterruptedException e){System.exit(1);} } $>java EstThread } Thread1: 0 } Thread2: 0 Thread1: 1 public class EstThread{ Thread2: 1 public static void main(String[] args){ Thread1: 2 EThread t1 = new EThread(1); Thread2: 2 EThread t2 = new EThread(2); Thread1: 3 t1.start(); Thread2: 3 t2.start(); Thread1: 4 } Thread2: 4 } 168 Criação de threads – Exemplo 2 Ex29\ImpRunnable.java class IThread implements Runnable { int n; IThread(int i){n=i;} public void run(){ for (int i=0; i<5;i++){ System.out.println("Thread"+n+": "+i); try{Thread.sleep(10); //10ms } catch(InterruptedException e){System.exit(1);} } } $>java impRunnable } Thread1: 0 Thread2: 0 public class ImpRunnable { Thread1: 1 public static void main(String[] args){ Thread2: 1 IThread it1 = new IThread(1); Thread1: 2 IThread it2 = new IThread(2); Thread2: 2 Thread t1 = new Thread(it1); Thread1: 3 Thread t2 = new Thread(it2); Thread2: 3 t1.start(); Thread1: 4 t2.start(); Thread2: 4 } } 169 Ciclo de vida de um thread wait() sleep() I/O blocking start() Thread t = new Thread() run() acaba (stop()) Executável Bloqueado notify() sleep time-out I/O acabou run() acaba (stop()) run() acaba (stop()) Morto 170 Classe Thread • Principais métodos: • Estáticos • Thread currentThread() • Devolve a referência para o thread que está a executar no momento • void sleep(long tempo) • Coloca o thread bloquado durante pelo menos tempo ms. • void yield() • Faz com que o thread atual pare e permita que outros que estão na sua fila de prioridades executem. 171 Classe Thread (2) • Principais métodos (cont.): • De instância (não estáticos) • void run() • É o "main()" do Thread. Deve ser implementado no Thread ou no objecto Runnable passado ao thread • void start() • É um bootstrap. Faz o JVM chamar o run() • boolean isAlive() • Verifica se thread está vivo 172 Monitor • Permite proteger os recursos impedindo que mais do que um thread os utilize em simultâneo. • Recorre-se à keyword synchronized • Por questões de desempenho deve-se limitar a sua aplicação ao essencial. 173 Monitor (2) • Aplica-se a blocos ou métodos. • por bloco: synchronized (this){ <codigo protegido aqui> } • por método synchronized <outros modificadores>* <tipo> <nome>(Arg*){ <codigo protegido aqui> } 174 Sem Monitor – Exemplo Ex30a\SemMonitor.java $>java SemMonitor + 1000, Saldo= 1000 - 1000, Saldo= 0 + 1000, Saldo= 1000 - 1000, Saldo= 0 + 1000, Saldo= 1000 - 1000, Saldo= 0 + 1000, Saldo= 1000 - 1000, Saldo= 0 - 1000, Saldo= -1000 + 1000, Saldo= 0 class Utilizador extends Thread { Conta conta; Utilizador (Conta c){ conta=c; } public void run(){ for (int i=0;i<5;i++) conta.movimentar(); } } class Conta { private int saldo=0; void movimentar(){ //o saldo nunca deve ser inferior a 0 if (saldo>=1000) { try { Thread.sleep((long)(Math.random()*1000)); //adormece durante alguns ms } catch (InterruptedException e){ System.exit(1);} saldo-=1000; //levantamento System.out.println("- 1000, Saldo= "+saldo); } else { saldo+=1000; //depósito System.out.println("+ 1000, Saldo= "+saldo); } } } continua 175 Sem Monitor – Exemplo (2) Ex30a\SemMonitor.java (cont.) public class SemMonitor { public static void main(String[] args){ Conta c = new Conta(); new Utilizador(c).start(); new Utilizador(c).start(); } } 176 Com Monitor – Exemplo Ex30b\CemMonitor.java $>java SemMonitor + 1000, Saldo= 1000 - 1000, Saldo= 0 + 1000, Saldo= 1000 - 1000, Saldo= 0 + 1000, Saldo= 1000 - 1000, Saldo= 0 + 1000, Saldo= 1000 - 1000, Saldo= 0 + 1000, Saldo= 1000 - 1000, Saldo= 0 class Utilizador extends Thread { Conta conta; Utilizador (Conta c){ conta=c; } public void run(){ for (int i=0;i<5;i++) conta.movimentar(); } } class Conta { private int saldo=0; synchronized void movimentar(){ //o saldo nunca deve ser inferior a 0 if (saldo>=1000) { try { Thread.sleep((long)(Math.random()*1000)); //adormece durante alguns ms } catch (InterruptedException e){ System.exit(1);} saldo-=1000; //levantamento System.out.println("- 1000, Saldo= "+saldo); } else { saldo+=1000; //depósito System.out.println("+ 500, Saldo= "+saldo); } } } continua 177 Com Monitor – Exemplo (2) Ex30b\SemMonitor.java (cont.) public class ComMonitor { public static void main(String[] args){ Conta c = new Conta(); new Utilizador(c).start(); new Utilizador(c).start(); } } 178 Comunicações TCP/IP Pilha Protocolar TCP/IP • Rede • IP (Internet protocol) • ICMP (Internet Control Message Protocol) • IGMP (Internet Group Management Protocol) • Transporte • TCP (transmission Control Protocol) (orientado à conexão) • UDP (User datagram Protocol) (orientado ao datagrama) • Exemplo de outros protocolos (não suportados pelo Java): • SCTP (Stream Control Transmission Protocol) (orientado à conexão) • DCCP (Datagram Congestion Control Protocol) (orientado ao datagrama) • Aplicação • HTTP, SMTP, POP3, FTP, etc. 180 Modelos de distribuição de dados • Unicast • De um ponto para um outro ponto • Endereço destino identifica/localiza ponto destino Æ endereço unicast • Multicast • De um ponto para um grupo de pontos • Endereço destino identifica o grupo destino • Nós destino associam os seus endereços (unicast) ao grupo destino • Broadcast • De um ponto para todos os pontos • Endereço destino corresponde a um endereço universal correspondido por todos os nós 181 TCP • Transmission Control Protocol • Protocolo de transporte orientado à conexão • Antes de começar a enviar dados é necessário proceder ao estabelecimento da conexão • Depois dados são enviados/recebidos sob a forma de um fluxo de bytes • Unicamente unicast • Não existe um limite para o tamanho das mensagens a enviar. • Fiável Æ Implementa mecanismo de recuperação de dados • Modelo cliente/servidor Æ servidor fica à espera que o cliente inicie o estabelecimento da conexão. 182 UDP • User Datagram Protocol • Protocolo de transporte orientado ao datagrama • Cada mensagem é enviada num datagrama independente dos (possíveis) restantes. • Não é necessária qualquer sinalização prévia. • Cada datagrama contém toda a informação necessária para a correcta comunicação (portos origem e destino) Æ necessário especificar/verificar aquando do envio/recepção de cada datagrama • Pode ser utilizado em todos os modelos de distribuição. • Tamanho das mensagens limitado a 64 kbytes (cabeçalho IP incluído) • Não é fiável Æ Não implementa mecanismos de recuperação de datagramas 183 java.net • TCP é suportado pelas classes • • Socket (permite a comunicação através de uma conexão TCP) SeverSocket (permite ao servidor ficar à escuta de pedidos de conexão) • UDP é suportado pelas classes • • • DatagramSocket (permite a comunicação via UDP) DatagramPacket (datagrama UDP) MulticastSocket (permite a comunicação via UDP em multicast) • Endereçamento • • InetAddress (representa um endereços IP) URL (representa um URL e oferece um conjunto de operações para comunicação) 184 Classe Socket • Ponto de contacto entre a aplicação e a conexão TCP • Principais construtores • • Socket() Socket(InetAddress address, int port) • Cria um socket e conecta-o a um socket em address/port. • Socket(String host, int port) • Cria um socket e conecta-o a um socket em host/port. • Principais métodos servem para obter fluxos de entrada, saída • • getInputStream(), getOutputStream() close() • Depois de obtido os fluxos, basta ler ou escrever dados como se de um ficheiro se tratasse. 185 Classe ServerSocket • Permite a um servidor TCP ficar à escuta num dado porto (local), até receber um pedido, para depois devolver um socket que fica associado à nova conexão • Principais contrutores • ServerSocket(int port) • Fica à escuta em no porto port de todas as interfaces (endereços IP) locais • ServerSocket(int port, int backlog, InetAddress bindAddr) • Fica à escuta no porto port do endereço bindAddr • Principal método • accept() • Aceita a conexão e devolve um socket para acesso à mesma 186 Cliente TCP – Exemplo Ex31\ClienteTcpHttp.java //Esta aplicação é um cliente TCP que faz o pedido de uma página a um servidor HTTP import java.io.*; import java.net.*; public class ClienteTcpHttp { public static void main(String[] args) throws IOException { Socket socket = null; PrintWriter out = null; BufferedReader in = null; try{ //cria o socket e associa-o a um endereço socket = new Socket("www.google.com",80); out = new PrintWriter(new OutputStreamWriter( socket.getOutputStream()), true); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (UnknownHostException e) { System.out.println("Host desconhecido"); System.exit(1); } catch (IOException e) { System.out.println("Não foi possível estabelecer uma conexão"); System.exit(1); } 187 Continua Cliente TCP – Exemplo (2) Ex31\ClienteTcpHttp.java (cont.) // envia ao servidor o pedido da página por omissão (index.html...) out.println("GET / HTTP/1.1\r\n"); //não esquecer o \r\n String resp=""; while ((resp = in.readLine()) != null) { System.out.println(resp); //imprime a resposta do servidor } out.close(); //fecha os fluxos e depois o socket in.close(); socket.close(); } } 188 Servidor TCP – Exemplo Ex32\EchoServer.java //Esta aplicação é um servidor TCP que devolve o que recebe (faz echo) import java.net.*; import java.io.*; public class EchoServer { public static void main(String[] args) throws IOException{ //fica associado ao porto local 3000 ServerSocket serverSocket = new ServerSocket(3000); Socket clienteSocket=null; try { //fica à espera (escuta) de uma conexão clienteSocket = serverSocket.accept(); //o socket para escuta é diferente do socket para a conexão } catch (IOException e) { System.out.println("O accept falhou"); System.exit(-1); } Continua 189 Servidor TCP – Exemplo (2) Ex32\EchoServer.java (cont.) PrintWriter out = null; BufferedReader in = null; out = new PrintWriter(new OutputStreamWriter( clienteSocket.getOutputStream()), true); in = new BufferedReader(new InputStreamReader( clienteSocket.getInputStream())); String str=""; while ((str = in.readLine()) != null) { //quando recebe uma string do cliente imprime-a no monitor e //deveolve-a (echo) System.out.println(str); out.println(str); } out.close(); //primeiro fecham-se os fluxos e só depois os sockets in.close(); clienteSocket.close(); serverSocket.close(); } } 190 Servidor TCP com threads Exemplo Ex37\EchoServerThread.java import java.net.*; import java.io.*; class Connection extends Thread { private Socket clienteSocket; static int stConNum=1; int ConNum=stConNum++; public Connection(Socket cliente) { clienteSocket = cliente; } public void run() { PrintWriter out = null; BufferedReader in = null; try { out = new PrintWriter(new OutputStreamWriter( clienteSocket.getOutputStream()), true); in = new BufferedReader(new InputStreamReader(clienteSocket.getInputStream())); while ((str = in.readLine()) != null) { System.out.println("Con"+ConNum+": "+str); out.println(str); } out.close(); in.close(); clienteSocket.close(); }catch (IOException ioe) { System.out.println(ioe);} } } Continua 191 Servidor TCP com threads Exemplo (2) Ex37\EchoServerThread.java (cont.) public class EchoServerThread { public static final int PORT = 3000; public static void main(String[] args) throws IOException { ServerSocket sock = null; try { sock = new ServerSocket(PORT); while (true) { //Fica à escuta de conexões. Cada nova conexão é servida //num thread separado Thread worker = new Connection(sock.accept()); worker.start(); } } catch (IOException ioe) { System.out.println(ioe); } finally { if (sock != null) sock.close(); } } } 192 Classe InetAddress • Representa um endereço IP • Principais métodos estáticos • getLocalHost() • Devolve um objecto InetAddress com um endereço do host local • getByName(String hostname) • Devolve um objecto InetAddress com o endereço do host cujo nome é hostname • Principais métodos de instância • getHostAddress() • Devolve uma string com o IP do host a que o objecto InetAddress se refere • getHostName() • Devolve uma string com o nome do host a que o objecto InetAddress se refere 193 Classe InetAddress – Exemplo Ex34\ResLocalhost.java import java.net.*; //Para descobrir o IP e nome da máquina local public class ResLocalhost { public static void main(String[] args) throws Exception { InetAddress address = InetAddress.getLocalHost(); String ip = address.getHostAddress(); String nome = address.getHostName(); System.out.println("O seu computador chama-se "+nome+" e tem o endereço IP "+ip); } } 194 Classe DatagramSocket • Representa o ponto de acesso para envio e recepção de datagramas UDP (unicast e broadcast) • Principais métodos constructores • DatagramSocket() • Cria um socket e associa-o a um porto local livre (>1024) • DatagramSocket(int port) • Cria um socket e associa-o ao porto local port. • DatagramSocket (int port, InetAddress addr) • Cria um socket e associa-o ao porto local port e endereço local addr. 195 Classe DatagramSocket (2) • Principais métodos servem para enviar e receber datagramas • send(DatagramPacket p) • Envia um datagram a partir deste socket. • receive(DatagramPacket p) • Recebe um datagrama por este socket. • int getLocalPort() • Devolve o porto local ao qual o socket está associado. • close() • Fecha o socket. 196 Classe DatagramPacket • Representa um datagrama UDP. • Principais construtores: • DatagramPacket(byte[] buf, int length) • Cria um datagrama para enviar e receber mensagens com um tamanho máximo de length bytes. • DatagramPacket(byte[] buf, int length, InetAddress address, int port) • Cria um datagrama e inicializa-o com o par endereço/porto destino. 197 Classe DatagramPacket (2) • Principais métodos : • InetAddress getAddress() • Devolve o endereço do socket remoto. • void setAddress(InetAddress addr) • Altera o endereço destino para addr. • int getPort() • Devolve o porto do socket remoto. • void setPort(int port) • Altera o porto destino para port • byte[] getData() • Devolve a mensagem contida no datagrama. • void setData(byte[] buf) • Copia a mensagem contida em buf para o datagrama. 198 UDP envio – Exemplo Ex35\UDPSend.java import java.io.*; import java.net.*; // Envia um pacote para uma aplicação UDP, neste caso no localhost, no porto 3000 public class UDPSend { static final int port = 3000; //porto destino static final String host = “localhost”; //host destino public static void main(String args[]) throws Exception { //Obtem o endereço do host destino InetAddress address = InetAddress.getByName(host); String msg = "Isto é um teste"; int msglen = msg.length(); //Converte a string para um array de bytes byte[] message = msg.getBytes(); // inicializa o datagrama com os dados a enviar e os endereços DatagramPacket packet = new DatagramPacket(message, msglen, address, port); // Cria um socket e envia o datagrama através dele DatagramSocket socket = new DatagramSocket(); socket.send(packet); socket.close(); } } 199 UDP recepção – Exemplo Ex35\UDPReceive.java import java.io.*; import java.net.*; //Fica à espera de datagramas no porto 3000. Imprime qual a sua origem e qual o seu conteúdo public class UDPReceive { static final int port = 3000; public static void main(String args[]) throws Exception { byte[] buffer = new byte[1024]; DatagramSocket socket = new DatagramSocket(port); //fica à escuta no porto 3000 while(true) { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); // Espera pela chegada de um datagrama socket.receive(packet); // Converte o buffer de bytes para uma string através // do contrutor: String(byte[] bytes, int offset, int length) String s = new String(packet.getData(), 0, packet.getLength()); System.out.println("UDPReceive: received from " +packet.getAddress().getHostName()+ ":" +packet.getPort() + ": " + s); } } } 200 Classe MulticastSocket • Representa o ponto de acesso para envio e recepção de datagramas UDP em multicast • IPv4: 224.0.0.0 a 239.255.255.255 • IPv6: endereços começados por FF • Principais construtores: • MulticastSocket() • Cria um socket UDP para multicast. • MulticastSocket(int port) • Cria um socket UDP associado ao porto port para multicast. 201 Classe MulticastSocket (2) • Principais métodos: • void joinGroup(InetAddress mcastaddr) • Associa o socket a um grupo (endereço) multicast mcastaddr. • void leaveGroup(InetAddress mcastaddr) • Sai do grupo multicast mcastaddr. • void setLoopbackMode(boolean disable) • Inibe/permite o loopback de datagramas multicast. • void setTimeToLive(int ttl) • Altera o valor do TTL. 202 Multicast envio – Exemplo Ex36\MulticastSender.java import java.net.*; public class MulticastSender { public static void main(String[] args) throws Exception{ String addr = "230.0.0.1"; //endereço multicast int port = 6000; //porto destino InetAddress group = InetAddress.getByName(addr); String msg = "Aqui vai alguma coisa via multicast\r\n"; DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.length(), group, port); MulticastSocket ms = new MulticastSocket(); ms.send(dp); ms.close(); } } 203 Multicast recepção – Exemplo Ex36\MulticastReceiver.java import java.net.*; public class MulticastReceiver { public static void main(String[] args) throws Exception { int port = 6000; String addr= "230.0.0.1"; InetAddress group = InetAddress.getByName(addr); MulticastSocket ms = new MulticastSocket(port); ms.joinGroup(group); byte[] buffer = new byte[8192]; int c=0; while(c++<10){ DatagramPacket dp = new DatagramPacket(buffer, buffer.length); ms.receive(dp); String s = new String(dp.getData(), 0, dp.getLength()); System.out.println(s); } ms.leaveGroup(group); ms.close(); } } 204 Classe URL • Representa um Uniform Resource Locator • Ex: http://www.google.pt:80/index.html • • • • protocol: http host: www.google.pt port: 80 (porto por omissão associado ao http) file: index.html (ficheiro por omissão) • Principais contrutores • • • URL(String spec) URL(String protocol, String host, String file) URL(String protocol, String host, int port, String file) 205 Classe URL • Principais métodos • openStream() • Obtém um InputStream para os dados • openConnection() • Devolve um objecto URLConnection que contém métodos para ler o cabeçalho dos dados • getContent() • Devolve os dados directamente como Object se conteúdo for conhecido (texto, imagens, etc.) 206 Classe URL – Exemplo Ex33\GetPag.java import java.net.*; import java.io.*; public class GetPag { public static void main(String[] args) throws IOException { try { URL url = new URL("http://www.google.com"); InputStreamReader reader = new InputStreamReader(url.openStream()); BufferedReader br = new BufferedReader(reader); String linha = ""; while ( (linha = br.readLine()) != null) { System.out.println(linha); } } catch (MalformedURLException e) { System.out.println("URL mal formado");} } } 207