quarta-feira, 25 de fevereiro de 2015

test Link 2

Novo mapa mental

Novo mapa mental

Imagemap
Novo mapa mental

Substitui o href no imagemap para ver se funciona.

imagem do linkTest

Imagem:
xxx

Link Test - para incluir imagens clicáveis.

Novo mapa mental

Novo mapa mental

Imagemap
Novo mapa mental Uso freemind para gerar os mapas mentais. O programa também suporta hyperlinks e gera imagens clicáveis. O formato gerado é XML com várias figuras e estilo CSS, mas tem problemas de compatibilidade. Aparentemente blogger não suporta o tag a fechado com /> como em < a href="http://fabionakano.blogspot.com.br/2015/02/0-bem-vindo.html" /> Ele não publica html nesse formato, exige que seja fechado com </a>
freemind gera tags nesse formato então precisarei substituí-lo ou eliminá-lo.
Blogger não tem suporte para CSS, mas isso não tem nenhum efeito que eu não deseje.

0.0.0.14.0 - Como reportar Erros e Exceções em aula

Há o que aprender para interpretar as mensagens de erro e exceção escritas na tela quando se executa o compilador ou a máquina virtual Java. É uma combinação de inglês com computação.

Informação parcial ou interpretações alternativas podem levar a ainda outra interpretação (incorreta).

A informação completa é a mensagem repetida literalmente, sem traduções E o código-fonte que causou o erro ou exceção.


0.0.0.14 - Erros e Exceções em Java

Não se espera que um programa em funcionamento normal execute operações que perturbem o funcionamento de outros programas ou do computador. Quando um programa o faz (este é o evento), supõe-se que seja acidentalmente ou por mal funcionamento ou por entrar em uma condição não prevista pelo programador. Por isso diz-se que o evento é inesperado. É necessário definir isto pois contraria o pensamento comum de que se algo é detectado então não é inesperado.

