Revista Do Linux
 
OUTRAS SEÇÕES
  Cartas
  Variedades
  Rádio Linux
  CD do Mês
  Coluna do Augusto
  Leitura
  Dicas e truques
  Opinião
 

O geek que sabia Java

Parte I
Nascida de um projeto da Sun para descobrir qual seria a nova onda da informática, a linguagem Java cada vez mais ganha novos adeptos e defensores. Apropriada para a criação de aplicativos independentes de plataforma, a linguagem ganhou muita popularidade desde 1995, quando foi publicamente anunciada. A Revista Do Linux traz até você um curso de Java, voltado aos que já conhecem alguma linguagem de programação, como C ou C++, dividido em várias edições e escrito por um dos autores do livro ~SAprendendo Java 2~T, Rodrigo Fernandes de Mello. Aproveite para iniciar o ano novo que se aproxima aprendendo uma nova linguagem

A linguagem de programação Java nasceu como parte do The Green Project, um projeto da Sun iniciado em 1990 por Patrick Naughton, Mike Sheridan e James Gosling, que tinha como objetivo tentar descobrir qual seria a ~Snova onda~T da computação e como seria possível desenvolvê-la.

Em Abril de 1991, com uma mudança de endereço do escritório do projeto, Chris Warth, Ed Frank e Craig Forrest uniram-se ao grupo. Ed Frank trouxe a idéia de um dispositivo baseado na plataforma SPARC com um sistema operacional embarcado. Dava-se início ao protótipo do Star7, um novo handheld wireless baseado na arquitetura SPARC, com um display LCD colorido de 5" com touchscreen.

Para desenvolver a interface do Star7 foi criada uma nova linguagem de programação independente de processador. A linguagem foi desenvolvida por James Gosling e recebeu o nome de Oak (carvalho), por causa das árvores que podiam ser vistas através de sua janela. Esta linguagem mais tarde se tornaria a linguagem Java. A equipe de desenvolvimento tentava encontrar um mercado para a venda do Star7 e as companhias de TV a cabo, interessadas em projetos de set-top-boxes e de vídeo sob demanda pareciam fazer mais sentido. A equipe desenvolveu então um novo protótipo chamado MovieWood, mas, infelizmente, estas indústrias estavam começando a aparecer e ainda tentavam investir em modelos de negócios mais viáveis para se fixarem no mercado.

Quando perceberam que a tecnologia desenvolvida pelo grupo era bastante boa, mas que não havia clientes para ela, tentaram visualizar o que poderia ser feito com a criação da equipe, agora conhecida como FirstPerson. Foi então que John Gage, James Gosling, Bill Joy, Patrick Naughton, Wayne Rosing e Eric Schmidt resolveram apostar na internet.

A grande rede mundial era exatamente o cenário que o grupo esperava para a tecnologia desenvolvida. Em 1994, a FirstPerson disponibiliza para download o WebRunner, um clone do navegador Mosaic feito com tecnologia baseada em Java, que mais tarde foi oficialmente chamado de HotJava. O WebRunner foi o primeiro navegador a apresentar objetos se movendo e o conteúdo dinâmico sendo executado em uma página da Internet.

Em 1995, John Gage e James Gosling apresentaram o WebRunner na conferência de tecnologia, entretenimento e design em Monterey e impressionaram o público com a possibilidade de ter animações em um navegador, fazendo com que os presentes no auditório repensassem seus conceitos sobre as capacidades da internet.

Em março de 1995 o grupo liberou uma versão pública do código fonte do Java para download na internet. O sucesso foi grande, em alguns meses os downloads chegavam à casa dos milhares e a linha T1 compartilhada que o grupo possuía não era suficiente para a crescente demanda de mercado que o software estava causando.

Após algum tempo a tecnologia foi incorporada ao navegador Netscape, então onipresente no mercado de browsers e, mais tarde, também em alguns produtos da Microsoft. Desde então, o Java é utilizado pelas mais diversas empresas, possibilitando a criação desde simples gráficos animados em um website a complexos sistemas de análise meteorológica.

Programação Orientada a Objetos

