Arrays em Java - PDF
Document Details
Uploaded by ForemostRadon
Tags
Summary
Este documento descreve arrays em Java, incluindo declarações, exemplos e uso do operador new para criar arrays. Aborda também arrays de valores e arrays de referências, bem como métodos úteis da classe Arrays, como copyOf, copyOfRange, equals, fill, sort, toString e binarySearch.
Full Transcript
Arrays Em Java, os próprios arrays são objetos e é por isso que o tamanho (capacidade) de um array v pode ser facilmente obtido usando o atributo length (v.length) Declaração de arrays O array pode ser logo criado com os seus elementos, da seguinte forma elem...
Arrays Em Java, os próprios arrays são objetos e é por isso que o tamanho (capacidade) de um array v pode ser facilmente obtido usando o atributo length (v.length) Declaração de arrays O array pode ser logo criado com os seus elementos, da seguinte forma elementType[] arrayName ={initialValue0, initialValue1,…, initialValueN-1}; //exemplo: int[] v={5, 10, -2, 18}; //ou, alternativamente: int v[]={5, 10, -2, 18}; Ou então com recurso ao operador new elementType[] arrayName = new elementType[length]; //exemplo: int[] v = new int; //ou, alternativamente: int v[]= new int; //o operador new devolve uma referência para o novo array A Linguagem Java 34 Algoritmos e Estrutura de Dados Arrays de valores e arrays de referências Um array pode conter elementos primitivos, tais como carateres Ou conter referências para objetos A Linguagem Java 35 Algoritmos e Estrutura de Dados Métodos da classe Arrays Dada a importância dos arrays, o Java faculta-nos a classe Arrays com um conjunto de métodos estáticos que asseguram algumas das operações mais comuns (considere que A e B são arrays): copyOf(A,n) – devolve um array de tamanho n com a cópia de A; copyOfRange(A, s, t) – devolve um array de tamanho t-s com uma cópia dos elementos de A que se situem estre as posições s e t-1; equals(A,B) – devolve true se e só se os dois arrays contiverem os mesmos elementos e na mesma ordem; fill(A,x) – preenche todos os elementos do array A com o valor x; sort(A) – ordena os elementos do array A; toString(A) – retorna uma string com uma representação do array A; binarySearch(A, x) – devolve o índice do array ordenado A onde se encontra o elemento com o valor de x; Os arrays também podem ser copiados por clonagem int[] B = (int []) A.clone(); No caso dos arrays, não há vantagem em usar o método equals() do próprio objeto. Daí a utilidade do método estático equals() da classe Arrays A.equals(B) é o mesmo que fazer A==B (apenas compara as referências); Arrays.equals(A,B) é que compara efetivamente o conteúdo dos arrays. A Linguagem Java 36 Algoritmos e Estrutura de Dados Classes de embrulho (Wrapper types) Permitem representar como objetos valores de tipos primitivos. Nas bibliotecas do Java existem muitas estruturas de dados e algoritmos que foram especificamente desenhados para lidar apenas com tipos de objeto (não com tipos primitivos: float, int, …). Por exemplo, as coleções do Java apenas colecionam objetos. De forma a contornar esta limitação, o Java define uma classe de embrulho (wrapper class) para cada um dos tipos primitivos Designando-as com um nome idêntico ao dos tipos primitivos correspondentes, mas iniciados sempre em letra Maiúscula (Integer vs int; Double vs double; Charater vs char, …) O Java assegura a conversão automática (implícita) entre os tipos primitivos e as suas classes de embrulho um processo conhecido como autoboxing e unboxing. As classes de embrulho Integer, Long, Byte, Double, Float e Short derivam da classe abstrata Number. A Linguagem Java 37 Algoritmos e Estrutura de Dados Exemplo de classes de embrulho A Linguagem Java 38 Algoritmos e Estrutura de Dados Métodos úteis As classes de embrulho também nos facultam um conjunto de métodos estáticos de grande utilidade, como por exemplo: int Integer.parseInt(String s) //idem para outros tipos para converter uma string num inteiro; String Integer.toString(int i) //idem para outros tipos para converter um inteiro numa string ; boolean Character.isDigit(char c) para verificar se um carater é um dígito; boolean Character.isLetter(char c) para verificar se um carater é uma letra (do alfabeto inglês); boolean Character.isWhitespace(char c) para verificar se um carater é um carater branco (‘ ‘, ‘\n’, ‘\t’);... A Linguagem Java 39 Algoritmos e Estrutura de Dados Modificadores de acesso Os modificadores são colocados imediatamente antes da definição de uma classe, atributo ou método, de forma a impor-lhes restrições ou outras especificações adicionais. Os modificadores de acesso, em concreto, permitem definir se outras classes podem ou não aceder a um dado atributo ou método, ou à classe no seu todo. O controlo de acesso pode então dar-se a dois níveis diferentes: ao nível da classe – public ou package-private (afeta a classe por inteiro); ao nível do membro – public , protected , private ou package-private (afeta apenas o membro); Modificadores de acesso à classe: public – torna a classe acessível a toda e qualquer outra classe; Por omissão, a classe fica com a proteção conhecida como package-private, o que leva a que a classe só esteja acessível dentro do seu próprio package (package é um grupo de classes, como veremos mais adiante) – para este nível de proteção não é usado um modificador explícito. A Linguagem Java 40 Algoritmos e Estrutura de Dados Modificadores de acesso ao membro Existem modificadores de acesso que se destinam a impor um determinado nível de proteção a um membro (atributo ou método): public – torna o membro acessível a toda e qualquer classe; protected – torna o membro apenas acessível a classes do seu próprio package e, adicionalmente, a subclasses da classe em questão, ainda que se encontrem noutros packages; private – torna o membro apenas acessível dentro da própria classe. Por omissão o membro fica com a proteção conhecida como package- private, o que leva a que só esteja acessível a classes do mesmo package – para este nível de proteção não é usado um modificador explícito. Note-se que, em Java, o modificador (public, private e protected) é indicado membro a membro, e não por zonas, como acontecia em C++. A Linguagem Java 41 Algoritmos e Estrutura de Dados Outros modificadores O modificador static Quando um atributo ou método é declarado como estático, esse membro fica associado à classe, em vez de surgir associado a cada um dos objetos que venham a ser criados dessa classe. O modificador abstract Um método declarado como abstrato, é um método que não tem implementação (não tem corpo), sendo apenas fornecida a sua assinatura (cabeçalho) – corresponde à função virtual pura em C++; A ideia é impor que esse método seja implementado nas subclasses; Uma classe com um ou mais destes métodos (classe incompleta) tem também ela que ser declarada como abstrata (classe não instanciável). O modificador final Quando uma variável é declarada com o modificador final, à mesma só lhe pode ser atribuído um valor no momento da sua declaração (inicialização); Não lhe serão permitidas futuras atribuições (alterações do seu valor); Com o modificador final a variável converte-se, portanto, numa constante. Tratando-se de um atributo, tipicamente ele também será estático. Se for uma classe ou método a ser declarado como final, então o efeito é outro, apenas relevante em contexto de herança: a classe final não pode ter subclasses; o método final não pode ser redefinido nas subclasses. A Linguagem Java 42 Algoritmos e Estrutura de Dados Boas práticas a adotar na criação de classes Declarar os atributos como privados, de forma a não violar um dos princípios basilares do encapsulamento – proteção do estado do objeto; Evitar escrever métodos que leiam ou escrevam valores diretamente na consola, de modo a garantir a completa separação entre a classe e os dispositivos de I/O Caso contrário, a classe fica dependente desses dispositivos (por exemplo, não poderá ser usada mais tarde numa aplicação gráfica); Por norma, criar pelo menos dois construtores: Construtor por omissão (sem parâmetros) – o compilador fornece este construtor, sempre que não se definam quaisquer outros construtores; Construtor inicializador (com um parâmetro por cada atributo) – construtor que permite facilmente inicializar os atributos do objeto, com os valores que lhe sejam passados através dos seus parâmetros; Sempre que necessário para manter o encapsulamento do estado do objeto, incluir getters e setters; Implementar adequadamente os métodos equals(), toString() e clone(); Documentar bem a classe, nomeadamente os seus métodos, usando comentários elucidativos e esclarecedores. A Linguagem Java 43 Algoritmos e Estrutura de Dados Operadores Os operadores em Java são praticamente coincidentes com os operadores do C/C++. O resultado dos operadores aritméticos é do tipo dos operandos Os operadores incremento ++ e decremento -- continuam a poder ser usados quer como prefixo quer como sufixo do operando O resultado dos operadores relacionais é, como se sabe, um valor booleano A Linguagem Java 44 Algoritmos e Estrutura de Dados Operador igualdade com tipos referência Como já vimos anteriormente, quando os operandos são tipos referência, convém não esquecer que os operadores == e != comparam as referências contidas nas variáveis, não as instâncias referenciadas De modo que, a expressão a == b só é true se a e b referenciarem ambas o mesmo objeto. É por essa razão, que os objetos, por norma, incluem o método equals() que permite comparar o próprio objeto com um outro, que é o que normalmente se pretende Dessa forma, a expressão a.equals(b) é true se a e b referenciarem dois objetos considerados iguais. A Linguagem Java 45 Algoritmos e Estrutura de Dados Operadores (continuação) Os operadores lógicos permitem combinar e negar condições Nos operadores && e || a 2ª condição não é avaliada se o resultado poder ser determinado apenas com base na 1ª condição Operadores bit-a-bit A Linguagem Java 46 Algoritmos e Estrutura de Dados Operadores de acesso aos membros de uma classe/objeto Também já sabemos que em Java dispomos de um único operador, o operador ‘.’, para aceder a um membro de uma classe/objeto Como sabe, em C++ dispúnhamos de três: ‘::’, ‘->’ e ‘.’ A Linguagem Java 47 Algoritmos e Estrutura de Dados Precedência dos operadores A Linguagem Java 48 Algoritmos e Estrutura de Dados Conversão de tipos de valor A conversão explícita, com recurso ao operador casting (tipo) expressão apenas pode ser usada para converter um tipo primitivo para outro, ou para converter um tipo referência para outro. e neste segundo caso, a conversão só é permitida entre classes e subclasses Na conversão implícita, um erro de compilação é reportado sempre que se tente converter um valor para um tipo mais restritivo A Linguagem Java 49 Algoritmos e Estrutura de Dados Instruções de controlo As instruções de controlo do Java são essencialmente as mesmas de que dispomos no C/C++ if, if-else, switch while, do-while, for(;;), for-each A nova estrutura for-each fornece-nos uma forma simplificada de iterar uma coleção ou array. for (TipoElemento nome: coleção) blocoInstruções; A Linguagem Java 50 Algoritmos e Estrutura de Dados Entrada e saída de dados pela consola Usam-se os objetos definidos na classe System: System.out – standard ouput stream System.in – standard input stream System.err - standard error stream E recorre-se à classe java.util.Scanner para que as operações de leitura da entrada standard se possam fazer de uma forma mais cómoda. A Linguagem Java 51 Algoritmos e Estrutura de Dados Operações básicas de escrita na consola O objeto System.out assegura as operações de escrita na consola por intermédio dos métodos print() e println(). A Linguagem Java 52 Algoritmos e Estrutura de Dados Operações básicas de leitura a partir da consola O objeto System.in assegura as operações de leitura. Mas, de modo a dispormos de uma forma simples de afetuar as operações de leitura, devemos criar um outro objeto, da classe Scanner, a partir do objeto System.in: new Scanner(System.in) mas se objetivo fosse, por exemplo, ler de um ficheiro, o objeto da classe Scanner já seria criado a partir dum objeto da classe java.io.File A Linguagem Java 53 Algoritmos e Estrutura de Dados Métodos úteis da classe Scanner A classe Scanner, ao ler a stream de entrada, e usando como separador os caracteres ‘brancos’, divide-a em pequenos segmentos (tokens), que se traduzirão em pequenas cadeias de caracteres (strings). A Linguagem Java 54 Algoritmos e Estrutura de Dados Programa exemplo [1/3] A Linguagem Java 55 Algoritmos e Estrutura de Dados Programa exemplo [2/3] Como é estático, não mostra os dados do cartão atual, mas A Linguagem sim do cartão ‘card’ Java como parâmetro que entra 56 Algoritmos e Estrutura de Dados Programa exemplo [3/3] A Linguagem Java 57 Algoritmos e Estrutura de Dados Construtores e destrutores Como se pode verificar no exemplo (linha 17 da classe CreditCard), em Java é possível invocar um construtor a partir do corpo de um outro construtor da mesma classe, usando this(…); Dentro de um qualquer método, o palavra reservada this referencia o objeto atual (objeto sobre o qual o método foi invocado). Por sua vez, o construtor da classe base pode ser invocado, como veremos mais adiante, usando super(…). Quando numa classe não é definido qualquer construtor, o compilador Java encarrega-se de gerar automaticamente o construtor por defeito – aquele que não tem parâmetros. Mas logo que seja definido explicitamente um qualquer construtor, o construtor por defeito deixa de ser gerado de forma automática; Terá que ser o utilizador a defini-lo, se o quiser. Destrutores Normalmente são desnecessários em Java, devido à desalocação automática da memória; Mas, se a classe usar um recurso externo (por exemplo, um ficheiro), pode mesmo ser necessário o destrutor, para libertar esse recurso; Em Java, o destrutor designa-se finalize(). A Linguagem Java 58 Algoritmos e Estrutura de Dados Packages Como já dissemos, cada classe Java deve ser definida num ficheiro separado. Devemos, no entanto, notar que um ficheiro até pode conter várias classes, desde que só uma delas seja de acesso público. Para uma melhor organização do código, o Java permite que classes relacionadas entre si sejam agrupadas numa entidade conhecida por package. Um package pode ser visto como um agrupamento de tipos relacionados (classes, interfaces, enumerações e anotações), fornecendo um novo nível de proteção de acesso e criando um espaço de nomes independente. Se pretendermos que determinada classe faça parte de um package chamado packageName, então devemos colocar o ficheiro que a contem num subdiretório chamado packageName e esse ficheiro deve começar com a declaração: package packageName; As classes definidas dentro de ficheiros que não contenham uma declaração explicita do package a que pertençam, são colocadas no default package. A Linguagem Java 59 Algoritmos e Estrutura de Dados Packages (continuação) Para usarmos uma classe X que pertença a um package concreto, devemos usar a qualificação completa do nome: packageName.X Os packages podem ser organizados em subpackages Por exemplo, existe o subpackage zip dentro do package java.util, e a classe Deflater, pertencente a esse subpackage, é identificada por java.util.zip.Deflater. Vantagens dos packages Reduz a ocorrência de conflitos de nomes; Facilita a distribuição de conjuntos de classes a outros programadores; Facilita a compreensão do significado das classes, uma vez que permite que elas estejam agrupadas de acordo com a função que desempenham; Fornecem-nos um nível de proteção adicional, ao possibilitarem que definamos classes, ou membros das mesmas, apenas acessíveis a partir de classes do mesmo package (proteção package-private, sempre que não se explicíta qualquer modificador). A Linguagem Java 60 Algoritmos e Estrutura de Dados O comando import Devido ao uso de packages, pode se tornar fastidioso termos que usar a qualificação completa do nome de uma classe sempre que a pretendamos usar Por exemplo, para instanciarmos a classe Scanner, temos que escrever: java.util.Scanner input = new java.util.Scanner(System.in); Felizmente, com o comando import conseguimos incluir no ficheiro corrente a classe de um dado package, e com isso passar identificar a classe apenas pelo seu nome No exemplo anterior, se começássemos o ficheiro com import java.util.Scanner, bastaria depois fazermos: Scanner input = new Scanner(System.in); A Linguagem Java 61 Algoritmos e Estrutura de Dados O comando import – importando todo o package Se percebermos que vamos usar várias classes de um mesmo package, temos a possibilidade de incluir todo o package, usando o wildcard * (carater de substituição) import packageName.*; No entanto, é recomendável que se importe individualmente cada classe de que se necessite, em vez de se importar todo o package Facilita a clareza do código (se se usam poucas classes do package, esse facto fica mais evidenciado com importações individuais); Diminui a possibilidade de colisões (caso existam classes com o mesmo nome em dois ou mais packages importados). A Linguagem Java 62 Algoritmos e Estrutura de Dados O comando import – estático A importação estática permite-nos importar membros estáticos de uma dada classe import static packageName.className.staticMemberName; Dessa forma, passa a ser possível usar diretamente esse membro estático (portanto, sem usar o nome da classe como qualificador) Exemplo sem importação estática public class Test { public static void main(String[] args) { System.out.println(Math.sqrt(2)); } } O mesmo exemplo, mas com importação estática import static java.lang.Math.sqrt; public class Test { public static void main(String[] args) { System.out.println(sqrt(2)); } } Repare-se que o subpackage java.lang já é importado automaticamente pelo Java. A Linguagem Java 63 Algoritmos e Estrutura de Dados Regras de criação de ficheiros fonte Apenas pode existir uma classe pública por ficheiro. Um mesmo ficheiro pode conter múltiplas classes não publicas. O ficheiro deve ter o nome da classe pública e terminar com a extensão.java. Se a classe for definida dentro de um package, então a instrução package deve aparecer logo no inicio do ficheiro. Se estiverem presentes instruções import, estas devem surgir entre a instrução package e a declaração da classe. As instruções import e package que existirem terão efeito sobre todas as classes presentes no ficheiro. O NetBeans, tal como a maioria dos IDEs, encarrega-se de parte destas regras A Linguagem Java 64 Algoritmos e Estrutura de Dados Uso de packages numa aplicação Java do NetBeans A Linguagem Java 65 Algoritmos e Estrutura de Dados Definir nome e localização do projeto A Linguagem Java 66 Algoritmos e Estrutura de Dados Configuração inicial do projeto A Linguagem Java 67 Algoritmos e Estrutura de Dados Definição da função main A Linguagem Java 68 Algoritmos e Estrutura de Dados Adição da classe Counter num novo package ‘util’ A Linguagem Java 69 Algoritmos e Estrutura de Dados Edição do código da classe Counter Apenas temos que escrever os membros da classe (linhas 13 a 19) A Linguagem Java 70 Algoritmos e Estrutura de Dados Uso da classe Counter A Linguagem Java 71 Algoritmos e Estrutura de Dados