Erros são eventos inesperados que dificilmente (no juízo de valores de quem define Java) podem ser contornados durante a execução do programa escrito pelo programador da aplicação (em geral nós). Java diz pouco sobre o que gera erros (http://docs.oracle.com/javase/8/docs/api/java/lang/Error.html). Mesmo com essas poucas "dicas", é possível entender que funcionamento inesperado do hardware, sistema operacional, máquina virtual e outros que perturbam a aplicação podem provocar Erros.

Exceções são eventos inesperados que (eventualmente) podem ser contornados pelo programador da aplicação (http://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html) e por isso é dada ao programador da aplicação a chance de fazê-lo.

Explicações técnicas

O método main do seu programa é invocado pela JVM assim que ele começa a ser executado. Este invoca outros métodos, que invocam outras métodos, até chegar a uma instrução de máquina. Muitos desses métodos não foi você quem escreveu, alguns fazem parte da JVM, outros do Sistema Operacional. Há uma sequência (mais precisamente uma pilha) de métodos que foram invocados até checar à instrução de máquina.

Suponha que essa instrução causa uma exceção Por exemplo (hipotético, ilustrativo mas talvez inverossímil) uma instrução de máquina que soma o conteúdo do acumulador com o conteúdo de um endereço de memória é ADD <endereço>. O endereço não pode ser 00000000. A instrução ADD 00000000 não é válida. Sua execução é um evento inesperado e faria o processador lançar o equivalente a uma exceção. Se não for tratada no caminho, esta é propagada de volta na pilha de métodos invocados até chegar ao main, que imprime uma mensagem e aborta. Uma mensagem como: "Hello.java line 20: ADD 00000000: invalid address", seria de difícil compreensão pelo programador da aplicação.

Outro exemplo: Você esqueceu de instanciar um objeto e isso passou desapercebido pelos seus testes. O programa foi instalado no cliente que viu a mensagem "Programa.java line 239: null pointer exception". O que ele pode fazer para lidar com essa mensagem?

Note que para pelo menos um dos programadores envolvidos, qualquer que seja a mensagem de erro, ela fará sentido. Para algum (talvez outro) além de fazer sentido, ele é capaz de traduzi-la em algo mais apropriado.

Exceções são previsíveis e evitáveis, tal que comandos específicos para seu tratamento não são essenciais, mas esse tipo de tratamento dificulta a leitura e transmissão do código entre programadores. Observando isso, Java tem comandos específicos para tratamento de exceções.

Em Java...

...Erros e Exceções em Java são objetos que podem ser usados como superclasses (ou seja nós podemos criar nossos próprios erros e exceções). Estes são lançados por algum comando ou método.

Quando usamos estes métodos em nossos métodos, ou capturamos e tratamos as exceções, ou as passamos adiante (na pilha de métodos invocados). Os comandos específicos para isso são throw, throws, try, catch e finally.

0.0.0.11.3.0 - Polimorfismo

Por exemplo, pode-se escrever um método de nome soma, que ao receber dois inteiros, retorna sua soma aritmética. Pode-se escrever no mesmo programa um outro método soma que ao receber duas cadeias de caracteres, retorna sua concatenação. no momento da invocação do método, ele parecerá um só, de nome soma e dois argumentos que quando aplicado a inteiros faz uma coisa, quando aplicado a cadeias de caracteres faz outra - aparentemente o método soma tem duas formas.

Codificar o exemplo.

Polimorfismo vem do grego: várias formas. Em programação orientada a objetos refere-se à possibilidade de escrever métodos de mesmo nome que podem ser aplicados a diferentes tipos de dados. Esses métodos podem executar comandos diferentes. Como fizemos no exemplo.

Esta forma de polimorfismo emprega sobrecarga de métodos (method overloading). Sobrecarregar significa escrever vários métodos com mesmo nome e argumentos diferentes. O compilador seleciona o método a aplicar de acordo com o tipo dos argumentos.

Sobrecarga de métodos é muito usada em construtores. Por exemplo o objeto String tem 15 construtores (2 deprecados) http://docs.oracle.com/javase/8/docs/api/java/lang/String.html

Tarefa:
    Escrever classes com métodos polimórficos.

terça-feira, 24 de fevereiro de 2015

0.0.0.11.4 - Modificadores de Acesso

O acesso padrão para classe, atributos, e métodos é que todas as classes dentro do mesmo pacote podem instanciar classes, acessar variáveis e invocar métodos. Este é o acesso package private e é usado quando o acesso não é modificado por public, protected ou private.

Quando desejamos que o acesso possa ser feito por qualquer outra classe, usa-se o modificador public.

Quando desejamos que o acesso possa ser feito apenas por sub-classes, usa-se o modificador protected.

Quando desejamos que o acesso possa ser apenas dentro da classe, usa-se o modificador private.

A ordem de acesso, do mais aberto ao mais fechado é: public, package private, protected e private.

Interfaces e métodos da interface são public.

Sub-classes (e seus atributos e métodos) precisam ter o acesso pelo menos tão aberto quanto o da super-classe.

Tarefas:
    Escrever exemplos de uso de modificadores de acesso usando herança, pacotes e testando seu funcionamento.

0.0.0.11.3 - Herança

Java permite criar classes baseada em outra classe. A classe inicial é chamada super-classe (usa-se também classe pai ou classe base). A classe criada é chamada sub-classe (usa-se também classe filha ou classe derivada).

Baseado significa que a sub-classe contém todos os atributos e métodos da super-classe. Esse mecanismo é chamado herança.
Em outras palavras, a sub-classe herda os atributos e métodos da super-classe. Isto é uma forma de reúso de código, ou seja, evita que se escreva o mesmo código mais de uma vez.

Uma sub-classe é definida com o comando extends. Em Java, diz-se que a sub-classe estende a super-classe.

Com uma sub-classe o programador pode sobrescrever métodos e ocultar atributos.

Em Java, uma sub-classe pode ter apenas uma super-classe - não há herança múltipla.

O funcionamento de variáveis e métodos precisa ser pensado em relação à definição de herança:

A superclasse tem seus atributos com certo nome e métodos com certas assinaturas. A subclasse pode ter atributos e métodos com os mesmos nomes e assinaturas.

A superclasse não é modificada pela subclasse no sentido que o funcionamento de instâncias da superclasse não muda pela existência (ou não) de subclasses;

Definir na subclasse atributos de mesmo nome dos da superclasse ocultam os atributos da superclasse. Numa instância e num método da subclasse, o atributo da subclasse é acessado através do nome. Em um método da subclasse, o atributo da superclasse pode ser acessado com o "prefixo" super. Fora da subclasse o atributo não é acessível.

Definir na subclasse métodos de mesma assinatura dos da superclasse sobrescrevem estes. O funcionamento é análogo ao das variáveis, o uso de super também tem o mesmo efeito.


Tarefas:
    Escrever exemplos de herança, ocultamento de variáveis, sobrescrita de métodos.

0.0.0.11.2 - package, import - suporte a programação modular

Programas Java sem estes comandos podem ser distribuídos em vários arquivos dentro de uma única pasta, por exemplo uma classe em cada arquivo (o que é o usual). As classes dentro da pasta podem usar umas as outras. Não haveria como distribuir programas em várias pastas sem os comandos package e import.

package informa que o arquivo pertence a determinado pacote.

Em geral package, quando existe, é o primeiro comando do arquivo (pode ser precedido de comentários, por exemplo um cabeçalho - comentários não são comandos).

Pacotes em Java correspondem a pastas no sistema de arquivos. Assim, requer que o nome da pasta que contém o arquivo seja igual ao nome do pacote declarado em package.

import informa que determinado pacote deve ser importado (pois contém uma ou mais classes que são usadas no arquivo).

O uso comum de import é: import java.util.io.* que informa que todas as classes do pacote java.util.io devem ser importados.

Algumas classes, como System e String são importadas automaticamente, logo seu arquivo não conterá algo como import java.System

Os métodos da classe Math podem ser usados sem import - é algo tolerado. São todos estáticos e podem ser usados com o operador . (ponto): Math.abs(...), Math.pow(...), ...

Java permite o comando static import java.Math, que importa o pacote Math e dispensa o uso do prefixo Math.

Tarefas:
    Escrever exemplos de pacotes e usos.


0.0.0.11.1 - Atributos e métodos

Atributos são variáveis declaradas no escopo da classe. Métodos da classe são os definidos no escopo da classe.

Atributos podem ser objetos.

Para acessar os atributos ou invocar os métodos, usa-se o operador . (ponto)
Caso o atributo ou método seja acessível a partir do escopo em que o operador foi usado.

objeto.atributo // permite usar o atributo

objeto.metodo() // invoca o método

Tarefas:
    Escrever exemplos de classes com atributos e métodos.

0.0.0.11.0 - Instanciação, construtores, destrutores e garbage collection

A instância de uma classe é criada em tempo de execução pelo comando new. Chamamos isso instanciação de um objeto e como é feito em tempo de execução, então o contexto é dinâmico.

new aloca a memória necessária para armazenar os atributos e invoca o construtor que lhe é passado, retornando a referência para o objeto. Em geral esta é armazenada em uma variável que é usada paraa cessar essa instância.

construtor é um método encarregado pela inicialização dos atributos. Em geral classes têm um ou mais construtores definidos pelo programador. Há casos em que os valores padrão dos atributos são satisfatórios e o programador não define nenhum construtor. Neste caso, Java "fornece" um construtor padrão.

destrutor é o método que finaliza as variáveis e de-aloca a memória. Java não permite destrutores. Ao invés disso, tem garbage collector - um programa que roda em paralelo aos outros e que detecta objetos "abandonados", destruindo-os. Logo, se a referência para a instância for "abandonada" seja pela modificação da variável, seja porque tenha se saído do escopo da variável, em algum momento a instância será destruída e a memória ocupada retornará para o pool de memória livre.

Tarefas:
    Escrever exemplos de instanciação.

quinta-feira, 19 de fevereiro de 2015

0.0.0.2 e meio - O que é um computador?

Computador é uma máquina que chaveia eletricidade.

Atualmente os computadores mais comuns são elétricos e digitais. Parece "óbvio" ou "desnecessário" escrever isso, mas houve muitos projetos de máquinas antes de chegar-se ao atual.

As primeiras máquinas de calcular eram mecânicas e o primeiro computador projetado  (a máquina analítica de Babbage, no séc. XIX: http://en.wikipedia.org/wiki/Analytical_Engine) era mecânica e era capaz de executar qualquer algoritmo que uma máquina moderna executaria.

Antes que os computadores digitais se estabelecessem, houve pesquisa também em computadores analógicos. Componentes como capacitores e indutores servem como integradores e diferenciadores, e por isso podem ser usados para cálculos avançados (ACH2011) e também aritmética. O desenvolvimento dessa tecnologia foi mais lento que o da digital pois dependia da construção de componentes muito precisos e com perdas pequenas ou conhecidas (teoricamente um computador deste tipo faria cálculos com precisão infinita, o que os computadores atuais não são capazes de fazer).

Estreitando nos computadores atuais, (aproveitando parte do post sobre compiladores), eles chaveiam eletricidade de forma que passe ou não corrente em condutores, ou haja (ou não) tensão elétrica sobre componentes. Por facilidade de implementação, apenas dois símbolos são "permitidos" sobre cada condutor ou sobre cada componente.

O ser humano atribui significado ou interpretação aos circuitos e símbolos. A utilizada: um condutor ou um componente corresponde a um dígito. Passa corrente corresponde a "1", não passa corresponde a "0". Criou-se um dígito binário (bit).

Concatenando bits independentes formam-se sequências de bits, por exemplo "10100111". Nota: juntando afirmações "óbvias" a conclusão pode não ser tão óbvia assim...XD

Aí entra outra invenção humana: a matemática: Digamos que esta sequência de símbolos representa um número na base binária. Como os bits são independentes, então todas as combinações de sequencias binárias podem ser representadas*.

Existe uma teoria que permite converter números de uma base para outra, e outra que define operações lógicas, aritméticas e relacionais,... inclusive operações aritméticas podem ser construídas a partir de operações lógicas (Veja aritmética na base binária).

Ao circuito podemos acrescentar um outro número, que codifica a operação. Temos três números:A Op B onde A e B são operandos e Op é uma operação: Se Op={0:soma, 1:subtração, 2: multiplicação, 3: divisão}. Por exemplo 5 2 3 é o produto de 5 por 3. Caso você queira saber como é esse circuito: http://en.wikipedia.org/wiki/74181


Sendo muito simplista, juntando a máquina elétrica, a interpretação dos sinais em números binários, aritmética e conversão entre bases temos uma calculadora que pode até ser decimal!

Sofisticando um pouco esta máquina:

Acrescente memória. Memória é um componente elétrico que armazena o sinal que foi escrito. Uma memória de 1 bit armazena ou 0 ou 1 em seu dígito. Novamente podemos concatenar bits de memória e fazê-la armazenar um número. Podemos também concatenar muitas memórias de um número e construir bancos de memória para muitos números... acessamos cada número por seu endereço (que é outro número). Esse componente suporta as operações "armazene DDDD no endereço AAAAA", e "recupere o que está gravado no endereço AAAAA".
Na memória são armazenados tanto programas quando dados. A interpretação é posicional, sendo que o número armazenado na posição zero é um comando.Supondo que o programa já está na memória, apertar um botão (convencionalmente o reset) faz a máquina começar a executar que estiver na memória a partir da posição zero. A execução é sequencial: lê o comando na posição zero, lê o operando na posição 1, lê outro operando na posição 2, executa o comando, lê o próximo comando na posição 3, ....

Acrescente comandos para testar valores armazenados na memória e "saltar" para executar a partir de outra posição de memória.

Isso é tudo o que um computador faz (e é tudo o que uma máquina precisa fazer para ser um computador). Se quiser ver que comandos foram adicionados, veja o primeiro microprocessador da intel http://en.wikipedia.org/wiki/Intel_4004 e baixe seu datasheet.

Se quiser programar em linguagem de máquina, existe um simulador chamado HIPO http://hipo.sourceforge.net/. Ele foi desenvolvido para que estudantes de ciência da computação aprendam o que é programar em linguagem de máquina e não é um 4004 (se vc conhece o brinquedo Genius, ele usa um 4004).


Um modelo (modelos são simplificações) útil para um computador é o de Von Neumann. Nele o computador tem três partes interligadas: O processador, a memória e o dispositivo de entrada e saída (a maneira como esses blocos são conectados, por exemplo os circuitos, são abstraídos nesse modelo).

http://en.wikipedia.org/wiki/Von_Neumann_architecture

O modelo de computador usado para explorar matematicamente a capacidade desse tipo de máquina é a máquina de Turing. O modelo é simples. A teoria matemática construída usando esse modelo mostra que ele é capaz de fazer tudo o que nossos computadores fazem (na verdade talvez faça mais pois tem memória infinita).

http://en.wikipedia.org/wiki/Turing_machine


A teoria da computação tem muitos resultados importantíssimos: A equivalência de Turing mostra que nossos computadores são equivalentes a máquinas de Turing e mostra que a máquina analítica também o é. Também é por essa teoria que sabe-se o que é necessário para usar todo o potencial da máquina.... o teorema da programação estruturada, que se segue.


------
* representar o conjunto todo e sem repetições é uma propriedade importante!

** demonstrar teoremas está além do escopo desta disciplina - é assunto principal de ACH2013-Matemática Discreta. Demontrar alguns teoremas em computação é assunto em ACH2043-Introdução à Teoria da Computação.

0.0.0.13.0 - arrays 2

   {
    byte[] A={21, 9, 77, 32, 44};                //1
    for (int i=0;i<5;i++) {                      //2
     System.out.println ("A["+i+"]="+A[i]);    //3
    }
   }
  

A linha 1 cria o array e a referência com identificador A. A linha 2 repete o bloco de código 5 vezes, com i indo de 0 a 4, quando i==5 o loop termina e o bloco não é executado. A linha 3 é o bloco de código repetido 5 vezes e é executado uma vez para cada valor de i. Executado para i==0, imprime na tela o valor armazenado em A[0], para i==1, imprime o valor A[1], e assim por diante.

Arrays com mais dimensões

Sabemos como definir arrays de uma dimensão. Como seriam arrays de duas ou mais dimensões? ... ela segue a mesma idéia das referências, ou seja, se

 int[]
declara uma referência para inteiros, essa referência "aponta" para o conteúdo.

 int[][]
declara uma referência para referências para inteiros. A primeira "aponta" para um array de referências e cada elemento desse array aponta para o conteúdo correspondente.

 int[][][]
declara uma referência para referências para referências para inteiros. A primeira "aponta" para um array de referências e cada elemento desse array aponta para seu respectivo array de referëncias cada elemento deste aponta para o conteúdo correspondente. As três situações são diagramadas abaixo.

Diagramas de arrays

Como declarar arrays de mais de uma dimensão

   int[] A={21, 9, 77, 32, 44}; // uma dimensão
  
   int[][] M={{21, 9, 77, 32, 44},
               {1, 19, 37, 92, 48}}; // duas dimensões
  
   int[][][] C={
                 {{21, 9, 77, 32, 44},
                  {1, 19, 37, 92, 48}}, // tres dimensões
                 {{-21, -9, -77, -32, -44},
                  {-1, -19, -37, -92, -48}},
                 {{2, 9, 7, 3, 4},
                  {21, 1, 3, 9, 8}}
               };
  

Usos de arrays*

* embora possa conter erros (e por isso requerer leitura crítica), Wikipedia contém bons exemplos.

0.0.0.11 - Objetos

Objetos são uma forma de encapsular juntos os dados e os métodos que operam sobre esses dados.
 Por exemplo, podemos usar um inteiro para armazenar tempo e um método para adicionar tempos. Podemos também usar um inteiro para armazenar cores...

... podemos também aplicar o método para adicionar tempos sobre as cores...

esse engano não será encontrado antes da execução do programa, quando ele não funcionar conforme o esperado.

Em Java, criando os objetos cor e tempo, este com o método que adiciona, a linguagem não permitiria aplicar esse método sobre o objeto cor. O engano não ocorreria.

Conceitualmente, objetos são uma evolução sobre tipos abstratos de dados pois estes encapsulam dados juntos e métodos em separado, o que possibilita o engano do exemplo. Cronologicamente há quem afirme que os conceitos foram concebidos na mesma época.

Essa definição de "objeto" em linguagens de programação conserva muitas analogias com objetos do "mundo real". Instrutores de linguagens orientadas a objetos costumam aproveitar-se dessa analogia para apresentar linguagens orientadas a objetos (e assim o farei), o aprendiz deve ter em mente que isso não é necessário - é apenas um recurso didático.

A partir de agora trataremos apenas de objetos em linguagens de programação. Estes contém variáveis que geralmente armazenam características do objeto e por isso chamadas atributos e o objeto pode  tanto agir quanto receber ações, codificadas em métodos.

Por exemplo, pense nos seguintes problemas:
  • "Você quer comprar uma mesa de trabalho e quer escrever um programa que busca candidatas. Como representar uma mesa de trabalho nesse programa?";
  • "Representar uma mesa de trabalho em um programa para um site de vendas";
  • "Representar uma mesa de trabalho em um simulador gráfico de ambiente de trabalho".
Note que para cada problema há diferentes atributos relevantes. Pode ser importante para você que a mesa tenha uma borda de ferro para fixar lembretes com ímãs, para o site de vendas, qual é a localização do ítem no estoque e para o simulador gráfico, se tem pernas verticais, ou em X, ou em formato de pedestal. O processo de escolha dos atributos relevantes faz parte do projeto de software. Os atributos desnecessários são abstraídos (desconsiderados).

Linguagens orientadas a objeto facilitam ao programador focar nos aspectos essenciais dos objetos e em O QUE ele faz, adiando a especificação sobre COMO ele faz. Em determinadas circunstâncias convém ocultar COMO o objeto faz e mostrar O QUE ele faz. Seja por esse conhecimento não ser relevante a quem vai usá-lo, seja por manter a implementação sob sigilo.

O ocultamento bem usado permite a modificação de objetos sem necessidade de alteração do código que USA esse objeto, ou seja, auxilia na construção de módulos independentes.

Da forma como um objeto (em programação) é definido, determinar que atributos e métodos tem equivale a responder às perguntas informais:

  1. o que (que atributos) o objeto tem?
  2. o que o objeto faz (ou o que fazem com o objeto, ou ainda como interagir com o objeto)?.
 No paradigma orientado a objetos define-se visão interna como a estrutura e o comportamento do objeto, visão externa como a interface como se interage com o objeto e mensagem como o mecanismo pelo qual a interação efetivamente ocorre. Em Java mensagem corresponde à invocação de métodos.

Em todos os exemplos apresentados aqui e em quase todos os programas deseja-se atribuir ou modificar os valores dos atributos durante a execução do programa, não durante a codificação. Isto é feito generalizando objetos em classes.


Classes são definições suficientemente genéricas dos objetos que deseja-se representar (quanto é suficiente depende da aplicação). Por exemplo, em algum dos problemas a cor do tampo não é relevante (e por isso escolhemos não representá-la), ou a cor é sempre 'azul' (podemos optar por deixar implícito ou representar como uma constante) ou pode ser importante armazená-la e modificá-la (se for um conjunto pequeno de cores, um caracter pode ser suficiente, se for toda a paleta do computador, um RGB armazenado em 24 ou 32 bits,...).

Usando o conceito de classes, objetos são instâncias, que são construídas (alocadas em memória e inicializadas) usadas e destruídas (apagadas e liberadas da memória).

Nota: Linguagens orientadas a objeto como Java não são computacionalmente mais poderosas que linguagens procedurais como Fortran, mas podem ser mais práticas para determinados usos.



----- anotações dispersas ----
São elementos característicos da orientação a objetos:
instanciação;
construtores;
herança;
    - polimorfismo;
    - classes abstratas e interfaces;

    - vinculação tardia;
destrutores;


Uma forma de representar classes e relações entre classes é o diagrama de classes, que é um tipo de diagrama UML (Unified Modeling Language).

É possível usar as relações entre classes de forma a aproveitar certa propriedade e resolver determinados problemas. Essas soluções foram catalogadas e suas propriedades foram elicitadas em padrões de projeto (design patterns), foco da disciplina ACH2003-Computação Orientada a Objetos.

Nesta disciplina estudaremos o padrão Decorator para ilustrar um uso menos intuitivo de herança. Este padrão é muito usado nas classes de Java que fazem acesso a arquivos.

Herança "poupa" codificação - isto é "verificável" usando a interface Serializable.

0.0.0.13 - Arrays 1

Arrays, arranjos, vetores e matrizes.

Objetivo desta aula:

Apresentar o primeiro tipo abstrato de dados.

links citados durante a aula

M

T

Introdução

Chamamos tipos abstratos de dados (ADT ou TAD) os tipos de dados que não são os primitivos. Arrays e Strings são tipos abstratos presentes na maioria das linguagens de programação. Outros tipos podem ser criados pelos usuários ou pelos mantenedores da linguagem. Por exemplo, o tipo que representa datas em C (struct tm no arquivo time.h). No sentido estrito, TAD se refere apenas às variáveis, e não aos métodos.

  struct tm                                                                                                
  {                                                                                                   
     int tm_sec;           /* Segundos */      
     int tm_min;           /* Minutos */                            
     int tm_hour;          /* Horas */                       
     int tm_mday;          /* Dia do mes */             
     int tm_mon;           /* Meses */                
     int tm_year;          /* Anos  */                       
     int tm_wday;          /* Dia da semana */                 
     int tm_yday;          /* Dia do ano */                        
     int tm_isdst;         /* DST.     [-1/0/1]*/         
  }
  

A extensão do conceito de tipo abstrato, para incluir métodos, ou seja, associar métodos aos dados, originou a idéia de objeto. Como Java é uma linguagem orientada a objetos, torna-se difícil ilustrar o conceito de tipo abstrato, pois Java já parte do conceito estendido.

Os tipos abstratos Arrays ou arranjos representam conjuntos homogêneos (por exemplo números) distintos por sua posição relativa. Estes são usados em computação para representar vetores e matrizes, e são essencialmente a mesma estrutura da informação.

Além do seu uso em física e matemática, para representar pontos, transformações de coordenadas e sistemas de equações, são utilizados para representar listas, imagens, grafos. As imagens que se formam na tela de um computador, independente de serem texto ou imagem, estão armazenadas em uma matriz, fotos digitais também são matrizes. Os algoritmos de roteamento (do GPS) trabalham sobre uma representação da cidade como um grafo.

Funcionamento

Em Java, um array de bytes com cinco elementos é declarado e inicializado com:

   byte[] A={21, 9, 77, 32, 44};
  

O que indica que A é um array (e não um byte) são os colchetes após o tipo. Esse array contém os elementos 21, 9, 77, 32 e 44, que são acessados usando A[0], A[1], A[2],A[3],A[4], tanto para escrita quanto para leitura, ou seja:

   System.out.println (A[3]); // imprime 32
   A[2]=22;   // escreve 22 no lugar de 77
  

Podemos considerar a memória do computador um array (de 2G posições de um byte cada), também iniciando pelo índice zero.

Os elementos de um array são colocados na memória de forma contígua, ou seja, o elemento zero é imediatamente anterior ao elemento um, que é imediatamente anterior ao elemento dois e assim por diante. Supondo que o endereço do elemento de índice zero seja 0x0378 (em hexadecimal)

Endereço Conteúdo
0x378 21
0x379 9
0x37A 77
0x37B 32
0x37C 44

No caso acima, um endereço da memória armazena exatamente um valor do tipo byte, logo, passar para o próximo elemento equivale a passar para o próximo endereço, mas em outros tipos, como short (2 bytes) ou int (4 bytes), temos que "pular" de dois em dois ou de quatro em quatro. Isso é resolvido automaticamente pelo compilador/máquina virtual.

Este talvez seja o ponto menos intuitivo: em A está armazenada a referência para os dados. Referências são números que são convertidos em endereços de memória.

O comando

int[] A;
informa ao compilador/JVM que deve-se alocar memória para uma variável do tipo int[] com identificador (nome) A. Este tipo é uma referência para um inteiro. Quando não inicializadas, essas variáveis não se referenciam a dados válidos.

O comando

{21, 9, 77, 32, 44};
aloca um bloco de memória e armazena os elementos nesse bloco.

O comando de atribuição armazena na posição de memória cujo endereço corresponde a A, o endereço do bloco de memória.

Assim, A é inicializada com a referência para os dados. Complementando o mapa de memória, suponha que a variável A seja alocada no endereço 0x500. Que valor ela conterá? (resposta na tabela).

Endereço Conteúdo
0x378 21
0x379 9
0x37A 77
0x37B 32
0x37C 44
... ...
0x500 0x378

Certamente há outras formas de criar e usar arrays e outros tipos abstratos, inclusive formas que prescindem do uso de referências, mas esta solução tem vantagens (a que voltaremos em mais detalhes quando tratarmos sobre objetos):

  • Evita cópia desnecessária de grandes quantidades de dados;
  • Permite passar dados complexos para dentro e para fora de métodos;
  • Fornece uma forma simples e uniforme de tratar atribuições.

Voltando ao array, como acessamos seus elementos? Por exemplo A[2]? Bem, o acessamos tomando o endereço base (0x378) e acrescentando o offset (2* oTamanhoDe(int)), o que resulta em 0x37A. Desta forma, a que offset corresponde o endereço base?

Em geral, quando usamos um array, este será percorrido de alguma forma, e é o programador quem deve definir como isso será feito. Por exemplo, se quisermos escrever na tela o conteúdo de A, poderia ser uma boa resposta:

   {
    byte[] A={21, 9, 77, 32, 44};
    for (int i=0;i<5;i++) {
     System.out.println ("A["+i+"]="+A[i]);
    }
   }
  

Por favor, explique o que o código acima faz, e como.

Próxima parte

0.0.0.10.3 - métodos 5

Procedimentos e sua relação com funções matemáticas 4.

links citados durante a aula

Métodos na especificação da linguagem Java

Tutorial sobre métodos em Java

Por que métodos, procedimentos, funções e sub-rotinas? Existe alguma diferença?

Sendo rigoroso, há diferenças, embora sutis, entre cada um desses nomes. Estas tem a ver com o paradigma de linguagem de programação.

Paradigma é o tipo de linguagem, por exemplo, imperativo, em que ordenamos ao computador o que fazer; funcional, em que o código dentro da função não modifica o estado fora dela; procedural, em que o código dentro do procedimento pode modificar o estado fora dela e orientado a objetos, em que todas as variáveis são objetos.

Em linguagens de máquina e de montagem, sub-rotinas são chamadas através de dois comandos cujos mnemônicos são GO SUB ou GO TO. Isso foi herdado para versões iniciais de COBOL e BASIC - nessas linguagens também usa-se sub-rotina e elas são chamadas.

Em linguagens funcionais, quis se imitar o funcionamento das funções matemáticas, que modificam exclusivamente as variáveis definidas dentro delas. Acredito que atualmente a palavra funcional seja utilizada num outro sentido.

Em linguagens procedurais, os procedimentos são funções que podem modificar variáveis definidas fora delas. Funções e procedimentos são chamados. São linguagens procedurais PASCAL, C, FORTRAN.

Em linguagens orientadas a objetos, estes têm seu comportamento, ou ação, definido por métodos. Métodos não são chamados, são invocados (embora o funcionamento seja o mesmo). A diferença é que estes estão associados a objetos, ou seja, invocamos o método de um objeto.

Para que servem os métodos?

  • Apenas métodos são executados. Se você quer que a máquina execute algo, tem que escrever um método.
  • Caso um bloco de código seja usado repetidas vezes, ao invés de escrever o bloco diversas vezes, ou fazer CTRL-C CTRL-V, use um método. Inclusive se você precisar corrigir o método, só precisará fazê-lo uma vez.
  • Um método pode fazer algo muito complicado, ou que requeira muito código, mas que pode ser descrito com uma palavra, usar um método deixa o código mais fácil de ler,

Posso retornar mais de um valor?

Não diretamente, usando tipos primitivos, mas isso é possível, definindo seus próprios objetos ou usando arrays.

Existe diferença entre escrever na tela e retornar um valor?

Sim!!!. É completamente diferente. Imprimir na tela é uma invocação de método e "só" faz uns pontos na tela apagar e outros acender. Retornar um valor significa usar return e ainda "dizer" o que deve ser retornado.

Como posso passar mais de um valor para fora de uma função?

Use variáveis globais.

Exercícios

  • Escreva um programa em que dados cinco números, armazenados um em cada variável GLOBAL, teste e imprima na tela o valor do maior.
  • Escreva um programa em que dados dois números, e um caracter que será sempre uma das 4 operações aritméticas, faça a operação entre os números e imprima na tela o resultado.
  • Escreva um programa em que dados cinco números, armazenados um em cada variável, teste e imprima na tela o valor do maior.
  • Escreva um programa em que dado um número, testa se este é primo e imprime uma mensagem na tela informando o resultado. O teste deve estar em um método diferente de main.
  • Escreva um programa que sugere um entre três telefones celulares, dadas as características que o usuário deseja.
  • Escreva um programa que escreve na tela o n-ésimo elemento da sequência x(i)=x(i-1)+5 iniciando por x(0)=2.

A partir da semana que vem falaremos sobre tipos abstratos. Para entender seu funcionamento, precisamos saber, até certo ponto, como o computador funciona, em especial, como as variáveis são armazenadas na memória. Podemos estudar isso usando o Hipo. Este é um simulador de kit de microprocessador. Ele é programado em linguagem de máquina (lembra do sanduíche de mortadela??). Com os comandos dados, além de operações lógicas, aritméticas e relacionais, é possível implementar if, switch, while, do..while, for e sub-rotinas simples, sem passagem de parâmetro (pode-se usar variáveis globais). A tarefa para a próxima aula é rodar pelo menos um exemplo da documentação do HIPO. Ele é distribuído em um arquivo tipo JAR, que é executado diretamente pela JVM usando java -jar hipo.jar. Talvez seja útil entender o que são Máquinas de Von Neumann. Nossos computadores são esse tipo de máquina.

0.0.0.10.2 - métodos 4

Procedimentos e sua relação com funções matemáticas 3.

Objetivo desta aula:

Apresentar procedimentos/funções/métodos/subrotinas.

links citados durante a aula

Métodos na especificação da linguagem Java

Tutorial sobre métodos em Java

  class Taximetro {
   static double x=7.0;
   static double f (double x) {
    return x;
    
   }
   public static void main (String[] args) {
    double x=5.0;
    System.out.println (f(2.0));
   }
  }
  

Respostas:

  • Que valor será impresso na tela quando executarmos o programa? Imprimirá 2.0.
  • Quantas variáveis de nome x existem no programa? Três.
  • Qual é o escopo de cada variável? Uma "global", uma local a f (o parâmetro), e uma local a main.

A regra para saber qual variável será usada é proximidade de escopo, ou seja, será usada a variável do escopo mais próximo da linha que a utiliza.

Próxima parte.

0.0.0.10.1 - métodos 3

Procedimentos e sua relação com funções matemáticas 3.

Objetivo desta aula:

Apresentar procedimentos/funções/métodos/subrotinas.

links citados durante a aula

Métodos na especificação da linguagem Java

Tutorial sobre métodos em Java

Código completo do exemplo inicial

  class Taximetro {
   static double f (double x) {
    return 5+0.5*x;
   }
   public static void main (String[] args) {
    System.out.println ("ola");
    double w=5.0;
    System.out.println (f(w));
   }
  }
  

Código completo do exemplo ampliado

  class Taximetro {
   static double f (double x, int b) {
    double r;
    if (b==1) {
     r=5+0.5*x;
     } else {
     r=5+1.0*x;
    }
    return r;
   }
   public static void main (String[] args) {
    System.out.println ("ola");
    double w=5.0;
    int bandeira=2;
    System.out.println (f(w,bandeira));
   }
  }
  
  • Tente explicar o funcionamento do código acima, tenha especial atenção com o que ocorre com os parâmetros de f.
  • É possível reescrever a função, por exemplo usando switch e manter a funcionalidade. experimente.
  • Usar constantes (literais) pode ser desvantajoso, você seria capaz de mudar a função de maneira que o valor da bandeirada e do quilômetro sejam passados para a função como parâmetros? Neste caso, f teria quatro parâmetros.

Composição de funções

Voltando à matemática, existe o conceito de composição de funções, por exemplo g(f(x)). Que significa que aplicamos f sobre x e sobre o resultado, aplicamos g.

Como exemplo, temos uma empresa que envia seus funcionários para passar o dia em seus clientes e ao final do dia os traga de volta, de taxi. Para essa empresa, é interessante calcular o valor de duas corridas, mais o preço da espera do motorista, que é de R$80.00. Usemos a função mais simples de cálculo de valor de corrida.

f(x)=5+0.5*x, onde x é a distância percorrida em quilômetros.

e g(z)=80+2*z, onde z é o valor da corrida.

O código completo correspondente é:

   static double f (double x) {
    return 5+0.5*x;
   }
   static double g (double z) {
    return 80.0+2.0*z;
   }
   public static void main (String[] args) {
    System.out.println ("ola");
    double w=5.0;
    System.out.println (g(f(w)));
   }
  
  • Construa uma função, g(d,h) que receba o dia da semana e a hora, e retorne a bandeira que deve ser usada.
  • Componha esta função com a de cálculo de valor de corrida ampliada (f(x,b)) e apresente uma nova função h(x,d,h). Dica: como você escreveria (em notação matemática), a composição de f com g?

Escopo das variáveis

Quando trabalhamos com várias funções simultaneamente, precisamos ter claro como as variáveis funcionam nesta situação. Por exemplo, se definirmos em main uma variável x, ela é a mesmo que usamos na função f(x)?

Chamamos escopo da variável o intervalo do código em que essa variável é acessível. Em geral, uma variável é acessível no bloco onde é declarada e nos blocos contidos por ele. Por exemplo, se declararmos uma variável dentro da classe e fora de qualquer função, ela pode ser acessada por qualquer função:

  class Taximetro {
   static String mensagem="Táxis Ipê, calculando o valor da sua corrida...";
   static double f (double x, int b) {
    System.out.println (mensagem);
    double r;
    if (b==1) {
     r=5+0.5*x;
     } else {
     r=5+1.0*x;
    }
    return r;
   }
   public static void main (String[] args) {
    System.out.println ("ola");
    double w=5.0;
    int bandeira=2;
    System.out.println (f(w,bandeira));
   }
  }
  

A variável mensagem está definida dentro da classe, assim como os métodos f e main. Logo, ela pode ser usada dentro deles.

A variável mensagem foi declarada no escopo da classe. Em linguagens orientadas a objeto, ela é chamada atributo da classe (em C seria variável da classe;na documentação de java , é chamada member variable). Como até agora trabalhamos exclusivamnte em um contexto estático, a variável tem que ser estática também.

Quando trabalhamos com uma única classe em escopo estático, os atributos podem ser chamados "variáveis globais", em referência a tais variáveis no paradigma procedural.

A existência de vários escopos (e a escolha dos desenvolvedores da linguagem), permite declarar em diferentes escopos, variáveis de mesmo nome (no começo pode gerar um pouco de confusão, mas com a prática, veremos que é muito útil).

Uma ilustração deste caso é:

  class Taximetro {
   static double x=7.0;
   static double f (double x) {
    return x;
    
   }
   public static void main (String[] args) {
    double x=5.0;
    System.out.println (f(2.0));
   }
  }
  

Antes de ir para a próxima página, responda:

  • Que valor será impresso na tela quando executarmos o programa?
  • Quantas variáveis de nome x existem no programa?
  • Qual é o escopo de cada variável?

Próxima parte.

0.0.0.10.0 - métodos 2

Procedimentos e sua relação com funções matemáticas 2.

links citados durante a aula

Métodos na especificação da linguagem Java

Tutorial sobre métodos em Java

Executando uma função

Simplesmente incluir a definição de uma função no código não implica que a função será usada. Para usá-la, ela precisa ser "chamada". Para isto precisamos colocar o nome da função e seus parâmetros dentro de alguma função que seja executada - neste caso, em main.

   public static void main (String[] args) {
    System.out.println ("ola");
    double w=5.0;
    System.out.println (f(w));      /**/
   }
  

Relembrando: a JVM executa um programa a partir do método main. No método acima, o primeiro comando executado é a chamada ao método println com parâmetro "ola". O comando seguinte é a declaração da variável w. O comando seguinte é a atribuição do valor 5.0 a w. Na terceira linha, faz-se como em expressões com parêntesis - executa-se primeiro o que está dentro. No caso: Recupera-se o valor contido em w, chama-se f, que retorna um valor, que é passado para println. Finalmente, executa-se println.

Como funciona a chamada da função?

Este ponto é chave: Quando executamos f(w), o valor de w é copiado para x e então executa-se o bloco de código que define f. No exemplo, w vale 5.0 então 5.0 é copiado para x e então executa-se return 5.0+0.5*x.

Ampliando o conceito

Podemos escrever funções a várias variáveis. No exemplo do taxi, o valor do quilometro muda de acordo com o horário e dia da semana. Na bandeira 1, que é usada de segunda a sábado das 6h às 20h, o valor do quilômetro é R$0.50; na bandeira 2, usada nos outros horários, o valor do quilômetro é R$1.00.

Notando a bandeira com a variável b, o valor da corrida agora é f(x,b), onde f(x,b)=5+0,5*x, se b==1 e f(x,b)=5+1,0*x, se b==2 . Você conseguiria ajustar o código anterior para fazer este novo cálculo?? Tente fazer e depois siga em frente.

Próxima parte

0.0.0.10 - Métodos

Procedimentos e sua relação com funções matemáticas.

Objetivo desta aula:

Apresentar procedimentos/funções/métodos/subrotinas.

links citados durante a aula

Métodos na especificação da linguagem Java
Tutorial sobre métodos em Java

Introdução

procedimentos, funções, métodos, subrotinas, em linguagens de programação, tem uma idéia em comum: definir um bloco de código e dar-lhe um nome. Fora da definição, "executar esse nome", será equivalente a executar esse bloco de código.
Iniciaremos pelas funções matemáticas, com as quais estamos familiarizados, e começemos com uma simplificação de corrida de taxi: O valor de uma corrida de taxi é a soma do valor da bandeirada, que supomos fixado em R$5,00 mais 0,50 por quilômetro rodado. Chamemos f a função que relaciona a distância percorrida em uma corrida com o valor da corrida. Qual é a expressão dessa função?
f(x)=5+0.5*x, onde x é a distância percorrida em quilômetros.
Acabamos de definir uma função (matemática). Agora vamos usá-la:
Calcule o valor de uma corrida de 5km, ou em outra notação, f(5)=...
Para chegar ao resultado, atribuímos a x o valor 5 e calculamos o valor de f(x). O resutado é 7.5
Como faremos para calcular o valor de três corridas de 5km? Como podemos notar usando f(5)?
Calculamos então 3*f(5). Para isso atribuímos a x o valor 5, calculamos o valor de f(x) e multiplicamos por 3. O resultado é 22.5
Note que quando "calculamos f", acabamos "substituindo f por um número". Podemos também dizer que a aplicação de f sobre 5 resulta em 7.5. Em computação, é comum dizer que f retorna 7.5, ou que o valor retornado por f é 7.5
Como você programaria o computador para fazer esse cálculo?? (recomendo escrever e executar o programa antes de continuar a leitura)
Podemos codificar essa função no programa. Primeiro vamos definí-la. Lembre, Java é uma linguagem com tipagem forte, ou seja, temos que informar o tipo de todas as variáveis. Como a função retorna algo, e este algo tem que ter tipo, então precisamos dar um tipo à função também - é o tipo de retorno da função. Assim, chegamos a:
   double f (double x)
  
Esta é a declaração da função. Nela definimos como se usa, mas ainda não definimos o que ela faz - que é um bloco de código:
   {
    double r;
    r=5+0.5*x;
    return r;
   }
  
Neste bloco, definimos a variável r, que armazenará o resultados da conta, fazemos a conta e retornamos o valor contido em r.
Por uma questão do tipo de objeto que estamos usando, precisamos informar que o método é static. Enfim, a definição da função fica:
   static double f (double x)
   {
    double r;
    r=5+0.5*x;
    return r;
   }
  
Esta não é a única forma de escrever esta função, além de diferenças na indentação, podemos "economizar" variáveis e código:
   static double f (double x) {
    return 5+0.5*x;
   }
  
Se simplesmente incluirmos (CTRL-C CTRL-V) esta definição de função no código do OlaMundo e executarmos, o que o programa imprime na tela muda? Uma questão menos aparente: a função é utilizada?

0.0.0.6 - Variáveis e operadores aritméticos

Variáveis são posições de memória que armazenam valores. O identificador (nome) de uma variável serve como um rótulo, é necessário para compilação e desnecessário para execução.

Para declarar uma variável, sem inicializá-la (atribuir-lhe valor), usa-se:

<tipo> <identificador> ;

O operador de atribuição é

=
e é usado quando queremos atribuir valor a uma variável de tipo primitivo. Ele é lido "recebe" e não "igual" para distinguir atribuição de comparação. São exemplos de atribuição:

   a = 5  // a recebe 5
   casa = 15.4  // casa recebe 15.4
   letra = 'x'  // letra recebe xis
  

Para declarar uma variável e inicializá-la, usa-se:

<tipo> <identificador> = <literal> ;

Há um tutorial Java que explica isso em detalhes e apresenta outros exemplos de uso de variáveis.

Funcionamento dos operadores aritméticos sobre variáveis e literais numéricos

Os operadores aritméticos são:
+  // soma
-  // subtração
*  // produto
/  // divisão

A estes, em linguagens de programação acrescenta-se o operador mod, que calcula o resto da divisão inteira.

%  // mod

Todos são operadores binários, ou seja envolvem dois operandos. em algumas referências vocês vão encontrar

A <op> B //onde A e B são operandos e op é qualquer operador binário.

Apenas para satisfazer a curiosidade (este é um assunto que será abordado com mais cuidado em ach2043 e em ach2087), a definição destes operadores em linguagens de programação usa notação e regras que facilitam a construção de compiladores, e é a notação usada na especificação da linguagem. Estes operadores são apresentados no capítulo 15 seção 17.

segunda-feira, 16 de fevereiro de 2015

0.0.0.6.0 - Escopo de variáveis

O escopo de uma variável refere-se ao trecho de código mais amplo onde ela pode ser usada.

Em Java, variáveis podem ser usadas dentro do bloco de código em que foram declaradas e em seus sub-blocos (blocos declarados dentro do bloco). Referimo-nos ao escopo como o trecho mais amplo.

0.0.0.7 - Operadores lógicos e relacionais

links citados durante a aula

Especificação da linguagem Java

Operadores lógicos (bit a bit)

Nos computadores digitais atuais, podemos dizer que a representação interna dos números é binária, ou seja, números são armazenados na base 2. As operações lógicas bit a bit operam cada um dos bits dos números. São elas:


    Lista de Operadores Lógicos bit a bit
    ~   &   |   ^

A operação ~ é unária e complementa o número bit a bit. A operação & é binária e faz um E bit a bit. A operação | é binária e faz OU bit a bit. A operação ^ é binária e faz OU exclusivo (XOU, ou XOR) bit a bit - nesta operação o resultado é 1 somente se os dois operandos são diferentes.

Para entender essas operações, comecemos com números de um bit. Eles podem assumir valores zero ou um. Construiremos tabelas com todas as possibilidades de operandos de um bit.

Não E OU OU exclusivo
A ~A
0 1
1 0
A B A & B
0 0 0
0 1 0
1 0 0
1 1 1
A B A | B
0 0 0
0 1 1
1 0 1
1 1 1
A B A ^ B
0 0 0
0 1 1
1 0 1
1 1 0

Para aplicar essas operações sobre números inteiros, temos que converter os números em sua representação binária, aplicar a operação bit a bit, a partir do bit menos significativo e converter o resultado de volta para decimal. Por exemplo: 19 & 6

    2^4 2^3 2^2 2^1 2^0  
A 19 1 0 0 1 1  
B 6 0 0 1 1 0  
S   0 0 0 1 0 2

Outro exemplo: 19 | 6

    2^4 2^3 2^2 2^1 2^0  
A 19 1 0 0 1 1  
B 6 0 0 1 1 0  
S   1 0 1 1 1 23

Outro exemplo: 19 ^ 6

    2^4 2^3 2^2 2^1 2^0  
A 19 1 0 0 1 1  
B 6 0 0 1 1 0  
S   1 0 1 0 1 21

Há operadores de deslocamento bit a bit, que são listados abaixo, mas não serão apresentados agora.


    Lista de Operadores de deslocamento bit a bit
    <<   >>   >>>

Você pode perguntar por que operadores lógicos como esses são importantes. Há vários motivos, dentre eles, os componentes básicos para construção dos computadores funcionam desta forma. Conectando milhões destes componentes que construímos o microprocessador, memória, chipset,...

Operadores relacionais

Operadores relacionais são aqueles que testam uma relação, por exemplo a de igualdade, e retornam como resultado se essa relação é verdadeira ou falsa. São operadores relacionais em Java:


    Lista de Operadores Relacionais
    >   <==  <=  >=  !=
    !  &&  ||

O operador ! é unário, o restante é binário. Os da primeira linha da lista podem ser aplicados diretamente a variáveis e literais de tipo primitivo. Os da segunda linha servem para associar logicamente os da primeira, resultando em expressões mais complexas e poderosas.

12 == 12   // retorna true pois os números são iguais 
12 <= 12   // retorna true pois um números é menor ou igual a ele mesmo 
12 >= 17   // retorna false 
17 < 17   // retorna false pois um número não pode ser menor que ele mesmo 
5 > -3 // retorna true
5 != 7 // retorna true pois 5 é diferente de 7 

Os operadores da segunda linha são NÃO, E e OU relacionais. Esses operadores se aplicam exclusivamente a operandos do tipo boolean. Relembrando, em Java, o tipo boolean só pode assumir dois valores: true ou false, se fizermos a correspondência true=1 e false=0, seu funcionamento é igual ao dos operadores lógicos bit a bit correspondentes.

Talvez o que há de mais poderoso e mais compicado a respeito dos operadores relacionais acontece quando ao invés de usar literais, usamos variáveis, e os nomes (identificadores) dessas variáveis são palavras com significado para nós. As expressões lógicas resultantes dessa combinação são o cerne do que entendi que os alunos daqui chamam de lógica de programação.

Exemplo 1

"Eu digo que ehIdoso quando a idade for maior que 65 anos."

O período acima pode ser escrito como uma expressão lógica em que o resultado é armazenado em ehIdoso e os operandos são idade e 65.

boolean ehIdoso=idade > 65

Exemplo 2

"Eu digo que naoEntra quando a idade for menor que 18 anos."

O resultado é armazenado em naoEntra e os operandos são idade e 18

boolean naoEntra=idade < 18

Podemos, a partir de naoEntra, escrever entra. Eu digo que entra quando naoEntra for falso.

boolean entra= naoEntra==false

Podemos escrever a mesma coisa dizendo: Eu digo que entra quando não naoEntra.

boolean entra= !naoEntra

Exemplo 3

"Eu digo que vaiChover quando a umidade for maior que 85% e a temperatura for maior que 27C."

O período acima pode ser escrito como uma expressão lógica em que o resultado é vaiChover e os operandos são umidade temperatura, 85 e 27. Vamos separar as operações relacionais:

a umidade for maior que 85% corresponde à expressão lógica umidade > 85.

a temperatura for maior que 27C corresponde à expressão lógica temperatura > 27.

As duas operações são "conectadas" por um e, que corresponde ao operador lógico &&. Logo obtemos:

boolean vaiChover=(umidade > 85) && (temperatura > 27)

Exemplo 4

"Eu digo que ehBixo quando estiverPintado"

O resultado é ehBixo, e os operandos? Este caso é um pouco mais complicado pois há informação implícita: estiverPintado é um operando - qual é o seu tipo e o que significa? Neste caso, convém definir que estiverPintado é um boolean, que vale true quando a pessoa estiver pintada e false quando a pessoa não estiver pintada. Há duas expressões equivalentes (e pode haver outras):

boolean ehBixo = estiverPintado
boolean ehBixo = estiverPintado==true

Exemplo 5

"Eu digo que tem poucaChance quando foiAtropelado e a idade for menor que 3 ou maior que 60 anos, ou se tem cancerOsseo."

Neste caso, a expressão é mais complicada, e a precedência das operações não é clara (pois na linguagem natural não há como especificá-la). Nesta expressão, numa análise superficial, só há uma ordem para as operações que faz sentido. Vamos perceber quando tentarmos escrever a expressão lógica:

foiAtropelado é um operando e vale true se o indivíduo foi atropelado, false caso não foi atropelado.

idade menor que 3 anos corresponde a idade < 3

idade maior que 60 anos corresponde a idade > 60

As duas expressões acima são conectadas or um OU, resultando em (idade < 3) || (idade > 60)

A expressão acima é conectada à primeira por um E, resultando em foiAtropelado && ((idade < 3) || (idade > 60)).

cancerOsseo é um operando e vale true se o indivíduo tem a doença, false caso não tenha. É conectado ao restante por um OU e o resultado é atribuído a poucaChance, o que resulta em:

boolean poucaChance = cancerOsseo || (foiAtropelado && ((idade < 3) || (idade > 60)))

Exercício 1

"Eu digo que ehBixo quando estiverPintado e o cabelo estiver meioRaspado e a roupa estiver cortada."

2.6 - Sobre a avaliação

Avaliação é o momento em que o aluno mostra que aprendeu ao avaliador.

Frases vagas, mal construídas ou sem conteúdo geralmente são entendidas como tentativa de ocultar alguma lacuna no conhecimento percebida somente no momento da avaliação.

Saber escrever bem e com precisão é essencial.

0.0.0.3.1 - Tente notar os detalhes....


O teorema da programação estruturada é a base da construção da maioria das linguagens de programação. Nelas, comandos são executados na sequência (para nós) natural de leitura, um por um* a menos que o comando altere a de sequeência de execução.

A leitura de cima para baixo e da esquerda para a direita nos é tão "natural" (o que significa que fomos adestrados tão bem) que passa por um detalhe "insignificante". Tenha cuidado pois não é.

Um sub-programa equivale, em Java, a um bloco de código.
Um bloco de código é uma sequência de comandos e blocos de código delimitados por chaves. Na gramática de Java:


Block:
    { [BlockStatements] }
;

BlockStatements:
    BlockStatement {BlockStatement}
;

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement    
;

2.5 - Do papel de professor.

Talvez não seja o lugar para colocar comentários, mas aí vai:
Pessoas podem não ter claros todos os conceitos necessários para entender um novo conceito - isso atinge a todos nós.
Alunos geralmente não querem expor aos professores os conceitos que não têm claros. É um acerto caso o primeiro queria defender-se do segundo, e é um erro caso o primeiro queira aprender com o segundo. Infelizmente o papel de professor une o de mestre (o que ensina) com o de avaliador (o que julga se o aluno aprendeu), o que cria uma contradição. Colocada para o aluno na forma "expor-se ou defender-se?" e para o professor na forma "ensinar ou jugar?"

Acho que o potencial benefício educacional de atribuir a diferentes pessoas os papéis de "mestre" e de "avaliador" deve ser avaliado.

quinta-feira, 12 de fevereiro de 2015

0.0.0.2.5 - O que é compilar e executar?

A resposta curta:
  • Executar significa "entregar' o programa ao computador para que ele o execute.
  • Programas que traduzem arquivos contendo código-fonte em arquivos contendo código de máquina são compiladores.
  • (bônus) Programas que traduzem arquivos contendo código-fonte nas ações correspondentes  são interpretadores.
Caso você tenha se contentado com a resposta curta, mesmo sem entendê-la direito, TALVEZ você não goste realmente do que está aprendendo.

Os detalhes:

A questão pode ser colocada em termos de linguagens e interpretações.

Computadores são máquinas elétricas digitais. Máquinas que chaveiam eletricidade de forma que passe ou não corrente em condutores, ou haja (ou não) tensão elétrica sobre componentes. Por facilidade de implementação, apenas dois símbolos são "permitidos".

O ser humano dá a esses símbolos uma "interpretação", por exemplo passa corrente corresponde a "1", não passa corresponde a "0". Também concatena esses símbolos, por exemplo "10100111". Esta invenção tem muitos desdobramentos, o que explorarei agora é que uma linguagem composta por sequências de uns e zeros é bem diferente de qualquer linguagem que usamos (português, inglês, russo, japonês,...).

É possível treinar pessoas para ler e escrever nesta linguagem, e era o que se fazia nas décadas de 40 e 50, em que os programadores sabiam montar os circuitos que faziam o chaveamento que correspondia ao programa e o aplicava às sequências de entrada (dado), lendo e interpretando as sequências de saída (resultado). Há duas consequências que quero explorar:
  1. ao menos uma parte do programa estava nos circuitos;
  2. era parte da tarefa dos programadores configurar os circuitos;
Na época já existiam circuitos de memória e a idéia de armazenar programas em memória era explorada no campo da teoria da computação (a máquina de Turing universal é o modelo teórico de computador que explorava essa característica e foi proposta em 1936). Há disputas sobre qual seria a primeira implementação de uma máquina com programa armazenado, mas a época certamente é final da década de 40. Com isto programadores precisariam lidar "apenas" com as sequências de zeros e uns que poderiam, para facilitar, ser convertidas em números. Por convenção esta é a chamada linguagem de máquina (machine code).

Mesmo com a melhoria de não precisar recabear a máquina, programar continuava trabalhoso para todos (inclusive programadores) e massante para a maioria das pessoas pois  exigia que se lidasse com os números (em outras palavras usar a linguagem da máquina).

Pessoas são criativas e logo nos grupos de programadores surgiram formas de se escrever programas que eram mais tratáveis para seres humanos: os comandos (números) da linguagem de máquina recebiam mnemônicos que equivaliam à interpretação do que a máquina fazia quando executava o comando, por exemplo LD (load), ST (store), ADD, SUB, MUL, JMP (jump). Posições de memória que armazenavam dados recebiam rótulos. Desta forma surgiu a linguagem de montagem (assembly language).

Numa outra iniciativa, programadores começaram a codificar caracteres como números (ASCII, EBCDIC), à semelhança do que era feito em teletipos. Isso permitiu usar caracteres.

A idéia de "arquivo" já existia como hoje, embora a mídia poderia ser diferente da moderna, por exemplo fitas e cartões perfurados e discos magnéticos poderiam armazenar arquivos. (Que por sua vez poderiam ser fisicamente armazenadas em pastas :-)

A união dessas iniciativas permitiu o desenvolvimento do seguinte processo:
  1. Programa "P1" é executado no computador;
  2. Ele lê programas em assembly armazenados em arquivos, "P2" e
  3. Escreve programas em linguagem de máquina "P3".
Por sua vez o programa "P3" poderia ser executado no computador (esta é a intenção).

Por esse processo era possível escrever "P2" em uma linguagem que fosse fácil para humanos e por uma ou mais traduções, transformá-la em linguagem de máquina "P3" que poderia ser executado.

"P1" é o compilador, "P2" é o código-fonte (source code) e "P3" é o código em linguagem de máquina (machine code).

"P3" pode ser chamado "arquivo executável", ou simplesmente "executável".

Nota: À medida que computadores e programas tornaram-se mais complexos, outros passos foram acrescentados aos apresentados por exemplo não mencionou-se a existência de um sistema operacional, nem que ele "carrega" o programa armazenado em arquivo para a memória antes da execução, que é o que ocorre em computadores modernos. Os antecessores dos sistemas operacionais eram mais parecidos com o BIOS do seu computador que com UNIX ou com Windows.

0.0.0.2.4 - O que é um programa?

  • Um programa de computador, ou simplesmente programa, é uma sequência de instruções escrita para desmpenhar uma tarefa específica em um computador.[1]
  • Algoritmo (informal) é uma lista de instruções que indicam passos a ser seguidos.


[1] Stair, Ralph M., et al. (2003). Principles of Information Systems, Sixth Edition. Thomson Learning, Inc. p. 132. ISBN 0-619-06489-7. apud Wikipedia http://en.wikipedia.org/wiki/Computer_program

2.4 - Recomendação sobre escolha de nomes de arquivos e variáveis.

Lin e Win são parcialmente (in)compatíveis no que tange à codificação de caracteres. Em geral o primeiro usa UTF-8, o segundo ISO8859-1, ou ISO8859-15 ou CP-1252.

Todas essas codificações são compatíveis com a ASCII de 7 bits, que codifica caracteres romanos: minúsculas, maiúsculas, números e a maioria dos sinais de pontuação.

Caracteres acentuados e o cedilha não são compatíveis.

Pendrives usam FAT, que codifica os nomes em 8.3 sem distinção de maiúsculas e minúsculas e usa um artifício (que não pesquisei qual é) para manter os "long file names".

Na linha de comando e shell scripts caracteres com significado especial como barra, espaço, e-comercial, arroba ou não são válidos ou precisam ser "escapados". Os caracteres inválidos para Windows não são os mesmos para Linux.

Esse cenário traz problemas em potencial, como arquivos que podem ser lidos em um SO mas não no outro, tentativas (automáticas) de "reparo" que acabam por "quebrar" os nomes para todos os SO, avisos "falsos" de que "há um problema nesta unidade", ...

Em meio a isto, há programadores que tentam armazenar informação demais nos nomes dos arquivos, por exemplo nome completo separado por espaços, número usp entre parêntesis, número da turma, ou o nome completo de palestra, palestrante data de exibição, ... construindo um nome longuíssimo.

A informação pode ser útil e facilitar o trabalho de quem lê o nome, mas aumenta a chance de problemas e dificulta escrever programas (principalmente shell scripts).

Caso queira previnir-se de "dores de cabeça" associadas a problemas com codificação de caracteres, fique nas maiúsculas, minúsculas e números. Traço (subtração) e underscore também são seguros. Evite espaços, sinais de pontuação e caracteres especiais.

Para considerações sobre nomes de variáveis, veja o post sobre "que editor de texto usar".

Lembre que em Java o nome do arquivo tem que coincidir com o nome da classe que contém, se esta for pública.

2.3 - Que editor de texto?

No Linux, qualquer um não formatador, por exemplo vi, nano, emacs, gedit, bluefish,...
No Windows, sugiro Notepad++ (que não é nem o Notepad nem o WordPad).

Frase de efeito: A questão é a que atormenta o mundo dos desenvolvedores desde que a IBM é a IBM: codificação de caracteres e formato de arquivos texto.

  • A codificação de caracteres mais usada atualmente é UTF-8. Nela caracteres são codificados em números de comprimento variável (um, dois, três ou quatro bytes) - o suficiente para representar qualquer caracter de qualquer alfabeto do mundo.
  • Windows distribuído no Brasil usa ou CP-1252 ou ISO8859-1 ou ISO8859-15, que são os code pages para alfabetos latinos. São codificações de tamanho fixo (1 byte) em que os primeiros 127 códigos são iguais ao UTF-8 e iguais à tabela ASCII.
  • Há editores de texto no Windows que permitem salvar em UTF-8, mas alguns destes seguem a orientação da MS para arquivos neste formato ao invés de seguir a orientaçao do consórcio unicode (que é a entidade que regula essa codificação, diga-se de passagem). Pela orientação da MS, arquivos UTF-8 devem ter o marcador de ordem de bytes (BOM) - são três bytes indicando que o arquivo é UTF-8. Pela orientação do consórcio unicode, esse marcador deve ser omitido.
  • javac (o compilador java) assume que o arquivo-fonte é codificado em UTF-8 do consórcio unicode, independente da plataforma.

Vamos à combinatória:
Escrever arquivos em windows com CP-1252 ou ISO... usando só os 127 primeiros caracteres (alfabeto romano, minúsculas, maiúsculas, números e boa parte dos sinais de pontuação, sem caracteres acentuados nem cedilha) vai ser editado (quase* da mesma forma) em Win e Lin e não haverá problemas de codificação de caracteres em nenhum JDK.

Usar caracteres acentuados APENAS nos comentários e mensagens e manter o restante inalterado só vai atrapalhar na impressão das mensagens. A compilação e execução são normais com o uso de -encoding ISO8859-1.

Usar caracteres acentuados nos nomes de variáveis e manter o restante como no caso 1 causa erro de compilação.

Escrever arquivos em windows com UTF-8 sem BOM. Compila e executa sem problemas.

Escrever arquivos em windows com UTF-8 com BOM. Causa erro de compilação. O arquivo pode ser ajustado convertendo com Notepad++ ou editando o arquivo em modo binário e removendo o BOM.

quase* pois Windows codifica quebra de linha com \10\13 e UNIX com \10. Arquivos escritos num editor UNIX aparecerão em uma única linha no Notepad. Outros editores como WordPad e Word reconhecerão o arquivo e o exibirão corretamente.




2.2 - Que ambiente de desenvolvimento usar?

Ambientes de desenvolvimento fazem muita coisa pelo programador e de fato agilizam o desenvolvimento, mas isso tem custo: o desenvolvedor geralmente perde a noção de todos as etapas de desenvolvimento, inclusive "desaprendendo" a escrever código. Para um iniciante, que nem tem noção de que etapas são essas, usar um ambiente de desenvolvimento deforma seu conhecimento (o que considero ruim, mas alguém por aí pode dizer que tem vantagem...).

Caso você queira conhecer todo o processo de desenvolvimento, ou queira ter controle do processo para fazer programas num certo sentido inovadores, use editor de texto, terminal e um emulador da plataforma-alvo (por exemplo se estiver desenvolvendo para celulares Android).

Caso você seja aluno de ACH2001, editor de texto e terminal, sem dúvida. Você deve aprender todo o processo por seu futuro profissional.

Caso você não esteja nessas categorias, nada contra Eclipse (embora vocês já devam ter adivinhado minha preferência pessoal).

Termino com "causos":

Pela praticidade de usar um debugger on line, tanto DrJava quanto Eclipse tem sua própria implementação do JDK.

Em conversa com colegas, soube que DrJava é capaz de executar códigos incompletos que sequer compilariam no JDK da Oracle.

Na passagem do JDK 4 para o 5, a especificação passou a prever "comandos" informativos como @override. Isso foi implementado no Eclipse antes de sê-lo no JDK. Seria sem efeito, mas o editor Eclipse acrescentava @override automaticamente ao código, o que causava erro de compilação.

2.1 - Linux ou Windows?

Eles são iguais em funcionalidade e potencial (são capazes de usar todos os recursos da máquina), mas não é só isso que conta.
Na época em que foram concebidos com os respectivos ambientes gráficos, eram muito parecidos, mas o modelo de negócio era (e continua sendo) muito diferente.

A Microsoft sempre foi uma empresa que claramente visa o lucro (não considero isso imoral). Desenvolveu partes de seus produtos, terceirizou outras, cresceu, tornou-se rica e gigante. Direcionou seus esforços para atender o público mais numeroso - o de usuários "finais" que navegam na internet, escrevem memorandos, controlam finanças em planilhas, não querem conhecer detalhes da máquina. Dão muito valor à estética e pouco valor ao desempenho computacional.

O público do Linux inicialmente eram os desenvolvedores e acadêmicos, os valores eram outros - aderência a uma especificação (UNIX), desempenho, popularização da informática, conseguir aproveitar máquinas baratas, já havia ideais: Software Livre (hoje é realidade), projetos com equipes espalhadas pelo mundo,... A sobrevivência da iniciativa depende de quão bem o software é escrito e documentado.

Os dois casos são muito bem sucedidos - cumprem seus objetivos e resultaram em produtos substancialmente diferentes.

Atualmente há muitos programas que foram (trans)portados de Linux para Windows e vice-versa, assim como há emuladores de Windows para Linux (wine), mas executar MS-Office no wine não é o mesmo que no Win, usar gcc no Win (Min-GW) não é o mesmo que gcc nativo. O banco de dados da Oracle tem versões para Windows e para Linux, assim como PostgreSQL, PHP, MySQL, Matlab, R,... geralmente usar no SO nativo é melhor.

A MS não fez uma versão de .Net ou de Office para Linux...

Que eu saiba, não existe supercomputador baseado em Windows...

No frigir dos ovos, "levantar" um servidor de arquivos ou web, ou um supercomputador usando Linux tem custo de licenciamento zero e funciona "suave" (smooth). Fazer o mesmo, com a mesma "suavidade" com Windows custa caro....

Resposta para a pergunta: Como "usuário final", Windows, como desenvolvedor, Linux.


0.2.0.1 - Máquina Virtual (VMWare Player)

A Máquina Virtual é um programa que emula um computador "virgem" dentro de um computador já com Windows ou Linux instalado e funcionando. Você instala um novo sistema operacional dentro dela. O sistema operacional do computador é o host, o da Máquina Virtual é o guest.

Você pode perguntar por que fiz isso - tenho motivos que acredito que sejam bons, também tenho um histórico extenso sobre o uso que tenho feito. Aqui restringir-me-ei a dar um guia de instalação do programa que escolhi: o VMWare Player.

Instalei Linux (Lubuntu 14.04) dentro do Windows 8.1, para isso:

  1. Baixe a imagem do CD/DVD de instalação do Linux que quiser (usei o Live CD do Lubuntu em formato .iso)
  2. Baixe e instale o Player em https://my.vmware.com/web/vmware/free#desktop_end_user_computing/vmware_player/7_0
    Execute o Player;
  3. Clique em "Criar nova Máquina Virtual" - dê ao menos 10GB de disco e 1GB de memória para a nova máquina;
  4. Informe que quer instalar o conteúdo do arquivo .iso do Linux (a situação é análoga a pegar um computador e iniciá-lo com um CD de boot;
  5. Ele executa o instalador do Linux, diga para instalar o sistema operacional - siga as instruções que o instalador dá.

O guest não compartilha nenhum arquivo com o host, logo copiar um arquivo do host para o guest ou vice-versa requer mandar por email para si mesmo, ou copiar num pendrive e conectá-lo ao host e ao guest. Dá trabalho.

Para compartilhar uma pasta, use VMWare tools, que é uma imagem .iso e é montada no guest como um CD.

  1. Instale gcc no guest (o compartilhamento é compilado no kernel, o que requer gcc) usando sudo apt-get install gcc;
  2. Instale no guest uns headers do kernel também necessários para compilá-lo:
  3.  sudo apt-get install build-essential linux-headers-$(uname -r)
  4. Crie no host uma pasta para compartilhar com o guest;
  5. Instale (ou reinstale) o VMWare tools pelo menu Player - Manage - Reinstall VMWare Tools;
  6. Habilite o compartilhamento pelo menu Player - Manage - Virtual Machine Settings - Options - Shared Folders. No meu caso apontei para a pasta \\ULTRALEVE\Users\Fabio\Documents\Notas\Shared e o link no guest foi montado em /mnt/hgfs/Shared.

Notas extras:

Testei movendo do guest um tex, compilando no host e abrindo o pdf no guest, depois editei e salvei no guest e editei e voltei no host. Os arquivos resultantes da compilação foram armazenados em Shared e são visíveis, embora a atualização da visualização no guest tenha que ser manual.

Testei executar um shell script e funcionou!!

Testei compilar e executar um hello.c e funcionou!! (esta é inesperada pois quando tentei fazer esse teste num pendrive o Ubuntu não executou. Entendi que era por causa do sistema de arquivos pois FAT32 não tem flag de permissões, por padrão, arquivos em pendrive não são executáveis, mesmo que tenham sido criados para isso. Neste caso o sistema de arquivos é o do Windows (NTFS) e não tem o mesmo flag de permissões do sistema de arquivos do Ubuntu (ext4). Eu esperava que não funcionasse) Funciona porque na falta do flag, as permissões são dadas para tudo:  todos são rwx. É o que dá para fazer... A mim ajuda, embora tenha resolvido usar esse espaço apenas para transferir arquivos e não para ter uma área de trabalho compartilhada.

Outra surpresa: caso o arquivo esteja aberto no host, o guest não o apaga - ele diz "permission denied", ou seja o flag de arquivo em uso passa do host para o guest.

Referencias:
file:///C:/Program%20Files%20(x86)/VMware/VMware%20Player/help/player/wwhelp/wwhimpl/js/html/wwhelp.htm#href=GUID-08BB9465-D40A-4E16-9E15-8C016CC8166F.html#1_24_9_8_1
http://superuser.com/questions/511679/getting-an-error-trying-to-set-up-shared-folders-on-an-ubuntu-instance-of-vmware
https://smyl.es/vmware-workstation-shared-folders-between-windows-and-ubuntu-debian-error-mounting/
http://askubuntu.com/questions/471361/shared-folders-vmware

2 - Minhas opiniões

Neste ramo expressarei minhas opiniões pessoais. É possível que discorde da opinião de colegas e, (espero que bem raramente) discorde de regulamentos.

Os formatos podem variar: relatos, dissertações, perguntas e respostas,...

Caso o que for escrito seja ofensivo, por favor informe paqra que possa ser ajustado ou retirado.

1 - O que não esperar do que está escrito aqui.

Que TODOS os argumentos e análises sejam (perfeitamente) amplos e imparciais (idéias sem viés) na realidade, duvido que isso exista, mesmo que seja posto como objetivo.

O que considero factível é ser suficientemente amplo e imparcial (quando desejado), onde a medida de suficiência depende de quem lê.

Este blog é resultado de um estudo guiado, com o objetivo de fornecer explicações (motivos), é de se esperar que mesmo sem intenção, alguns trechos serão bem sofistas (no mau sentido).

Quer não se sentir manipulado? Saiba tudo e tenha seu próprio ponto de vista para tudo (isto não é nada fácil, principalmente se quiser manter coerência entre seus pontos de vista).

0.2.0.0 - Java


  1. Baixar o JDK e executar o download de http://www.oracle.com/technetwork/java/javase/downloads/index.html ou de java.com (mais de 100MB).
  2. Teste se java está corretamente instalado:
    1. Supondo que você instalou o jdk1.8.0_05 (ou java 8 release 0_05) na pasta (diretório) \Program Files\Java\jdk1.8.0_05, (procure pela pasta Java em Program Files ou em Program Files (x86)) encontre os arquivos javac.exe, java.exe e javadoc.exe
    2. Abra  um prompt de comando;
    3. Digite java <ENTER> deve aparecer o modo de usar o java.
    4. Digite "\Program Files\Java\jdk1.8.0_05\bin\javac" <ENTER> deve aparecer o modo de usar javac.
    5. Digite "\Program Files\Java\jdk1.8.0_05\bin\javadoc" <ENTER> deve aparecer o modo de usar javadoc.
  3. Confirme que PATH não está ajustado, digitando javac <ENTER> no prompt de comando - o windows deve escrever algo como "javac comando ou programa desconhecido". Caso escreva a forma de usar javac então o JDK está instalado, salte para o passo 8 para completá-lo;
  4. Abra o painel de controle e selecione Sistema e Segurança;
  5. Selecione Sistema; 
  6. Selecione Configurações Avançadas de Sistema;
  7. Selecione Variáveis de Ambiente;
  8. Selecione e edite a variável de ambiente PATH: acrescente o caminho para javac - no exemplo:    ;"\Program Files\Java\jdk1.8.0_05\bin"
  9. Feche o prompt de comando e abra um novo para que as modificações tenham efeito;
  10. Verifique que o JDK está instalado digitando javac <ENTER>; java <ENTER> e javadoc <ENTER> - cada um deve exibir o seu modo de usar. Caso isso não aconteça, provavelmente PATH não está ajustada corretamente.

Referência: http://javarevisited.blogspot.com.br/2013/02/windows-8-set-path-and-classpath-java-windows-7.html