A programação orientada a objetos é um paradigma de programação baseado no conceito de classes e objetos. As classes são elementos onde dados e procedimentos podem ser agrupados, segundo sua função para um determinado sistema. Essas classes são codificações no formato de arquivos; quando uma destas classes é utilizada como um tipo de dado para a criação de uma variável, essa variável é chamada de objeto.

O que é uma Classe?

Uma classe é definida como uma estrutura de dados que contém métodos e atributos. No paradigma da orientação a objetos, os procedimentos ou funções (presentes em linguagens estruturadas, tais como C e Pascal) são chamados de métodos de uma classe. As variáveis, que são declaradas dentro de uma classe, são chamadas de atributos. Exemplo de uma classe em Java:

// declaração inicial da classe cliente
public class cliente
{
        // atributos da classe cliente
        String nome;
        String endereco;

        // métodos da classe cliente
        public void setNome (String novo_nome)
        {
                nome = novo_nome;
        }
        public void setEndereco (String novo_endereco)
        {
                endereco = novo_endereco;
        }
        public String getNome()
        {
                return nome;
        }
        public String getEndereco()
        {
                return endereco;
        }
} // fim da declaração da classe Cliente

O que é um Objeto? Enquanto uma classe é somente a codificação na forma de um arquivo texto, um objeto é uma instância de uma classe, ou seja, uma porção de memória que é reservada para armazenar os dados e os métodos declarados na classe. Enfim, um objeto é a instanciação de uma classe na memória. A classe é o código-fonte escrito em um arquivo texto, enquanto o objeto é uma parte de uma aplicação durante o processo de execução. No objeto, pode-se executar os métodos que foram definidos além de acessar e alterar dados.

O que é uma Mensagem?

Define-se mensagem como o ato de chamar ou requisitar a execução de um método. Portanto, um objeto do tipo Cliente apresenta diversos métodos, e o ato de requisitar a execução de um desses métodos é conhecido como mensagem.

O que é Encapsulação?

É a capacidade de restringir o acesso a elementos de uma classe por meio de qualificadores. Um qualificador é uma palavra reservada em uma linguagem orientada a objetos, que define a visibilidade de determinado atributo ou método. Veja na tabela 1.1 as características dos qualificadores na linguagem C++ e Java.

A seguir, um exemplo de uma classe em Java, que utiliza qualificadores:

// declaração inicial da classe Clientes

public class Clientes {

        // atributos da classe Clientes - estes
        // podem ser acessados somente dentro da classe

        private String nome;
        private String endereco;

        // atributos da classe Clientes acessíveis
        // por meio de código externo à classe

        public String cidade;
        public int idade;

        // atributos da classe Clientes acessíveis
        // por meio de código externo à classe,
        // desde que pertença ao mesmo pacote desta
        // classe - existe em Java, em C++, não.

        float saldo;
        String rg;

        // métodos da classe Clientes

        public void setNome (String novo_nome)
        {
                nome = novo_nome;
        }
        public void setEndereco (String novo_endereco)
        {
                endereco = novo_endereco;
        }
        public String getNome()
        {
                return nome;
        }
        public String getEndereco()
        {
                return endereco;
        }
} // fim da declaração da classe Clientes

O que é Herança?

A herança torna possível a reutilização de funcionalidades previamente definidas em uma classe. A finalidade é que a subclasse (aquela que herda as características de determinada classe) inclua o comportamento da superclasse (aquela que contém o comportamento a ser herdado) e adicione mais funcionalidades. Não seria interessante a herança, se não houvesse a possibilidade de adicionar funcionalidades à subclasse.

Existem construções de hierarquia de classes que apresentam erros. A figura anterior apresenta um exemplo de hierarquia onde a superclasse Carro tem as subclasses Porta e Pneu. Essa técnica não expressa corretamente o conceito de hierarquia, onde as subclasses especializam, ou seja, afunilam o conceito da superclasse. Caso utilize o mesmo questionamento realizado anteriormente para essa hierarquia como: ~SUma Porta é um Carro?~T, a resposta é não. Portanto, o correto é definir uma subclasse que tenha a ver com a superclasse, onde a subclasse seja o conceito da superclasse, adicionando algum conteúdo que possa representar de forma mais específica o conceito apresentado pela superclasse.

