Dia 4
Trabalho com objetos
Laura Lemay
CONTEÚDOS
Vamos começar a lição de hoje com uma afirmação óbvia: Como Java é uma língua orientada ao objeto, vai estar tratando com muitos objetos. Os criará, os modificará, os deslocará, modificará as suas variáveis, chamar os seus métodos, combiná-los com outros objetos - e, naturalmente, desenvolver classes e usar os seus próprios objetos na mistura.
Hoje, por isso, aprenderá todos sobre o objeto de Java no seu hábitat natural. Os tópicos de hoje incluem
- Criar exemplos de classes
- Testar e modificar classe e variáveis de exemplo no seu novo exemplo
- Chamar métodos naquele objeto
- O arremesso (de conversão) objeta e outros tipos de dados de uma classe ao outro
- Outro desacordo e fins sobre trabalho com objetos
- Um resumo das bibliotecas de classe de Java
Quando escreve um programa Java, define o grupo de classes. Como aprendeu no Dia 2, "A Programação orientada ao Objeto e Java", as classes são padrões de objetos; em sua maioria, simplesmente usa a classe para criar exemplos e logo trabalhar com aqueles exemplos. Nesta seção, por isso, aprenderá como criar um novo objeto de qualquer classe dada.
Lembrar-se de cadeias de ontem? Aprendeu que usando uma cadeia a série literal-a de carateres cercados em "citações duplas cria" um novo exemplo da classe String com o valor daquela cadeia.
A classe de String é excepcional naquele respeito - embora seja uma classe, há um modo fácil de criar exemplos daquela classe usando um literal. Outras classes não têm aquele atalho; para criar exemplos daquelas classes tem de fazer tão explicitamente usando o operador new.
Observar |
Que tal os literais de números e carateres? Não criam objetos, também? De fato, não fazem. Os tipos de dados primitivos de números e carateres criam números e carateres, mas da eficiência, não são de fato objetos. Pode pôr empacotadores de objeto em volta deles se tiver de tratá-los como objetos (aprenderá como fazer isto em "Arremesso e 'Conversão de Objetos e Tipos Primitivos").
|
Para criar um novo objeto, usa o operador new com o nome da classe quer criar um exemplo de, logo parênteses depois disto. Os seguintes exemplos criam novos exemplos das classes String, Random e Motorcycle, e guardam aqueles novos exemplos em variáveis dos tipos apropriados:
String str = new String();
Random r = new Random();
Motorcycle m2 = new Motorcycle();
Os parênteses são importantes; não os deixe. Os parênteses podem ser vazios (como nestes exemplos), em que caso o objeto mais simples, básico se cria; ou os parênteses podem conter argumentos que determinam os valores iniciais de variáveis de exemplo ou outras qualidades iniciais daquele objeto:
Date dt = new Date(90, 4, 1, 4, 30);
Point pt = new Point(0,0);
O número e o tipo de argumentos que pode usar dentro dos parênteses com new definem-se pela própria classe usando um método especial chamado um construtor (aprenderá mais sobre construtores depois hoje). Se tentar e criar um novo exemplo de uma classe com o número incorreto ou o tipo de argumentos (ou se não lhe der nenhum argumento e precisa-se de alguns), então adquirirá um erro quando tenta compilar o seu programa Java.
Aqui está um exemplo de criar vários tipos diferentes de objetos usando números diferentes e tipos de argumentos. A classe de Date, parte do pacote de java.util, cria objetos que representam a data atual. A listagem 4.1 é um programa Java que mostra três modos diferentes de criar um objeto de Date usando new.
A listagem 4.1. O programa Date de Laura.
1: import java.util.Date;
2:
3: class CreateDates {
4:
5: public static void main(String args[]) {
6: Date d1, d2, d3;
7:
8: d1 = new Date();
9: System.out.println("Date 1: " + d1);
10:
11: d2 = new Date(71, 7, 1, 7, 30);
12: System.out.println("Date 2: " + d2);
13:
14: d3 = new Date("April 3 1993 3:24 PM");
15: System.out.println("Date 3: " + d3);
16: }
17: }
Date 1: Tue Feb 13 09:36:56 PST 1996
Date 2: Sun Aug 01 07:30:00 PDT 1971
Date 3: Sat Apr 03 15:24:00 PST 1993
Análise |
Neste exemplo, três objetos de data diferentes criam-se usando argumentos diferentes à classe enumerada depois de new. A primeira instância (linha 8) usa new Date() sem argumentos, que cria um objeto de Date na data de hoje (a primeira linha da produção mostra uma amostra; a sua produção lerá, naturalmente, a data atual e tempo para você).
|
O segundo Date objeta que crie neste exemplo tem cinco argumentos de número inteiro. Os argumentos representam uma data: ano, mês, dia, horas e minutos. E, como a produção mostra, isto cria um objeto de Date naquela determinada data: o domingo, primeiro de agosto de 1971, às 7h30.
Observar |
Meses de números de Java que começam de 0. Assim, embora pudesse esperar que o sétimo mês fosse julho, o mês 7 em Java de fato é agosto.
|
A terceira versão de Date toma um argumento, uma cadeia, representando a data como uma cadeia de texto. Quando o objeto de Date se cria, aquela cadeia analisa-se, e um objeto de Date com aquela data e tempo cria-se (ver a terceira linha da produção). A cadeia de data pode tomar muitos formatos diferentes; ver a documentação API da classe de Date (parte do pacote de java.util) para a informação sobre que cadeias pode usar.
Quando usa o operador new, o novo exemplo da classe dada cria-se, e a memória aloca-se para ele. Além disso (e o mais importantemente), chama-se um método especial definido na classe dada para inicializar o objeto e fundar qualquer valor inicial do qual precisa. Este método especial chama-se um construtor. Os construtores são métodos especiais, definidos em classes, que criam e inicializam novos exemplos de classes.
Novo termo
|
Os construtores são métodos especiais que inicializam um novo objeto, estabelecem as suas variáveis, criam qualquer outro objeto que objeta necessidades, e geralmente executa qualquer outra operação que o objeto tem de inicializar ele mesmo.
|
Múltiplas definições de construtor em uma classe podem ter cada um um número diferente ou o tipo de argumentos então, quando usa new, pode especificar argumentos diferentes na lista de parâmetros, e chamarão o construtor direito daqueles argumentos. Isto é como cada uma daquelas versões diferentes de new que usou na classe de CreateDates pode criar objetos de Date diferentes.
Quando cria as suas próprias classes, pode definir tantos construtores como tem de implementar o comportamento daquela classe. Aprenderá como criar construtores no Dia 7, "mais sobre Métodos".
A gestão de memória em Java é dinâmica e automática. Quando cria um novo objeto em Java, Java automaticamente aloca o montante direito da memória daquele objeto no montão. Não tem de alocar nenhuma memória de nenhum objeto explicitamente; Java fá-lo para você.
O que acontece quando se termina com aquele objeto? Como anula a memória aquele objeto usos? A resposta, novamente, é que a gestão de memória é automática. Uma vez que se faz com um objeto, redestina todas as variáveis que poderiam considerar que o objeto e o retira de qualquer tabela, por meio disso fazendo o objeto inútil. Java tem um "coletor de lixo" que procura objetos não usados e reforma a memória que aqueles objetos usam. Não tem de fazer nenhuma libertação explícita da memória; somente tem de assegurar-se que ainda não se mantém para um objeto do qual quer livrar-se. Aprenderá detalhes mais específicos sobre o coletor de lixo de Java e como trabalha no Dia 21, "Abaixo do Capuz".
Novo termo |
Um coletor de lixo é uma coisa especial incorporada no ambiente de Java que procura objetos não usados. Se encontrar algum, automaticamente retira aqueles objetos e liberta a memória que aqueles objetos usavam.
|
Agora tem o seu objeto muito próprio, e aquele objeto pode ter classe ou variáveis de exemplo definidas nele. Como trabalha com aquelas variáveis? Fácil! A classe e as variáveis de exemplo comportam-se de exatamente os mesmos modos que as variáveis locais sobre as quais aprendeu ontem; somente refere-se a eles ligeiramente diferentemente do que faz variáveis regulares no seu código.
Para vir ao valor de uma variável de exemplo, usa uma expressão no que chamou a notação de ponto. Com a notação de ponto, a referência para um exemplo ou variável de classe tem duas partes: o objeto no lado abandonado do ponto e a variável no lado direito do ponto.
Novo termo |
A notação de ponto é uma expressão usada para alcançar variáveis de exemplo e métodos dentro de um objeto dado.
|
Por exemplo, se manda destinar um objeto ao myObject variável, e aquele objeto tem uma variável chamada var, refere-se ao valor daquela variável como isto:
myObject.var;
Esta forma para acessar variáveis é uma expressão (devolve um valor), e ambos os lados do ponto também podem ser expressões. Isto significa que pode aninhar o acesso a variável de exemplo. Se que a própria variável de exemplo de var mantém um objeto e aquele objeto têm a sua própria variável de exemplo chamada state, pode referir-se a ele como isto:
myObject.var.state;
As expressões de ponto avaliam-se da esquerda à direita, portanto começa com var variável de myObject, que aponta para outro objeto com o state variável. Termina com o valor de que a variável de state depois da expressão inteira se faz avaliando.
Destinar um valor àquela variável é igualmente fácil - somente pregam um operador de nomeação no lado direito da expressão:
myObject.var.state = true;
A listagem 4.2 é um exemplo de um programa que testa e modifica as variáveis de exemplo em um objeto de Point. Point é parte do pacote de java.awt e refere-se a um ponto coordenado com um x e um valor de y.
A listagem 4.2. A classe de TestPoint.
1: import java.awt.Point;
2:
3: class TestPoint {
4: public static void main(String args[]) {
5: Point thePoint = new Point(10,10);
6:
7: System.out.println("X is " + thePoint.x);
8: System.out.println("Y is " + thePoint.y);
9:
10: System.out.println("Setting X to 5.");
11: thePoint.x = 5;
12: System.out.println("Setting Y to 15.");
13: thePoint.y = 15;
14:
15: System.out.println("X is " + thePoint.x);
16: System.out.println("Y is " + thePoint.y);
17:
18: }
19:}
X is 10
Y is 10
Setting X to 5.
Setting Y to 15.
X is 5
Y is 15
Análise |
Neste exemplo, primeiro cria um exemplo de Point onde X e Y são ambos 10 (linha 6). As linhas 8 e 9 imprimem aqueles valores individuais, e pode ver a notação de ponto no trabalho lá. As linhas 11 para 14 modificam os valores daquelas variáveis a 5 e 15, respectivamente. Finalmente, as linhas 16 e 17 imprimem os valores de X e Y novamente para mostrar como se modificaram.
|
As variáveis de classe, como já aprendeu, são variáveis que se definem e se guardam na própria classe. Os seus valores, por isso, aplicam à classe e a todos os seus exemplos.
Com variáveis de exemplo, cada novo exemplo da classe adquire uma nova cópia das variáveis de exemplo que a classe define. Cada exemplo então pode modificar os valores daquelas variáveis de exemplo sem afetar qualquer outro exemplo. Com variáveis de classe, há só uma cópia daquela variável. Cada exemplo da classe tem o acesso àquela variável, mas há só um valor. Modificar o valor daquela variável modifica-o para todos os exemplos daquela classe.
Define variáveis de classe pela inclusão da palavra-chave de static antes da própria variável. Aprenderá mais sobre isto no Dia 6, "Criando Classes e Aplicações em Java". Por exemplo, tome a seguinte definição de classe parcial:
class FamilyMember {
static String surname = "Johnson";
String name;
int age;
...
}
Os exemplos da classe FamilyMember cada um tem os seus próprios valores de nome e idade. Mas a variável de classe surname tem só um valor de todos os membros da família. Modifique surname, e todos os exemplos de FamilyMember afetam-se.
A variáveis de classe de acesso, usa a mesma notação de ponto que faz com variáveis de exemplo. Para adquirir ou modificar o valor da variável de classe, pode usar o exemplo ou o nome da classe no lado abandonado do ponto. Ambas das linhas da produção neste exemplo imprimem o mesmo valor:
FamilyMember dad = new FamilyMember();
System.out.println("Family's surname is: " + dad.surname);
System.out.println("Family's surname is: " + FamilyMember.surname);
Como pode usar um exemplo para modificar o valor de uma variável de classe, é fácil ficar confundido sobre variáveis de classe e onde os seus valores vêm de (lembre-se de que o valor de uma variável de classe afeta todos os exemplos). Por essa razão, é uma boa ideia de usar o nome da classe quando se refere a uma variável de classe - faz o seu código mais fácil ler e resultados estranhos mais fáceis depurar.
A chamada de um método é semelhante à referência a variáveis de exemplo de um objeto: o Método chama a objetos também usam a notação de ponto. O próprio objeto cujo método chama está no lado abandonado do ponto; o nome do método e os seus argumentos está no lado direito do ponto:
myObject.methodOne(arg1, arg2, arg3);
Observe que todas as chamadas a métodos devem ter parênteses depois deles, mesmo se aquele método não tomar nenhum argumento:
myObject.methodNoArgs();
Se o método chamou regressos um objeto que ele mesmo tem métodos, pode aninhar métodos como ia variáveis. Este seguinte exemplo chama o método de getName(), que se define no objeto devolvido pelo método de getClass(), que se definiu em myObject. Adquiriu-o?
myObject.getClass().getName();
Pode combinar chamadas de método aninhadas e referências a variável de exemplo também (neste caso chama o methodTwo () método, que se define no objeto guardado pela variável de exemplo de var, que à sua vez é parte do objeto de myObject):
myObject.var.methodTwo(arg1, arg2);
System.out.println(), o método tem usado pelo livro isto longe para imprimir bits do texto, é um grande exemplo de variáveis de aninhamento e métodos. A classe de System (parte do pacote de java.lang) descreve o comportamento específico para o sistema. System.out é uma variável de classe que contém um exemplo da classe PrintStream que aponta para a produção padrão do sistema. os exemplos de PrintStream têm um método de println() que imprime uma cadeia para aquela corrente de produção.
A listagem 4.3 mostra um exemplo de chamar alguns métodos definidos na classe de String. As cadeias incluem métodos de testes de cadeia e modificação, semelhante ao que esperaria em uma biblioteca de cadeia em outras línguas.
A listagem 4.3. Vários usos de métodos de String.
1: class TestString {
2:
3: public static void main(String args[]) {
4: String str = "Now is the winter of our discontent";
5:
6: System.out.println("The string is: " + str);
7: System.out.println("Length of this string: "
8: + str.length());
9: System.out.println("The character at position 5: "
10: + str.charAt(5));
11: System.out.println("The substring from 11 to 17: "
12: + str.substring(11, 17));
13: System.out.println("The index of the character d: "
14: + str.indexOf('d'));
15: System.out.print("The index of the beginning of the ");
16: System.out.println("substring \"winter\": "
17: + str.indexOf("winter"));
18: System.out.println("The string in upper case: "
19: + str.toUpperCase());
20: }
21: }
The string is: Now is the winter of our discontent
Length of this string: 35
The character at position 5: s
The substring from positions 11 to 17: winter
The index of the character d: 25
The index of the beginning of the substring "winter": 11
The string in upper case: NOW IS THE WINTER OF OUR DISCONTENT
Análise |
Na linha 4, cria um novo exemplo de String usando uma cadeia literal (é mais fácil que caminho do que utilização de new e logo colocação dos carateres em individualmente). O resto do programa simplesmente chama métodos de cadeia diferentes para fazer operações diferentes naquela cadeia:
|
- Linha 6 impressões o valor da cadeia criamos na linha 4: "Now is the winter of our discontent".
- Linha 7 chamadas o método de length() no novo objeto de String. Esta cadeia tem 35 carateres.
- A linha 9 chamadas o método de charAt(), que devolve o caráter na posição dada na cadeia. Observe que a partida de posições de cadeia em 0, portanto o caráter na posição 5 é s.
- A linha 11 chamadas o método de substring(), que toma dois números inteiros que indicam uma variedade e devolve a subcadeia nos que começam e e terminam pontos. O método de substring() também pode chamar-se com só um argumento, que devolve a subcadeia daquela posição ao fim da cadeia.
- A linha 13 chamadas o método de indexOf(), que devolve a posição da primeira instância do caráter dado (aqui, 'd').
- A linha 15 demonstrações um uso diferente do método de indexOf(), que toma um argumento de cadeia e devolve o índice do começo daquela cadeia.
- Finalmente, linha 19 usos o método de toUpperCase() para devolver uma cópia da cadeia em toda a letra maiúscula.
Os métodos de classe, como variáveis de classe, aplicam à classe no conjunto e não aos seus exemplos. Os métodos de classe usam-se comumente para métodos de serviço gerais que podem não produzir diretamente um exemplo daquela classe, mas ajustar-se com aquela classe conceptualmente. Por exemplo, a classe de String contém um método de classe chamado valueOf(), que pode tomar um de muitos tipos diferentes de argumentos (números inteiros, booleans, outros objetos, e assim por diante). O método de valueOf() então devolve um novo exemplo de String que contém o valor de cadeia do argumento que se deu. Este método não produz diretamente um exemplo existente de String, mas a obtenção de uma cadeia de outro objeto ou tipo de dados é definitivamente um String - como operação, e faz sentido para defini-lo na classe de String.
Os métodos de classe também podem ser úteis para reunir métodos gerais em conjunto em um lugar (a classe). Por exemplo, a classe de Math, definida no pacote de java.lang, contém um grande jogo de operações matemáticas como os métodos lá de classe não são nenhum exemplo da classe Math, mas ainda pode usar os seus métodos com argumentos numéricos ou booleanos. Por exemplo, o método de classe Math.max() toma dois argumentos e devolve os maiores dos dois. Não precisa de criar um novo exemplo de Math; somente chame o método em qualquer lugar precisa dele, como isto:
in biggerOne = Math.max(x, y);
Para chamar um método de classe, usa a notação de ponto como faz com métodos de exemplo. Como com variáveis de classe, pode usar um exemplo da classe ou a própria classe no sítio esquerdo do ponto. Contudo, pelas mesmas razões observadas na discussão sobre variáveis de classe, usando o nome da classe de métodos de classe faz o seu código mais fácil ler. Duas linhas últimas neste exemplo produzem o mesmo resultado (a cadeia "5"):
String s, s2;
s = "foo";
s2 = s.valueOf(5);
s2 = String.valueOf(5);
Como trabalha com objetos, uma coisa importante que continua nos bastidores é o uso de referências para aqueles objetos. Quando destina objetos a variáveis ou objetos de passo como argumentos a métodos, passa referências para aqueles objetos, não os próprios objetos ou as cópias daqueles objetos.
Um exemplo deve fazer isto mais claro. Examine a Listagem 4.4, que mostra um exemplo simples de como trabalham as referências.
A listagem 4.4. Um exemplo de referências.
1: import java.awt.Point;
2:
3: class ReferencesTest {
4: public static void main (String args[]) {
5: Point pt1, pt2;
6: pt1 = new Point(100, 100);
7: pt2 = pt1;
8:
9: pt1.x = 200;
10: pt1.y = 200;
11: System.out.println("Point1: " + pt1.x + ", " + pt1.y);
12: System.out.println("Point2: " + pt2.x + ", " + pt2.y);
13: }
14: }
Point1: 200, 200
Point2: 200, 200
Análise |
Na primeira parte deste programa, declara duas variáveis do tipo Point (linha 5), cria um novo Point objetam a pt1 (linha 6), e finalmente, destinam o valor de pt1 a pt2 (linha 7).
|
Agora, aqui está o desafio. Depois de modificar x de pt1 e variáveis de exemplo de y em linhas 9 e 10, a que pt2 parecerá?
Como pode ver, x de pt2 e as variáveis de exemplo y também se modificaram, embora nunca explicitamente os modificasse. Quando destina o valor de pt1 a pt2, de fato cria uma referência de pt2 ao mesmo objeto ao qual pt1 se refere (ver a Figura 4.1). Modifique o objeto a que pt2 se refere, e também modifica o objeto para que pt1 aponta, porque ambos são referências para o mesmo objeto.
A figura 4.1: Referências para objetos.
Observar |
Se de fato quiser que pt1 e pt2 apontem para separar objetos, deve usar novo Point() para ambas as linhas para criar objetos separados.
|
O fato que Java usa referências fica especialmente importante quando passa argumentos a métodos. Aprenderá mais sobre isto depois hoje, mas vai se lembrar destas referências.
Nota técnica |
Não há ponteiros explícitos ou a aritmética de ponteiro em Java como há em línguas parecidas a C - somente referências. Contudo, com estas referências, e com tabelas de Java, tem a maioria das capacidades que tem com ponteiros sem a confusão e defeitos espreitam que os ponteiros explícitos podem criar.
|
Às vezes nos seus programas Java pode mandar guardar um valor em algum lugar que é o tipo incorreto para o que quer fazer com ele. Talvez é um exemplo da classe incorreta, ou possivelmente é um float e quer que ele seja um int. Para converter o valor de um tipo ao outro, usa o arremesso. O arremesso é um termo de programação que significa, efetivamente, convertendo um valor ou um objeto de um tipo ao outro. O resultado de uma forma é um novo valor ou objeto; o arremesso não modifica o objeto original ou valor.
Novo tempo |
Conversos lançam o valor de um objeto ou tipo primitivo em outro tipo.
|
Embora o conceito do arremesso seja um simples, as regras para que tipos em Java podem converter-se no que outros tipos se complicam pelo fato que Java tem ambos os tipos primitivos (int, float, boolean), e tipos de objeto (String, Point, Window, e assim por diante). Há três formas de formas e conversões para falar sobre nesta seção:
- Lançar entre tipos primitivos: int a float ou float a double
- Arremesso entre tipos de objeto: um exemplo de uma classe a um exemplo de outra classe
- Converter tipos primitivos a objetos e logo extrair valores primitivos atrás fora daqueles objetos
Lançar entre tipos primitivos permite-lhe "converter" o valor de um tipo a outro tipo por exemplo primitivo, destinar um número de um tipo a uma variável de outro tipo. Lançar entre tipos primitivos o mais comumente ocorre com os tipos numéricos; os valores booleanos não podem lançar-se a nenhum outro tipo primitivo.
Muitas vezes, se o tipo ao qual lança é "maior" do que o tipo do valor converte, não deveria usar uma forma explícita. Muitas vezes pode tratar automaticamente um byte ou um caráter como um int, por exemplo, ou int como um long, um int como um float ou algo como um double automaticamente. Na maioria dos casos, porque o tipo maior fornece mais precisão do que o mais pequeno, nenhuma perda da informação ocorre quando o valor se lança. A exceção lança números inteiros a valores de ponto flutuante; lançar um int ou um long a um float ou um long a um double pode causar alguma perda da precisão.
Para converter um grande valor no mais pequeno tipo, deve usar uma forma explícita, porque a conversão daquele valor pode resultar em uma perda da precisão. As formas explícitas parecem a isto:
(typename)value
Nesta forma, typename é o nome do tipo no qual converte (por exemplo: short, int, float, boolean), e value é uma expressão que resulta no valor que quer converter. Deste modo, por exemplo, nesta expressão o valor de x divide-se pelo valor de y e o resultado lança-se a um int:
(int) (x / y);
Observe que porque a precedência do arremesso é mais alta do que aquela da aritmética, tem de usar parênteses aqui; de outra maneira, o valor de x iria se lançar primeiro e logo iria se dividir por y (que poderia muito ser bem um resultado muito diferente).
Os exemplos de classes também podem lançar-se a exemplos de outras classes, com uma restrição: A classe do objeto que lança e a classe à qual o lança deve relacionar-se pela herança; isto é, pode lançar um objeto só a um exemplo da sua classe sub - ou superclasse - não a qualquer classe casual.
Análogo à conversão de um valor primitivo a um tipo maior, alguns objetos precisariam não de lançar-se explicitamente. Especialmente, porque as subclasses contêm mesmo assim a informação como a sua superclasse, pode usar um exemplo de uma subclasse em qualquer lugar espera-se uma superclasse. (Somente teve de ler aquela oração quatro vezes antes que o entendesse? Tive de reescrevê-lo um lote inteiro de tempos antes que ficasse até tão simples. Tenha paciência comigo, o seu não tão mal. Vamos tentar um exemplo.) Supõem que tem um método que toma dois argumentos: um de tipo Object e um de tipo Number. Não tem de passar exemplos daquelas determinadas classes àquele método. Para o argumento de Object, pode passar qualquer subclasse de Object (qualquer objeto, em outras palavras), e para o argumento de Number pode passar em qualquer exemplo de qualquer subclasse de Number (Integer, Boolean, Float, e assim por diante); não tem de convertê-los explicitamente primeiro.
Lançar para baixo na hierarquia de classe é automático, mas o arremesso para cima não é. Converter um exemplo de uma subclasse a um exemplo de uma superclasse perde a informação a subclasse original fornecida e necessita uma forma explícita. Para lançar um objeto a outra classe, usa a mesma operação de arremesso que usou para tipos baseados:
(classname)object
Neste caso, classname é o nome da classe à qual quer lançar o objeto, e object é uma referência para o objeto que lança. Observe que o arremesso cria uma referência para o velho objeto do tipo classname; o velho objeto ainda continua existindo como fez antes.
Aqui está um (fictício) exemplo de uma forma de um exemplo da classe GreenApple a um exemplo da classe Apple (onde GreenApple é teoricamente uma subclasse de Apple com mais informação para definir a maçã como verde):
GreenApple a;
Apple a2;
a = new GreenApple();
a2 = (Apple) a;
Além do arremesso de objetos a classes, também pode lançar objetos a interfaces - mas só se a classe daquele objeto ou uma das suas superclasses de fato implementam aquela interface. Lançar um objeto a uma interface significa que pode chamar um de métodos daquela interface mesmo se a classe daquele objeto não implementar de fato aquela interface. Aprenderá mais sobre interfaces na Semana 3.
Agora sabe como lançar um tipo primitivo a outro tipo primitivo e como lançar entre classes. Como pode lançar aquele ao outro?
Não pode! Os tipos primitivos e os objetos são coisas muito diferentes em Java e não pode lançar automaticamente ou converter entre os dois. Contudo, o pacote de java.lang inclui várias classes especiais que correspondem a cada tipo de dados primitivo: Integer de int s, Float de float s, Boolean de boolean s, e assim por diante. Observe que os nomes de classe têm uma carta de capital inicial, e os tipos primitivos são letra minúscula. Java trata estes nomes muito diferentemente, então não os confunda, ou os seus métodos e as variáveis não se comportarão o modo que espera.
Usar métodos de classe definiu nestas classes, pode criar um equivalente ao objeto de todos os tipos primitivos usando new. A seguinte linha do código cria um exemplo da classe de Integer com o valor 35:
Integer intObject = new Integer(35);
Uma vez que tem objetos reais, pode tratar aqueles valores como objetos. Então, quando quer os valores primitivos atrás novamente, há métodos para aquele também por exemplo, o método de intValue() extrai um int valor primitivo de um objeto de Integer:
int theInt = intObject.intValue(); // returns 35
Ver Java documentação de API destas classes especiais da especificação nos métodos para converter primitivos em e de objetos.
Observar |
Em Java 1.0 há classes de tipo especiais de Boolean, Character, Double, Float, Integer e Long. Java 1.1 acrescenta classes de Byte e Short, bem como uma classe de empacotador especial de Void. As últimas classes usam-se principalmente para a reflexão de objeto.
|
Esta seção é uma caixa de outra informação sobre o trabalho com objetos, em particular o seguinte:
- Comparação de objetos
- Descobrir a classe de qualquer objeto dado
- Testar para ver se um objeto é um exemplo de uma classe dada
Ontem aprendeu sobre operadores para comparar valores: iguala, não iguala, menos do que, e assim por diante. A maioria destes operadores só trabalham em tipos primitivos, não em objetos. Se tentar usar outros valores como operands, o compilador de Java produz erros.
A exceção a esta regra é com os operadores da igualdade: == (igual) e != (não igual). Estes operadores, quando usado com objetos, testam se os dois operands se referem a exatamente o mesmo objeto na memória.
O que deve fazer se quiser ser capaz de comparar exemplos da sua classe e ter resultados significativos? Tem de implementar métodos especiais na sua classe, e tem de chamar aqueles métodos usando aqueles nomes de método.
Nota técnica |
Java não tem o conceito do operador que sobrecarrega - isto é, a capacidade de redefinir o comportamento dos métodos de utilização de operadores construídos nas suas próprias classes. Os operadores construídos permanecem definidos só para números.
|
Um bom exemplo disto é a classe de String. É possível ter duas cadeias, dois objetos independentes na memória com os mesmos valores - isto é, os mesmos carateres na mesma ordem. Segundo o operador ==, contudo, aqueles dois objetos de String não serão iguais, porque, embora os seus conteúdos sejam o mesmo, não são o mesmo objeto.
A classe de String, por isso, define um método chamado equals() que testa cada caráter na cadeia e devolve true se as duas cadeias tiverem os mesmos valores. A listagem 4.5 ilustra isto.
A listagem 4.5. Um teste de igualdade de cadeia.
1: class EqualsTest {
2: public static void main(String args[]) {
3: String str1, str2;
4: str1 = "she sells sea shells by the sea shore.";
5: str2 = str1;
6:
7: System.out.println("String1: " + str1);
8: System.out.println("String2: " + str2);
9: System.out.println("Same object? " + (str1 == str2));
10:
11: str2 = new String(str1);
12:
13: System.out.println("String1: " + str1);
14: System.out.println("String2: " + str2);
15: System.out.println("Same object? " + (str1 == str2));
16: System.out.println("Same value? " + str1.equals(str2));
17: }
18: }
String1: she sells sea shells by the sea shore.
String2: she sells sea shells by the sea shore.
Same object? true
String1: she sells sea shells by the sea shore.
String2: she sells sea shells by the sea shore.
Same object? false
Same value? true
Análise |
A primeira parte deste programa (linhas 4 para 6) declara duas variáveis (str1 e str2) destina o she sells sea shells by the sea shore. literal a str1, e logo destina aquele valor a str2. Como aprendeu antes quando falamos sobre referências a objeto, agora str1 e str2 apontam para o mesmo objeto, e o teste de igualdade na linha 10 comprova isto.
|
Na segunda parte, cria um novo objeto de cadeia com o mesmo valor que str1 e destina str2 àquele novo objeto de cadeia. Agora tem dois objetos de cadeia diferentes em str1 e str2, ambos com o mesmo valor. Testá-los para ver se são o mesmo objeto usando o operador == (linha 16) devolve a resposta esperada (false - não são o mesmo objeto na memória), que faz a prova deles usando o método de equals() (linha 17) (true - têm os mesmos valores).
Nota técnica |
Porque somente não pode usar outro literal quando modifica str2, em vez de usar new? Os literais de cadeia otimizam-se em Java - se criar uma cadeia usando um literal, e logo usar outro literal com os mesmos carateres, Java sabe bastante para dar-lhe o primeiro objeto de String atrás. Ambas as cadeias são os mesmos objetos - para criar dois objetos separados tem de sair do seu caminho.
|
Quer descobrir a classe de um objeto? Aqui está o modo de fazê-lo para um objeto destinado ao obj variável:
String name = obj.getClass().getName();
O que isto faz? O método de getClass() define-se na classe de Object, e como tal está disponível para todos os objetos. O resultado daquele método é um objeto de Class (onde Class é uma classe), que tem um método chamado getName(). getName() devolve uma cadeia que representa o nome da classe.
Outro teste que poderia ser útil para você é o operador instanceof. instanceof tem dois operands: um objeto à esquerda e o nome de uma classe à direita. A expressão devolve true ou false baseado em se o objeto é um exemplo da classe denominada ou alguma de subclasses daquela classe:
"foo" instanceof String // true
Point pt = new Point(10, 10);
pt instanceof String // false
O operador instanceof também pode usar-se para interfaces; se um objeto implementar uma interface, o operador instanceof com aquele nome de interface no lado direito devolve true. Aprenderá todos sobre interfaces na Semana 3.
A reflexão, também conhecida como introspeção, é um termo um tanto alto para descrever a capacidade de "olhar dentro de" uma classe ou um objeto e adquirir a informação sobre variáveis daquele objeto e métodos bem como de fato estabelecer e adquirir os valores daquelas variáveis e chamar métodos. A reflexão de objeto é útil para instrumentos como browseres de classe ou depuradores, onde alcançar a informação de um objeto durante o voo lhe permite explorar o que aquele objeto pode fazer, ou para programas baseados no componente como Feijões de Java, onde a capacidade de um objeto de questionar outro objeto sobre o que pode fazer (e logo pedir que ele faça algo) é útil para a criação de aplicações maiores.
As classes que apoiam a reflexão de classes de Java e objetos serão parte de Java principal 1.1 API (não estão disponíveis na 1.0.2 versão do JDK). Um novo pacote, java.lang.reflect, conterá novas classes para apoiar a reflexão, que incluem o seguinte:
- Field, para arranjar-se e descobrir a informação sobre classe e variáveis de exemplo
- Method, para classe gerente e métodos de exemplo
- Constructor, para dirigir os métodos especiais para criar novos exemplos de classes (aprenderá mais sobre construtores no Dia 7)
- Array, para dirigir tabelas
- Modifier, para decifrar a informação sobre modificador sobre classes, variáveis e métodos (mais sobre modificadores no Dia 15, "Modificadores, Controle de acesso e Desenho de Classe")
Além disso, haverá um número de novos métodos disponíveis na classe de Class para ajudar a atar em conjunto várias classes de reflexão.
Pode descobrir mais sobre as novas classes de reflexão e métodos de http://java.sun.com/products/JDK/1.1/designspecs/reflection/.
Para terminar hoje, vamos olhar para a biblioteca de classe de Java. De fato, teve alguma experiência com algumas classes de Java já, portanto não devem parecer que estranhos.
A biblioteca de classe de Java fornece o jogo de classes que se garantem para estar disponíveis em qualquer ambiente de Java comercial (por exemplo, em qualquer ambiente de desenvolvimento de Java ou em browseres como Netscape). Aquelas classes estão no pacote de java e incluem todas as classes que viu por enquanto neste livro, mais um lote inteiro mais classes aprenderá sobre mais tarde neste livro (e mais não pode aprender sobre em absoluto).
O Conjunto de Desenvolvedor de Java vem com a documentação para toda da biblioteca de classe de Java, que inclui descrições de variáveis de exemplo de cada classe, métodos, construtores, interfaces, e assim por diante. Pode vir a esta documentação (chamou a Interface de Programador Aplicada de Java ou API) via a Web em http://java.sun.com:80/products/JDK/CurrentRelease/api/packages.html. Um sumário mais curto de Java API está no apêndice C também. Explorar a biblioteca de classe de Java e os seus métodos e variáveis de exemplo é uma ótima maneira compreender o que Java pode e não pode fazer, bem como como pode tornar-se um ponto de partida do seu próprio desenvolvimento.
Aqui estão os pacotes de classe que são parte da biblioteca de classe de Java:
- java.lang - Classes que aplicam à própria língua, inclusive a classe de Object, a classe de String e a classe de System. Também contém as classes especiais dos tipos primitivos (Integer, Character, Float, e assim por diante). Adquirirá pelo menos um relance à maioria das classes neste pacote nesta primeira semana.
- java.util - classes de Serviço, como Date, bem como classes de coleção simples, como Vector e Hashtable. Aprenderá mais sobre estas classes na Semana de Bônus.
- java.io - classes de Entrada e saída para escrever a e ler em correntes (como entrada e saída padrão) e para tratar arquivos. Dia 19, "As correntes e a entrada-saída", descreve as classes neste pacote.
- java.net - Classes para transmitir o suporte em rede, inclusive Socket e URL (uma classe para representar referências para documentos sobre World Wide Web). Aprenderá um pouco sobre a ligação em rede no Dia 14, "Windows, Ligação em rede e Outros Petiscos", e logo no Dia 26, "Cliente/Servidor que Transmite em rede em Java".
- java.awt - Isto é a Caixa de ferramentas de Windowing Abstrata. Contém classes para implementar características de interface de usuário gráficas, inclusive classes de Window, Menu, Button, Font, CheckBox, e assim por diante. Também inclui mecanismos de eventos de sistema gerentes e de processar imagens (no pacote de java.awt.Image). Aprenderá todos sobre o awt na Semana 2.
- java.applet - Classes para implementar Java applets.
Além das classes de Java, o seu ambiente de desenvolvimento também pode incluir classes adicionais que fornecem outra utilidade ou funcionalidade. Embora estas classes possam ser úteis, porque não são parte da biblioteca de Java padrão, podem não estar disponíveis para outras pessoas que tentam dirigir o seu programa Java a menos que explicitamente inclua aquelas classes com o seu programa. Isto é especialmente importante para applets, porque se espera que applets sejam capazes de correr em qualquer plataforma, usando qualquer browser permitido por Java. Só as classes dentro do pacote de java se garantem para estar disponíveis em todos os browseres e ambientes de Java.
Objetos, objetos em todo lugar. Hoje, aprendeu todos sobre como tratar com objetos: como criá-los, como descobrir e modificar os valores das suas variáveis, e como chamar os seus métodos. Também aprendeu como copiá-los e compará-los e como convertê-los em outros objetos. Finalmente, aprendeu um bocado sobre as bibliotecas de classe de Java - que lhe dão um salto vertical inteiro de classes para jogar com nos seus próprios programas.
Agora tem o fundamentals de como tratar com as coisas mais simples na língua de Java. Tudo que deixou é tabelas, condicionais e laços, sobre os quais aprenderá amanhã. Então aprenderá como definir e usar classes em aplicações de Java no Dia 6, e lançamento diretamente em applets a próxima semana. Com quase tudo faz nos seus programas Java, sempre voltará a objetos.
Q: | Confundo-me sobre as diferenças entre objetos e os tipos de dados primitivos, como int e boolean.
|
A: | Os tipos primitivos na língua (byte, short, int, long, float, double, boolean e char) representam as coisas mais pequenas na língua. Não são objetos, embora de muitos modos possam tratar-se como objetos - podem destinar-se a variáveis e passar-se em e fora de métodos. A maioria das operações que trabalham exclusivamente em objetos, contudo, não trabalharão com tipos primitivos. Os objetos são os exemplos das classes e, como tal, são tipos de dados normalmente muito mais complexos do que números simples e carateres, muitas vezes contendo números e carateres como variáveis de classe ou exemplo. |
Q:
| Nenhum ponteiro em Java? Se não tiver ponteiros, como se supõe que faça algo como listas ligadas, onde tem um ponteiro de um nariz ao outro assim pode atravessá-los?
|
A:
| Java não tem ponteiros em absoluto; não tem ponteiros explícitos. As referências a objeto são, efetivamente, ponteiros. Assim para criar algo como uma lista ligada, criaria uma classe chamada Node, que teria uma variável de exemplo também do tipo Node. Logo para ligar em conjunto objetos de nó tudo que tem de fazer é destinam um objeto de nó à variável de exemplo do objeto justo antes dele na lista. Como as referências a objeto são ponteiros, as listas ligadas estabelecem-se este caminho vai se comportar como os esperaria a. |
Q: | Na seção na chamada de métodos, tinha exemplos de chamar um método com um número diferente de argumentos cada vez - e deu um tipo diferente do resultado. Como é possível?
|
A: | Isto chamou a baldeação de método. Sobrecarregar meios que o mesmo método pode ter comportamento diferente baseado nos argumentos que se chama com - e o número e o tipo de argumentos pode variar. Quando define métodos nas suas próprias classes, define assinaturas de método separadas com jogos diferentes de argumentos e definições diferentes. Quando se chama um método, Java compreende que definição realizar baseado no número e o tipo de argumentos com os quais o chamou. Aprenderá todos sobre isto no Dia 6. |
Q: | Nenhum operador que sobrecarrega em Java? Porque não? Pensei que Java foi baseado em C ++, e C ++ tem o operador que sobrecarrega.
|
A: | Java de fato foi baseado em C ++, mas também se projetou para ser simples, tantos C ++ as características retiraram-se. O argumento contra o operador que sobrecarrega é isto porque o operador pode definir-se para significar algo; faz muito difícil compreender o que qualquer operador dado faz a qualquer momento. Isto pode resultar no código inteiramente ilegível. Quando usa um método, sabe que pode significar muitas coisas para muitas classes, mas quando usa um operador você gostaria de saber que sempre significa a mesma coisa. Considerando o potencial do abuso, os desenhistas de Java sentiram que foi um dos C ++ características que se omitiu melhor. |