A herança pode ser múltipla onde uma subclasse herda características de diversas superclasses. A linguagem C++ suporta esse tipo de herança, enquanto a linguagem Java suporta somente a herança de uma única classe.

A seguir, um exemplo de herança em Java:

/*~Wdeclaração da superclasse~W*/

class madeira {
        // atributo da classe madeira
        String cor;

        // métodos da classe madeira
        public String getCor()
        {
                return cor;
        }
        public void setCor(String nova_cor)
        {
                cor = nova_cor;
        }
} // fim da declaração da superclasse

/*~W~Wdeclaração da subclasse~W~W*/

class cadeira extends madeira
{
        // atributos adicionais à superclasse
        int peso;
        // métodos adicionais à superclasse
        public void escreve_tela()
        {
                System.out.println(this.getCor());
        }
} // fim da declaração da subclasse

O que é Sobrecarga de Métodos e de Operadores?

Sobrecarregar um método ou operador é permitir que se utilize o mesmo nome de chamada para operar sobre uma variedade de tipos de dados. A seguir, um exemplo de classe em Java que tem o método setValor sobrecarregado:

// declaração da classe vetor
public class vetor
{
        // atributos da classe vetor
        private float X;
        private float Y;
        // métodos da classe vetor
        // ocorre sobrecarga no método setValor, pois
        // ele manipula uma ou duas variáveis do
        // tipo float
        public void setValor(float novo_x)
        {
                X = novo_x;
        }
        public void setValor(float novo_x, float novo_y)
        {
                X = novo_x;
                Y = novo_y;
        }
} // fim da declaração da classe vetor

A sobrecarga de operadores é oferecida para classes que desejem manipular adição, subtração e outras operações. A seguir, um exemplo na linguagem C++ onde existe a sobrecarga do operador adição (+) para que manipule objetos do tipo Vetor2D.

// declaração da classe em C++
class Vetor2D
{
        // atributos
        float x, y;
        public:
        // construtor
        Vetor2D(Vetor2D v2);
        // métodos
        void EscreveVideo(char texto[]);
        Vetor2D operator + (Vetor2D v2);
} // fim da classe Vetor2D

No exemplo anterior, é declarado um método: Vetor2D operator + (Vetor2D v2).
Existe nesse método a sobrecarga do operador + (adição). Esta sobrecarga torna possível a soma de dois objetos do tipo Vetor2D, como abaixo:

Vetor2D v1 = new Vetor2D;
Vetor2D v2 = new Vetor2D;

// uso do operador adição entre instâncias
// do tipo Vetor2D
Vetor2D v3 = v2 + v1;

No caso apresentado acima, o objeto v2 é responsável por executar de forma implícita uma chamada para o operador adição sobrecarregado (+), o qual executa uma determinada função sobre os dados. Na chamada para execução do operador sobrecarregado, o objeto v1 é enviado como parâmetro. Na declaração da classe Vetor2D, observa-se que o operador adição sobrecarregado recebe somente um parâmetro, que é do mesmo tipo da classe.

O que é Polimorfismo?M

É a troca de mensagens entre métodos de uma subclasse com sua superclasse, e assim sucessivamente. O polimorfismo pode ser observado através de métodos virtuais de uma classe como representado a seguir:

/*~Wdeclaração da superclasse~W*/

class Madeira
{
        // atributo da classe Madeira
        String cor;
        // métodos da classe madeira
        public void escreve_na_tela()
        {
                escreve();
        }
        public void escreve()
        {
                System.out.println(~Sestou na classe Madeira!~T);
        }
} // fim da declaração da superclasse

/*~W~W~Wdeclaração da subclasse~W~W~W*/

class Cadeira extends Madeira
{
        // métodos adicionais à superclasse
        public void escreve()
        {
                System.out.println(~Sestou na classe Cadeira!~T);
        }
} // fim da declaração da subclasse

Na prática, o que acontece é que cada classe procura os métodos sempre da classe cujas chamadas estão sendo feitas em direção às superclasses. Na linguagem Java, todos os métodos são virtuais, portanto, suportam polimorfismo. Basta serem redeclarados nas subclasses. Em C++, o mesmo não ocorre, a superclasse deve permitir que determinado método seja reescrito nas subclasses.

O que são Construtores e Destrutores?

Construtores são métodos especiais que são chamados no processo de instanciação de um objeto no sistema. A execução de tais métodos garante que os identificadores serão inicializados de forma correta. Todo construtor tem o mesmo nome que a classe. O exemplo a seguir tem dois construtores, um que não recebe parâmetro algum e outro que recebe o nome de um cliente. Observe o exemplo em Java abaixo:

// declaração inicial da classe cliente
public class cliente
{
        // atributos da classe cliente
        private String nome;
        private String endereco;

        // construtores
        public cliente()
        {
                nome = ~S~T;
                endereco = ~S~T;
        }
        public cliente(String novo_nome)
        {
                nome = novo_nome;
                endereco = ~S~T;
        }
        // métodos da classe cliente
        public void setNome (String novo_nome)
        {
                nome = novo_nome;
        }
        public void setEndereco (String novo_endereco)
        {
                endereco = novo_endereco;
        }
        public String getNome()
        {
                return nome;
        }
        public String getEndereco()
        {
                return endereco;
        }
} // fim da declaração da classe Cliente

Todo construtor recebe o mesmo nome da classe. No exemplo anterior, existem dois construtores sobrecarregados, um que não recebe nenhum parâmetro e outro que recebe uma string novo_nome. Quando um objeto do tipo classe cliente é criado, isto pode ser feito de duas formas, pois existem dois construtores. Primeira forma:

// utilizando o construtor sem parâmetros que
// inicia o objeto do tipo cliente. É executado o
// código contido nesse construtor
cliente c1 = new cliente();

Segunda Forma:

// utilizando o construtor que recebe como parâmetro
// uma string que identifica o nome do cliente. É
// executado o código contido nesse construtor.
cliente c2 = new cliente(~So cliente~T);

O construtor é chamado somente durante o processo de instanciação do objeto. Nos construtores, são definidos comportamentos de início do objeto. Quando um objeto, por exemplo, do tipo Cliente é instanciado espera-se que o comportamento inicial do cliente seja satisfeito pelos construtores. Quais tipos de comportamento são esperados na instanciação de um cliente? Existem parâmetros como nome do cliente, endereço, cidade, estado, etc. Por meio desta análise de comportamento, são implementados os construtores.

Destrutores são métodos especiais chamados na finalização do objeto. Quando as posições de memória que um objeto ocupa devem ser liberadas, o destrutor é chamado. Na linguagem C++, todo destrutor tem o nome da classe precedido por ~ (til). Observe o exemplo em C++ a seguir:

// declaração da classe em C++
class Vetor2D
{
        // atributos
        float x, y;
        public:
        // construtor
        Vetor2D(Vetor2D v2);
        // destrutor
        ~Vetor2D();
        // métodos
        void EscreveVideo(char texto[]);
        Vetor2D operator+ (Vetor2D v2);
} // fim da classe Vetor2D

Quando um objeto do tipo Vetor2D estiver sendo removido da memória, o destrutor é chamado e nele devem conter chamadas que liberem a memória que está sendo utilizada pelo objeto.

Quando uma instância é criada utilizando a palavra new, ela é alocada na memória heap. As demais instâncias, tais como int, long e outras, são alocadas na stack (pilha do sistema). A stack é liberada automaticamente quando um programa ou objeto morre, entretanto a memória heap não é liberada automaticamente. Portanto, deve-se liberar a memória que foi alocada na heap utilizando a chamada delete sobre as instâncias que foram declaradas com o uso da palavra reservada new. Por exemplo:

// para instanciar
cliente c1 = new cliente();

// para liberar a memória heap
delete c1;

Portanto, o objetivo do destrutor é liberar a memória heap, alocada usando new, que não é liberada automaticamente. A stack é liberada automaticamente.

A Plataforma e a Linguagem Java
Tendo tudo isso em mente, pode-se dizer que a plataforma Java é composta de duas partes básicas:

  1. A Máquina Virtual Java (Java Virtual Machine - JVM): como se sabe, a Máquina Virtual Java tem como objetivo executar os bytecodes Java, traduzindo-os para código-nativo. Ela pode ser implementada em hardware (processadores dedicados que interpretam os bytecodes) ou software (tal como o J2SDK que inclui a Máquina Virtual, disponível em www.javasoft.com).
  2. A Interface para Programação de Aplicações em Java (Java Application Programming Interface - Java API): oferece um conjunto de pacotes de classes (packages) com funcionalidades semelhantes às bibliotecas de C ou C++. Ou seja, na Java API encontram-se classes que tratam de acesso a redes de computadores, manipulação de strings, gerenciamento de interfaces gráficas, threads etc.

Java API

A Java API é composta por vários pacotes (packages) que agrupam classes em torno de uma funcionalidade específica. Os pacotes básicos da Java API são mostrados na tabela 1.2.

Estes são apenas alguns pacotes. A Java API tem muitos outros, inclusive subpacotes dos citados anteriormente. É muito importante que, na hora em que estiver programando, você tenha sempre à mão uma referência da Java API. Esta referência pode ser encontrada no site www.javasoft.com/docs. Sem ela, é praticamente impossível criar algum programa na linguagem Java.

Coleta de lixo

A maioria das linguagens tem alguma instrução que permite que o programador requisite memória dinamicamente, ou seja, enquanto o programa está sendo executado. Da mesma forma, existe um comando que permite que o programador libere esta memória quando ela não for mais utilizada.

Na próxima edição da Revista do Linux, continuaremos com nosso curso de Java, abordando aspectos como tipos de dados, operadores, expressões, fluxo de execução e os passos para a compilação do nosso primeiro programa em Java. Até lá!

Por quê Star7?

Já no novo escritório da equipe, os telefones possuíam uma função útil: Quando um telefone estava tocando, podia-se atender a chamada a partir de outro aparelho pressionando as teclas * e 7. Então, quando alguém não podia atender uma ligação telefônica, este alguém gritava ~SStar Seven~T para que outra pessoa pudesse atender a chamada. Quando surgiu a necessidade de ~Sbatizar~T o projeto, o nome Star7 acabou sendo o escolhido

Duke

O mascote da linguagem Java se chama Duke, e foi criado como um 'agente' destinado a ajudar o usuário a navegar pela interface do projeto Star7, funcionando mais ou menos da mesma forma que o infame ~Sclipe~T de papel do Word'. E se você acha que já o viu em algum lugar, pode estar certo de que viu mesmo: seu formato foi inspirado no emblema da federação, do seriado de TV Star Trek.

Tabela 1.1 - Qualificadores nas linguagens Java e C++
Qualificadores Java C++
private O método ou atributo somente pode ser acessado dentro de sua própria classe. O método ou atributo somente pode ser acessado dentro de sua própria classe.
public O método ou atributo pode ser acessado externamente por outro código O método ou atributo pode ser acessado externamente por outro código
protected O método ou atributo pode ser acessado pela própria classe ou por classes filhas (aquelas que herdam desta classe). O método ou atributo pode ser acessado pela própria classe ou por classes filhas (aquelas que herdam desta classe)
package O método ou atributo pode ser acessado pela própria classe ou por classes que pertençam ao mesmo pacote Não existe em C++

Tabela 1.2 - Java API
Pacote Descrição
java.applet Contém as classes necessárias para se criar applets
java.awt Classes para se criar interfaces gráficas e para manipulação de imagens
java.io Provê o sistema básico de entrada e saída (I/O) e de manipulação de arquivos
java.lang Contém classes que são fundamentais no projeto da linguagem de programação Java
java.math Classes para cálculos com números de precisão arbitrária
java.net Provê classes que são utilizadas na programação de aplicações para redes
java.sql Contém classes que permitem o acesso a banco de dados
java.util Tem classes que são muito úteis no dia-a-dia da programação como, por exemplo, uma classe chamada Vector que implementa um vetor cujo tamanho vai sendo alocado dinamicamente


Rodrigo Fernandes de Mello - mello@virgos.com.br
É um dos autores do livro 'Aprendendo Java 2', publicado pela Novatec Editora


A Revista do Linux é editada pela Conectiva S/A
Todos os Direitos Reservados.

Política de Privacidade
Anuncie na Revista do Linux