sábado, 30 de julho de 2011

Conjunto de Notas Usadas para a Certificação OCPJP 6 (1Z0-851)

Deixo aqui um conjunto de notas que poderão vir a ser úteis para quem vier a tirar a certificação OCPJP6 - Oracle Certified Professional Java Programmer 6 (exame 1Z0-851). Esta certificação era conhecida como SCJP6.


Estas notas não são exaustivas e não são o suficiente para passar o exame. Há que estudar bastante para lá chegar. Obviamente que os que programam em Java à bastante tempo estão em significativa vantagem para fazer o exame.

Alguns pontos são básicos, outros mais complexos, mas todos servem para reforçar alguns aspectos que na utilização diária passam despercebidos. Parte dos títulos das notas estão em inglês pois são de uso comum na comunidade e não faz sentido traduzir as mesmas, pois o exame é em inglês.

Antes de mais recomendo vivamente o livro SCJP Sun Certified Programmer for Java 6 Study Guide
que serve tanto para a certificação OCPJP6 como para a OCMJ6D - Oracle Certified Master, Java SE 6 Developer (ex-SCJD6).

E sem mais demoras as notas de estudo.



Identificadores legais:
  • todos os começados por letras
  • $ (dólar)
  • _ (sublinhado)
Palavras reservadas:
  • const
  • goto
  • native
  • strictfp
  • assert
  • enum
  • há mais...
strictfp: Pode ser usada numa classe ou método. Se uma classe for marcada como strictfp, então qualquer método na classe irá ser conforme as regras do standard IEEE 754 para vírgulas flutuantes e respectivas operações. Se não for usado, então as vírgulas flutuantes e respectivas operações são dependentes da plataforma. Pode-se marcar apenas um método como sendo strictfp.

native: apenas pode ser aplicado a métodos, e a sua declaração é semelhante a um método abstract.

Não há conflitos possíveis entre:
  • Nomes de classes
  • Type parameter placeholders
  • Identificadores de variáveis

JavaBeans property naming rules:
  • As assinaturas dos métodos setter têm de ser  
    • public
    • retornar void
    • ter um argumento que representa o tipo da propriedade
  • As assinaturas dos métodos getter têm de ser
    • public
    • não têm argumentos de entrada
    • tipo de retorno igual ao tipo de argumento do método setter para essa propriedade
JavaBeans listener naming rules:
  • Os nomes dos métodos dos listeners usados para "registar" um listener com uma fonte de evento tem de usar o prefixo add, seguido do tipo de listener [ex: addActionListener(ActionListener al)]
  • As regas para remover ("desregistar") são iguais ás do add excepto que o prefixo é remove [ex: removeMyListener(MyListener m)]
  • O tipo de listener a adicionar ou remover tem de ser passado como argumento do método
  • Os nomes dos métodos do listener têm de terminar com a palavra "Listener"
Source file declaration rules:
  • Pode haver apenas uma classe pública no ficheiro fonte
  • Pode haver mais do que uma classe não pública num ficheiro fonte
  • Num ficheiro sem classes públicas, o nome do ficheiro pode ser diferente de quaisquer classes nele contidas
Modificadores de acesso (visibilidade)



Qualquer classe no mesmo pacote

Qualquer classe (não subclasse) fora do pacote

Própria classe

Subclasse no mesmo pacote

Subclasse pacote diferente
* Através de herança
default OK NA OK OK NA
public OK OK OK OK OK
private NA NA OK NA NA
protected OK NA OK OK OK (*)

O modificador de acesso protected tem um efeito nas classes que pertençam a pacotes diferentes da superclasse, que é estes serem visíveis apenas através de herança. Isto é, se uma subclasse que esteja num pacote diferente da superclasse instanciar a superclasse e através desta referência tentar aceder a um membro protected, irá surgir um erro de compilação.


Declaração de Interfaces:

Todos os métodos declarados numa interface são automaticamente:
  • public
  • abstract
e estes modificadores podem ser omitidos total ou parcialmente. Só estes são permitidos!

Todas as variáveis definidas numa interface têm de ser:
  • public
  • static
  • final
ou seja, apenas é permitida a declaração de constantes. Não é preciso usar os modificadores. Podem ser omitidos ou usados intercaladamente.

Encapsulation:
  • Protecção dos dados (com modificadores de acesso)
  • Proteger as variáveis de instância
  • Assessores públicos ao invés de acesso directo a variáveis de instância (usando a metodologia dos Javabeans)

Variable argument list (var-args)

Usotipo... variável

Só pode existir um var-arg na assinatura de um método e o var-arg tem de ser o último parâmetro.

Intervalos para os primitivos

Regra geral para intervalos

     Positivos: 2(nº bits -1) - 1
     Negativos: -2 (nº bits -1)



Tipo

Bits

Intervalo Menor

Intervalo Maior
byte8-2727 - 1
short16-215215 - 1
int32-231231 - 1
long64-263253 - 1
float32NANA
double64NANA
char16NA216 - 1 (sem sinal)

O tipo char é representado em Unicode. Pode-se indicar o valor do carácter directamente em unicode. ex: \uxxxx ao invés de representar o carácter directamente. Cada carácter numa String é representado como um char.

O tipo double é a representação por defeito para números de vírgula flutuante. Podem opcionalmente ser terminados em D ou d.

O tipo float tem de ter F ou f na terminação.

Um literal inteiro é sempre um int implicitamente

O resultado de uma expressão envolvendo qualquer coisa do tamanho int ou inferior é sempre int. Por exemplo: a soma de dois byte é sempre um int.

Modificadores possíveis em variáveis e métodos

Variáveis Locais e Method Local Inner Classes Variáveis Não Locais Métodos e Inner Classes

1- Não aplicável a Inner Classes
2 - Só aplicável a Method Local Inner Classes
final










abstract 2




final
public
protected
static
transient
volatile 








 
final
public
protected
private
static1





abstract
synchronized1
strictfp
native1

Ao contrário das variáveis não locais, as variáveis locais não têm inicializações por defeito.

A inicialização de uma variável final tem de ocorrer antes do construtor(es) terminar(em).

Declaração de Arrays

Constituição de um array:

int[] xpto      =      new int[4]           {1, 2, 3, 4}      ;
_______              __________       __________
Declaração           Construção          Inicialização

Regras gerais:
  • Na parte da construção é obrigatório indicar o tamanho do array se não existir a parte da inicialização; se tiver inicialização então é opcional
  • A parte parte da construção pode ser omitida se a inicialização vier no mesmo statement
Num array multidimensional apenas é obrigatório indicar na parte da construção o tamanho da primeira dimensão, caso não haja inicialização.

Os [] podem estar intercalados com o identificador.
O tamanho do array apenas pode ser declarado na inicialização do mesmo, isto é, à direita do =.

Ex:  int[] array = new int[10];



Declaração de enumerados

enum xpto {X, Y, Z};

Só podem ser declarados:
  • na sua própria classe 
  • como um membro da classe 
  • tal como uma classe dentro de um ficheiro de uma classe pública
Os enum não podem ser declarados dentro de métodos!

Tal como numa não inner classe (quando o enum é declarado como tal), apenas se pode aplicar os modificadores:
  • public
  • default
Se mais nenhuma declaração se seguir ao enum, então o ; (ponto e vírgula) é opcional.

A ordem pela qual os valores no enum são declarados conta! Isto porque o método values() presente em todos os enums, retorna um array do tipo do enum com os valores pela ordem da declaração.

Num enum é possível fazer override a métodos do próprio enum.

Exemplo:


enum Xpto{
   A(1),
   B(2){
      // Este bloco denomina-se: Constant Specific Class Body
      public String getXptoza(){
         return "ABC";
      }
   };

   Xpto(int i){


      this.i = i;
   }
    
   private int i;
   
   public String getXptoza(){

      return "Z";
   }
}


Uma classe que implemente uma interface:
  • Não pode declarar novas checked exceptions para os métodos implementados
  • Não pode declarar excepções que são mais abrangentes que as excepções declaradas no método da interface
  • Pode declarar Runtime Exceptions em qualquer método da interface independentemente da declaração da interface
  • Não é obrigatório declarar todas as excepções da interface (pode mesmo não declarar nenhuma)
IS-A: Passa o teste do instanceof (uso de implements e extends)
HAS-A: Baseado no uso e não na herança. Ou seja, uma classe has-a outra se o código da primeira classe tiver uma referência para uma instância da segunda.

Herança, Overriding, Overloading  e Polimorfismo

Invocação de métodos polimórficos aplica-se apenas a métodos de instância overrriden! Apenas métodos de instância overriden são invocados dinamicamente baseados no tipo real de objecto.

A escolha de qual método overloaded invocar não é decidida dinamicamente em runtime. O tipo de referência (não o tipo de objecto) determina o método overloaded que é invocado.

O compilador apenas "olha" para o tipo de referência e não ao tipo de instância.

Os métodos abstract, quando concretizados pelas subclasses, são sempre do tipo override.

Os métodos static não podem ser overriden!

As variáveis de instância também podem ser overrided.

Resumindo:
  • overriding: decidido em runtime baseado no tipo de objecto
  • overloading: baseado no tipo de referência do argumento passado em tempo de compilação
Escolha de métodos overloaded


Não esquecer: O código tem de ser retro-compatível sempre! Por isso comportamentos anteriores são sempre preferidos!
  • widening é preferido sobre o boxing
  • widening é preferido sobre var-args
  • boxing é preferido sobre var-args
  • var-args é sempre o último recurso 
    Regras de overriding

    Regras para o método que está a fazer o override em relação ao método overriden:
    • Modificador de acesso
      • Não pode ter um modificador de acesso mais restritivo
      • Pode ter um modificador menos restritivo
    • Retorno
      • O tipo de retorno tem de ser o mesmo, ou um subtipo do tipo declarado
    • Excepções (em relação às excepções declaradas na assinatura do método overriden)
      • Pode lançar quaisquer excepções não checadas (que estendam RuntimeException)
      • Não pode atirar novas excepções checked
      • Não pode atirar excepções que sejam mais abrangentes
      • Pode atirar excepções que sejam subclasses
      •  Pode lançar (declarar) menos ou nenhuma excepção
    Casting
    • upcasting - o cast é implícito, é opcional fazer o cast
    • downcasting - o cast é obrigatório. É verificado apenas se o cast é possível, isto é, se os tipos estão na árvore de herança. Se não estiverem na árvore de herança dá erro de compilação.
    Implementação de interfaces
    • Seguir todas as regras para os overrides legais
    Uma interface pode estender outras (uma ou mais ao mesmo tempo).

    extends tem de preceder implements caso uma classe use os dois.

    Se uma superclasse implementar uma interface, e se uma subclasse indicar explicitamente que também implementa a mesma interface, a subclasse não tem de voltar a implementar os métodos da interface, quando a superclasse já o fez. Não faz mal voltar a tornar explícito a indicação de implementação da interface.

    Regras para construtores
    • Pode existir um método com o mesmo nome da classe, mas este não ser um construtor (basta retornar algo)
    • O construtor por defeito e sem argumentos apenas é automaticamente criado pelo compilador, se nenhum outro construtor for declarado
    • A chamada a outro construtor ou a um construtor da superclasse é o primeiro statement (a primeira instrução) de cada construtor. O compilador pode inserir a chamada a super() caso não exista nenhuma chamada a outro construtor
    • Não pode ser efectuada nenhuma chamada a métodos de instância ou acesso a variáveis de instância até depois do super construtor ter corrido (o construtor da superclasse). (Daí a chamada a outros construtores ter de estar na primeira linha)
    • O uso de variáveis estáticas e métodos estáticos é permitido na chamada a outros construtores da classe
    • As classes abstract têm construtores que são sempre chamados quando uma subclasse concreta é instanciada
    • Um construtor apenas pode ser invocado dentro de outro
    • Os construtores não são herdados!
    • Os construtores não podem ser marcados como:
      • static
      • final
      • abstract
    Construtor default
    • Tem o mesmo modificador de acesso da classe
    • Incluí ele próprio uma chamada a super()
    O compilador dará erro se uma subclasse tiver um construtor onde ele tenha de colocar uma chamada implícita a super() e a superclasse não tiver um construtor sem argumentos. Neste caso  a chamada tem de ser feita à mão, colocando a chamada ao construtor da superclasse com argumentos.

    static e o compilador


    No acesso a coisas static, o compilador apenas tem em atenção o tipo declarado da variável que está a aceder ao static, ou seja, é independente da variável de instância (o que conta é o tipo da variável de referência e não o tipo de objecto).     

    Coupling e Cohesion

    Coupling - Até que ponto uma classe está ligada às demais. Ou seja, até que ponto alterações numa classe afectam outras.
    Cohesion - Como é que uma dada classe é desenhada. Até que ponto uma classe tem um único e bem focado propósito.

    Heap e Stack

    Heap Onde estão as variáveis de instância e os objectos.
    Stack - Onde estão as variáveis locais.

    Números octais, decimais e hexadecimais


    Números octais Todos os números inteiros começados por 0 (zero) podem ter até 21 dígitos.
    Números hexadecimais - Todos os números começados por 0x (zero x). Podem ter até 16 dígitos (a representação das letras não é case sensitive).

    Por defeito, os números em octal, decimal, ou hexadecimal são ints, a não ser que sejam terminados por L ou l (L minúsculo) sendo então longs.

    Narrowing e Widening

    Sendo Maior e Menor tipos de dados :

    Maior  ------------ Narrowing (cast obrigatório) ----------------- > Menor
    Maior  <-----------Widening (cast opcional. é implícito) ---------- Menor

    "Escala":

    double > float > long > int > short > byte


    Existe o caso especial do char. Uma vez que o char é um inteiro sem sinal de 16 bits só é possível fazer widening a partir de int. Todo e qualquer cast de outro tipo de dados numérico (double, float, long, int, short ou byte) para char é sempre narrowing. Detalhes completos disponíveis na especificação.

    Os operadores de atribuição compostos (+=, -=, *=, /=) colocam automaticamente um cast, não sendo necessário, por isso, escrevê-lo.


    Valores por defeito de variáveis não locais atribuídos pelo compilador
    • Referência para objecto: null
    • byte, short, int, long: 0 (zero)
    • float, double: 0 (zero)
    • boolean: false
    • char: '\u0000' (u seguido de zeros)
    Se uma referência de array for construída mas não for inicializada dentro do array serão colocados os mesmos valores que o tipo dos valores têm na inicialização por defeito. Isto é verdade quer para variáveis locais ou de instância.

    Todas as variáveis locais têm de ser inicializadas antes de serem usadas. Caso não sejam usadas não é obrigatório inicializadas.

    Arrays

    Arrays são sempre objectos!

    Blocos de inicialização
    • Estáticos
    • de Instância - correm imediatamente depois de todos os super construtores terem corrido. Correm pela ordem que aparecem no ficheiro fonte
    Classes wrapper

    As classes wrapper (de tipos primitivos como por exemplo Integer) tal como a classe String são imutáveis. O seu valor depois de atribuído não pode ser alterado.

    Exceptuando a classe Character cujo construtor apenas recebe um char, todos os outros construtores das outras classes wrapper podem receber uma String ou o tipo que fazem wrap.

    A partir do Java 5, o objecto Boolean pode ser usado num teste booleano.

    Criação de objectos wrapper:
    • Usando um construtor
    • Usando o método estático valueOf() [tomar em atenção que a classe Character não tem este método]
    Conversão de um numérico wrapped para um primitivo (Character e Boolean não têm):
    • xxxValue()
    • parseXxx() [estático]
    Apenas os inteiros podem ter radix.


     Boolean Byte  Character  Double  Float    Integer  Long  Short
    xxxValue
    X
    X X X X X
    parseXxx
    X
    X X X X X
    parseXxx
    com radix

    X


    X X X
    valueOf X X
    X X X X X
    valueOf
    com radix

    X


    X X X
    toString(primitivo) X X X X X X X X
    toString(primitivo)
    com radix





    X X
    toXxxString
    Octal, hex ou bin





    X X

    Para o exame é necessário saber bem estes métodos, em que classes existem, etc.

    Boxing e Autoboxing

    Ao invés de se ter de:
    • criar o wrapper
    • tirar o primitivo de dentro do wrapper
    • usar o primitivo
    • voltar a criar um wrapper
    Pode-se usar o objecto como primitivo que a VM trata do resto.

    No caso dos operadores != e ==, a comparação entre um primitivo e um objecto wrapped é feita do seguinte modo:
    • Os objectos são unwrapped e a comparação será primitivo a primitivo
    Duas instâncias dos seguintes objectos wrapper (criadas através de boxing), serão sempre iguais (comparação com o operador ==) quando os seus primitivos forem do mesmo valor:
    • Boolean
    • Byte
    • Character -> de \u0000 (0) a \u007F (127)
    • Short -> de -128 a 127
    • Integer  -> de -128 a 127 

    O Boxing e o unboxing funcionam, de um modo geral, nos mesmos locais onde normalmente se usam primitivos ou um objecto wrapped.

    As classes wrapper não podem fazer widden umas para as outras.

    O que é e não é permitido (no boxing e widening):
    • widden seguido de box não é permitido
    • box seguido de widen é permitido
    Garbage Collector (GC)

    O Garbage Collector (GC) limpa apenas a heap (no que ao exame diz respeito).

    Método finalize()
    • Para qualquer objecto, finalize() será apenas chamado uma e uma só vez no máximo pelo GC
    • Chamar o método finalize() pode fazer com que o objecto não seja apagado
    • Poderá nunca ser executado
    Operadores

    Nos operadores compostos (+=, -=, *=, /=) a expressão à direita tem sempre precedência.

    Na comparação entre um carácter com outro  ou com um numérico é usado o valor unicode do carácter como valor numérico.

    Com os operadores == ou != apenas de pode comparar tipos compatíveis.

    Nos enum == ou equals() dão o mesmo resultado.

    instanceof não pode ser usado para testar duas classes hierárquicas diferentes (dá erro de compilação).

    Operador condicional :  

    variável = (expressão_booleana) ? valor_a_atribuir_ se_Verdade : valor_a_atribuir_se_Falso;

    && - short-circuit AND                                    & - non-short-circuit AND
    !!     - short-circuit OR                                    |   - non-short-circuit OR



    Switch


    switch (expression) {
         case constant1: code block
         case constant1: code block
         default: code block
    }

    Uma expressão (expression) no switch tem de ser avaliada como: char, byte, short, int ou enum, ou seja, apenas enums e variáveis que possam implicitamente ser promovidas a int podem ser usadas!

    A constante do case tem de ser avaliada tal qual a expressão (expression) do switch e ainda tem de ser uma constante em tempo de compilação!

    default case pode vir em qualquer posição do case.

    Ciclo for

    No ciclo for todas as partes da declaração são opcionais.

    Na parte da inicialização todas as variáveis têm de ser do mesmo tipo. Na parte da condição o resultado tem de ser booleano. Na parte do incremento qualquer statement é válido!

    No uso de continue e break com labels, ambos têm de estar dentro do loop que tem o mesmo nome da label. Caso contrário código não compila.

    Assertions

    Quando se usa assertions presume-se sempre que algo (o que se testa) é verdadeiro. Caso não seja uma AssertionError é lançada.
    • assert (boolean_expression);
    • assert (boolean_expression) : expressão_que_retorna_um_valor
    A parte expressão_que_retorna_um_valor é impressa apenas se uma AssertionError for lançada.

    assert só pode ser usado como identificador se o código for compilado com a opção: -source 1.3

    A opção de runtime -ea ou -enableassertions activa as assertions.

    Apeser de por defeito as assertions estarem desligadas, as opções de runtime -da ou -disableassertions inactivam as assertions também.

    A opção -dsa desliga as assertions para as classes de sistema.

    Pode-se combinar as opções de ligar e desligar assertions.


    Pode-se ligar/desligar as assertions do seguinte modo:
    • sem argumentos -> Todas as classes excepto as de sistema
    • com nome de pacote -> Todas as classes do pacote indicado e também, subpacotes
    • nome da classe -> Classe indicada
    Exemplo: -ea:pt.xpto.pacote

    Mais informação em:


    Excepções

    Unchecked Exceptions 
    • RuntimeException (e subclasses)
    • Error (e subclasses)

    Excepção Descrição Normalmente Lançada Por
    IllegalStateExceptionAtirada quando o estado do ambiente não corresponde à operação que se está a tentarProgramaticamente
    ExceptionInInitializerErrorAtirada quando se tenta inicializar uma variável ou bloco de inicialização estáticoJVM


    String Constant Pool

    Zona de memória onde são guardadas as Strings pela JVM. Se uma dada String já existir, a JVM apenas coloca uma referência extra para a String, e um novo objecto não é criado.


    Métodos mais importantes na classe String

    É imprescindível para o exame saber de cor vários métodos em várias classes. Não há consulta disponível por isso tem de se decorar a API.
    • char charAt(int)
    • String concat (String)
    • String replace(char o, char n)
    • String toLowerCase()
    • String toUpperCase()
    • String trim()
    • boolean equalsIgnoreCase(String)
    • int length()
    • String substring(int)
    • String substring(int b, int e) - O e é exclusive
    • Strint toString()
    Não esquecer: Arrays têm a propriedade length pública para leitura. Nas Strings só por acesso ao método length()!

    Métodos mais importantes na classe StringBuilder e StringBuffer
    • StringXxx append(...)
    • StringXxx delete(int s, int e) - O e é exclusive
    • StringXxx insert(int o, ...)
    • StringXxx reverse()
    • String toString()
    • boolean equals(Object) - Não compara os valores pois não é overriden!
    Java io


    Métodos principais na classe java.io.File

    Um objecto do tipo File pode representar ou um ficheiro ou uma directoria.
    O construtor da classe File não cria o ficheiro/directoria fisicamente. Apenas cria o nome do ficheiro/directoria.
    • File(File, String)
    • File(String, String)
    • File(String)
    • boolean createNewFile() - cria um ficheiro se ainda não existir
    • boolean mkdir() - cria a directoria se ainda não existir
    • boolean isFile()
    • boolean isDirectory()
    • boolean exists()
    • boolean delete() - não apaga uma directoria se esta não estiver vazia
    • String[] list()
    • boolean renameTo(File)
    Métodos principais na classe java.io.FileWriter
    • FileWriter(File) -> Cria o ficheiro fisicamente
    • FileWriter(String) -> Cria o ficheiro fisicamente
    • close()
    • write(...)
    • flush()
    Métodos principais na classe java.io.BufferedWriter

    • BufferedWriter(Writer)
    • close()
    • newLine()
    • flush()
    • write(...)
    Métodos principais na classe java.io.PrintWriter
    • PrintWriter(File)
    • PrintWriter(String)
    • PrintWriter(OutputStream)
    • PrintWriter(Writer)
    • flush()
    • close()
    • format(...)
    • write(...)
    • print(...)
    • printf(...)
    • println(...)
    • append(...)

    Nota : Só o mkdir() cria a directoria. Ao contrário do que ocorre com os ficheiros, as directorias não são criadas automaticamente pelos Writers (dá excepção).

    Métodos principais da classe java.io.FileReader
    • FileReader(File)
    • FileReader(String)
    • int read(char[])
    Métodos principais na classe java.io.BufferedReader
    • BufferedReader(Reader)
    • String readLine()
    • read()
    Métodos principais da classe java.io.Console
    • String readLine(mascaraStr, promptStr)
    • char[] readPassword(mascaraStr, promptStr)
    • format(mascaraStr, ...) - escreve na consola
    • format(String, ...) - escreve na consola
    Nenhum dos parâmetros dos métodos da classe Console pode ser null. Caso algum seja uma NullPointerException é lançada.

    Obter o objecto ConsoleSystem.console(); - Pode retornar null se a mesma não existir.

    Métodos principais na classe java.io.ObjectOutputStream
    • ObjectOutputStream(OutputStream) - OutputSteam é geralmente FileOutputStream
    • writeObject(Object)

    Métodos principais na classe java.io.ObjectInputStream

    • ObjectInputStream(InputStream) - InputStream é geralmente FileInputStream
    • Object readObject()
    Métodos principais da classe java.io.FileInputStream
    • FileInputStream(String)

    Métodos principais da classe java.io.FileOutputStream
    • FileOutputStream(String)

    Serialização

    Para serem serializáveis as classes têm de implementar Serializable.

    Se um objecto não serializável (que não implementa Serializable) for tentado ser serializado ocorre a excepção: java.ioNotSerializableException.

    Se todos os objectos do grafo de serialização forem serializáveis, não é preciso fazer nada. Caso contrário poderá ser necessário ajudar na serialização com estes dois métodos:
    • private void writeObject(ObjectOutputStream) - pode lançar IOException
      •  deve-se invocar na primeira linha do método: os.defaultWriteObject
    • private void readObject(ObjectInputStream) - pode lançar IOException e
      ClassNotFoundException
      •  deve-se invocar na primeira linha do método: os.defaultReadObject
    É recomendado tratar as excepções na serialização.

    Criação de novos objectos e Serialização

    Eventos que ocorrem quando se usa new para criar um novo objecto:
    1. Todas as variáveis de instância da classe têm atribuído os valores por defeito
    2. O construtor é invocado e, imediatamente, é chamado o construtor da superclasse
    3. Os construtores da superclasse completam (correm e terminam)
    4. As variáveis de instância que são inicializadas como fazendo parte da sua declaração vêm atribuído o seu valor inicial
    5. O construtor completa-se (corre e termina)

    Esta ordem de eventos não ocorre quando um objecto é desserializado! Quando uma instância de uma classe serializável, é desserializada:
    1. O construtor não corre
    2. Se uma classe serializável estender outra que não o é, o construtor da classe  serializável não corre (como indicado no ponto anterior), mas o da superclasse irá correr, tal como todos os construtores de todas as superclasses acima da superclasse!
    3. As variáveis de instância não têm os seus valores iniciais atribuídos
    4. Só os valores que foram salvos (o estado do objecto na altura da serialização) serão reatribuídos
    5. As variáveis que não estão no estado do objecto terão os valores por defeito do tipo da variável

    Métodos principais na classe java.util.Date
    • Date()
    • Date(long) - em milissegundos
    • setTime(long) - em milissegundos
    • long getTime() - em milissegundos
    Métodos principais da classe java.util.Calendar
    • Calendar getInstance()
    • Calendar getInstance(Locale)
    • add(...)
    • setTime(Date)
    • get(CALENDAR_CONSTANT)
    • roll(...)
    • Date getTime()
    • set(int year, int month, int day) - month começa em 0
    • CALENDAR_CONSTANT getFirstDayOfWeek()
    O método roll é igual ao método add, exceptuando que no roll os outros campos não são automaticamente incrementados ou decrementados. Só o campo indicado é que é.
      Métodos principas da classe java.util.DateFormat
      • DateFormat getInstance()
      • DateFormat getDateInstance()
      • DateFormat getDateInstance(int style) 
      • DateFormat getDateInstance(int style, Locale locale)
      • String format(Date)
      • Date parse(String)
      O argumento style pode ser:
      • DateFormat.SHORT
      • DateFormat.MEDIUM
      • DateFormat.LONG
      • DateFormat.FULL
      Métodos principais da classe java.text.NumberFormat
      • NumberFormat getInstance()
      • NumberFormat getInstance(Locale)
      • NumberFormat getNumberInstance()
      • NumberFormat getNumberInstance(Locale)
      • NumberFormat getCurrencyInstance()
      • NumberFormat getCurrencyInstance(Locale)
      • String format(Number)
      • Number parse(String)
      • int getMaximumFractionDigits()
      • setMaximumFractionDigits(int) - Só se aplica na formatação
      • setParseIntegerOnly(boolean)
      Métodos principais da classe java.util.Locale
      • Locale(String language)
      • Locale(String language, String country)
      • Locale getDefault()
      • String getDisplayCountry()
      • String getDisplayCountry(Locale)
      • String getDisplayLanguage()
      • String getDisplayLanguage(Locale)
      Existe um conjunto de constantes que correspondem já a Locales construídos. Ex: Locale.GERMANY

      Expressões Regulares (regex)

      Métodos principais da classe java.util.regex.Pattern
      • Pattern Pattern.compile(String regex)
      • Matcher matcher(String)
      • String pattern() - String Regex
      Métodos principais da classe java.util.regex.Matcher
      • boolean find() - Verifica se há um match/procura no próximo resultado
      • int start() - Indices na String fonte onde começam os emparelhamentos
      • Pattern pattern() - String regex. Só deve ser invocado se o método find retornar true.
      • String group() - Resultado que encontrou. Só deve ser invocado se o método find retornar true.
      • boolean matches() - Indica se toda a String fonte corresponde à expressão regular indicada.
      Como regra geral, uma procura regex corre da esquerda para a direita, e assim que um carácter da fonte tiver sido usado num resultado (match), não pode ser reutilizado.

      Metacaracteres
      • \s - Um carácter whitespace
      • \w - Um carácter palavra (letras, dígitos ou _ )
      Quantificadores

      Para se usar quantificadores em conjuntos [....] tem de se colocar o conjunto entre parêntesis. Por exemplo:  ([....])+
      • ?, * e + são gananciosos. Basicamente lê a fonte toda e trabalha da direita para a esquerda. Assim que encontrar pára. Dá o resultado mais longo.
      • ??, *? e +? são relutantes. Encontra o resultado mínimo.
      Com os quantificadores gananciosos, o método find da classe Matcher pode retornar resultados (matches) do tamanho 0 (zero) , nas seguintes condições:
      • Depois do último carácter da fonte
      • Entre carácteres depois de um resultado ter sido encontrado
      • No início da fonte
      • No início de uma fonte com tamanho zero
      java.util.Scanner

      Usado para tokenização on-the-fly. Por defeito o delimitador é o espaço em branco.

      Métodos principais
      • Scanner(InputStream)
      • Scanner(String)
      • Scanner(File)
      • String findInLine(String regex) - Usado em loops. Retorna null se não encontrar nada. Chamadas sucessivas encontram o próximo match.
      • boolean hasNext() - Usado em loops. Não avança.
      • String next() - Usado em loops. Obtém e avança para o próximo.
      • boolena hasNextInt() - Usado em loops. Não avança.
      • int nextInt() - Usado em loops. Obtém e avança para o próximo.
      • boolean hasNextBoolean() - Usado em loops. Não avança.
      • boolean nextBoolean() - Usado em loops. Obtém e avança para o próximo.
      • useDelimiter(String regex)
      Os métodos hasXXX e nextXXX existem para todos os primitivos excepto char.
      Os métodos nextXXX só devem ser chamados se o método correspondente hasXXX retornar true. Caso contrário pode dar excepção.

      String e Tokenizing
      • String[] split(String regex) - Deve ser usado em Strings relativamente pequenas.
       Os delimitadores usados no Scanner e no split podem ser apenas expressões regulares. Exemplo: "\d\d".

      Formatação com printf e format da classe java.io.PrintStream

      Ambos os métodos funcionam com os mesmos parâmetros: printf(String format, Object... argumentos).
      O parâmetro format pode conter simultaneamente informação normal de literais String que não estão associados a quaisquer argumentos e dados de formatação específicos de argumentos.

      Explicação da parte format:

      %[arg_index$][flags][width][.precision] conversion

      Nota: entre [] são opcionais

      arg_index$ - Um inteiro imediatamente seguido de $. Indica qual argumento deve ser impresso nessa posição.

      flag:
      • - -> Alinhar à esquerda
      • + -> Incluir o sinal (+ ou -)
      • 0 -> Preencher com zeros
      • , -> Usar separadores específicos do Locale
      • ( -> Colocar entre parêntesis os números negativos
      width - Indica o número mínimo de caracteres a imprimir.

      precision - Usado em números de vírgula flutuante e indica o número de dígitos depois da vírgula.

      conversion -O tipo de argumento a formatar:
      • b - Booleano
      • c - Carácter (char)
      • d -Inteiro
      • f - Vírgula flutuante
      • s - String
      Se o tipo indicado não condizer com o tipo de argumento uma IllegalFormatConversionException ocorre (RuntimeException).

      Métodos principais da classe java.lang.Object
      • boolean equals(Object) - Este método, se não for overrided, apenas usa o operador == para as comparações. Se este método não for overrided, então o objecto não será usável, por exemplo,  como chave em Hashtables, pois a não ser que ainda se tenha referência para a chave, nunca a mesma será encontrada. Fazendo override a este método então deve-se fazer override ao método hashcode (por causa do contrato do equals e do hashcode).
      • int hashCode() - O overriding deste método deve usar as mesmas variáveis de instância usadas no overriding do método equals. Por esta razão se for efectuado o override deste método então deve-se fazer também o overriding do método equals (contrato do hashcode e do equals).
      • String toString() - Se não for overrided, retorna o nome_da_classe@hashcode do objecto (hexadecimal sem sinal).
      • final void notify()
      • final void notifyAll()
      • final void wait()
      • void finalize()
      Contrato do equals() 
      • Reflexivo: x.equals(x) deve retornar true
      • Simétrico: x.equals(y) = true se e só se y.equals(x) = true
      • Transitivo: x.equals(y) = true e y.equals(z) = true => x.equals(z) = true
      • Consistente: Múltiplas invocações de x.equals(y) consistentemente retornam true ou consistentemente retornam false, desde que os objectos não sejam modificados na informação usada no equals.
      • x.equals(null) = false
      • Se x.equals(y) = true => x.hashcode() = y.hashcode()
      Contrato do hashcode()
      • Consistente: Múltiplas invocações no mesmo objecto, durante a execução de uma mesma aplicação Java, retornam o mesmo inteiro, desde que nenhuma informação usada na comparação equals seja alterada.
      • Se x.equals(y) = true => x.hashcode() = y.hashcode()
      • Se x.equals(y) = false não implica que x.hashcode() <> y.hascode()
      • Se x.hascode() = y.hashcode não implica que x.equals(y) = true
      Nota: Variáveis transient não são apropriadas para uso no equals e hashcode.

      Ordem Natural dos Caracteres

      Espaço em branco < UPPERCASE < lowercase 

      Collections








      Propriedades principais das colecções
      • ArrayList e Vector - Iteração rápida e acesso aleatório rápido.
      • LinkedList - Iteração rápida e remoção rápida. Boa para adicionar elementos ao início ou ao fim. Serve para concretizar uma pilha ou fila.
      • HashSet - Acesso rápido. Sem duplicados e sem ordem.
      • LinkedHashSet - Sem duplicados e com ordem de iteração pela a de inserção.
      • TreeSet - Sem duplicados. Por defeito a ordenação é feita pela ordem natural (ascendente).
      • EnumMap - A chave tem de ser um enum e tem de pertencer ao tipo indicado. Chaves null não são permitidas (dá NullPointerException). Valores null são permitidos.
      • HashMap  - Actualizações rápidas. Só uma chave null e múltiplos valores null.
      • Hashtable - Actualizações rápidas. null não é permitido em lado nenhum.
      • LinkedHashMap - Iteração rápida. Mantém a ordem de inserção. Itera pela ordem de inserção ou último acesso.
      • TreeMap - Por defeito, a ordenação é feita pela ordem natural ascendente.
      • ConcurrentSkipListMap - log(n). null não permitidos em lado nenhum. Ordem natural.
      • PriorityQueue - Priority-in, Priority-out. Os elementos são ordenados pela sua prioridade relativa. O construtor pode levar um comparador no 2º argumento.


      Classe Map Set List Queue Ordered Sorted Identificadores Duplicados
      HashMapX


      NãoNãoÚnicos(chave)Sim (valores)
      HashtableX


      NãoNãoÚnicos(chave)Sim (valores)
      TreeMapX


      SimOrdem Natural ou CostumizávelÚnicos(chave)Sim (valores)
      LinkedHashMapX


      Por Ordem de Inserção ou por Último AcessoNãoÚnicos(chave)Sim (valores)
      ConcurrentSkipListMapX


      Ordem NaturalNãoNASim (valores)
      EnumMapX


      SimNãoÚnicos(chave)Sim (valores)
      HashSet
      X

      NãoNãoNANão
      TreeSet
      X

      SimOrdem Natural ou CostumizávelNANão
      LinkedHashSet
      X

      Por Ordem de InserçãoNãoNANão
      ArrayList

      X
      Por ÍndiceNãoNASim
      Vector

      X
      Por ÍndiceNãoNASim
      LinkedList

      XXPor ÍndiceNãoNASim
      PriorityQueue


      XSimPor Prioridades ou Ordem NaturalNASim

      Métodos principais da interface java.util.Set
      • boolean add(Object)
      • boolean remove(Object)
      • int size()
      • boolean contains(Object)
      • Iterator iterator()
      • Object[] toArray()
      • Object[] toArray(Object[])
      Métodos principais da interface java.util.List
      • boolean add(int, Object)
      • boolean add(Object)
      • Object get(int)
      • boolean remove(int)
      • boolean remove(Object)
      • int size()
      • boolean contains(Object)
      • int indexOf(Object)
      • Iterator iterator()
      • Object[] toArray()
      • Object[] toArray(Object[])
      Métodos principais da interface java.util.Queue
      • Object peek() - Retorna o primeiro elemento da fila sem o remover
      • Object pool() Retorna o primeiro elemento da fila removendo-o
      • boolean add(Object) - Adiciona o elemento à fila 
      • boolean offer(Object) - Adiciona o elemento à fila
      Métodos principais da interface java.util.Map
      • Object put(Object key, Object value)
      • Object get(Object key)
      • Object remove(Object key)
      • int size()
      • boolean contains(Object key)
      • boolean contains(Object value)
      • Set keySet()
      As chaves nos Map devem (não é obrigatório mas nada será retornado) fazer override de equals() e hashCode().

      Não esquecer que os Maps funcionam em dois passos:
      • Usam o método hashCode() para encontrar o balde certo (se o hashCode do objecto usado como chave mudar, o Map irá procurar o objecto no local errado!)
      • Usam o método equals() para encontrar o objecto no balde

      Métodos principais da classe java.util.Collections
      • int Collections.binarySearch(List, Object)- Os objectos na lista têm de implementar Comparable!
      • int Collections.binarySearch(List, Object, Comparator)
      • void Collections.sort(List) - Os objectos na lista têm de implementar Comparable!
      • void Collections.sort(List, Comparator)
      • Comparator Collections.reverseOrder(List) - Os objectos na lista têm de implementar Comparable!
      • Comparator Collections.reverseOrder(Comparator)
      • void Collections.reverse(List)
      Métodos principais da classe java.util.Arrays
      • int Arrays.binarySearch(Object[], Object)
      • int Arrays.binarySearch(Object[], Object, Comparator) 
      • void Arrays.sort(Object[]) - Os objectos no Object[] têm de implementar Comparable!
      • void Arrays.sort(Object[], Comparator)
      • List Arrays.asList(Object[]) - A lista e o array ficam ligados um ao outro. O Object[] não pode ser um array de primitivos
      • boolean equals(Object[], Object[])
      • String toString(Object[])
      Métodos importantes na classe java.util.TreeSet
      • Object ceiling(Object) - Elemento mais pequeno, maior ou igual ao objecto
      • Object heigher(Object) - Elemento mais pequeno, maior que o objecto
      • Object floor(Object) - Elemento maior, menor ou igual ao objecto
      • Object lower(Object) - Elemento maior, menor que o objecto
      • Object poolFirst() - Remove e devolve a primeira entrada
      • Object poolLast() - Remove e devolve a última entrada
      • NavigableSet descendingSet() - Retorna um NavigableSet por ordem inversa
      • NavigableSet/SortedSet headSet(Object, Boolean) - Retorna o subconjunto que termina no elemento Object (*)
      • NavigableSet/SortedSet tailSet(Object, Boolean) - Retorna o subconjunto que começa no elemento Object (*)
      • NavigableSet/SortedSet  subSet(Object start, Boolean, Object end, Boolean) - Retorna o subconjunto que começa no elemento Object start e termina no elemento Object end (*)
       (*) - Os Boolean são opcionais (Java 6). Indicam se o final é inclusive e retornam NavigableSet. Caso não sejam usados os Boolean, é retornado um SortedSet.

      Métodos importantes na classe java.util.TreeMap
      • Object firstKey() - Retorna a primeira chave
      • Object ceilingKey(Key) - Retorna a menor chave, maior ou igual a Key
      • Object heigherKey(Key) - Retorna a menor chave, maior que Key
      • Object floorKey(Key) -Retorna a maior chave, menor ou igual a Key
      • Object lowerKey(Key) -Retorna a maior chave, menor que Key
      • Object poolFirstEntry() - Retorna e remove o primeiro par chave-valor
      • Object poolLastEntry() - Retorna e remove o último par chave-valor
      • Map.entry lastEntry() -Maior chave no Map ou null se vazio.
      • NavigableMap descendingMap() -Retorna um NavigableMap na ordem inversa
      • NavigableMap/SortedMap headMap(Key, Boolean) - Submapa terminado em Key (*)
      • NavigableMap/SortedMap tailMap(Key, Boolean) - Submapa começado em Key inclusivé (*)
      • NavigableMap/SortedMap subMap(Key start, Boolean, Key end, Boolean)  - Retorna o submapa começado em start e terminado em end (*)
      (*) - Os Boolean são opcionais (Java 6). Indicam se o final é inclusive e retornam NavigableMap. Caso não sejam usados os Boolean, é retornado um SortedMap.

      Os seis métodos de TreeSet e TreeMap que retornam subconjuntos, retornam subconjuntos que estão ligados aos conjuntos originais. Pode-se efectuar operações no subconjunto que irão afectar também o conjunto original. Se se adicionar/remover elementos ao conjunto original, estes serão igualmente adicionados/removidos do subconjunto se os elementos estiveram dentro do intervalo. Se se adicionar um elemento ao subconjunto que esteja fora do intervalo deste, irá atirar uma excepção. O mesmo não acontece se este mesmo elemento for adicionado ao conjunto original!

      No TreeSet e no TreeMap os seus elementos têm de implementar Comparable.

      Collections e Código Legado

      Na invocação de código legado com colecções que usam genéricos, se o código legado inserir algo na colecção que seja diferente do tipo especificado no genérico, não irá dar erro de Runtime (embora se se usar o tipo guardado numa operação supostamente de outro tipo irá dar excepção). Contudo, em tempo de compilação, chamadas a métodos legados com colecções que usam genéricos e que inserem elementos nas colecções (se a inserção for invocada do código não legado) irá dar um aviso (warning) do género: A classe usa operações não seguras ou não checadas. Usar -Xlint para ver detalhes.

      Tomar em atenção que os métodos "get" das colecções retornam Object. Se a colecção não usar generics, então é obrigatório o uso de casts, inclusive para primitivos e respectivos wrappers. Não há autoboxing automático. No "add" já há autoboxing.

      Pesquisa nas classes Arrays e Collections

      O método binarySearch das classes Arrays e Collections retorna:
      • >= 0 - Índice do elemento procurado
      • < 0 - Índice que presenta o ponto de inserção. Para calcular devidamente: ABS(ponto de inserção -1)
      Os Arrays/Collections têm de estar ordenados antes de se proceder à procura. Caso contrário os resultados serão imprevisíveis.

      Os Arrays/Collections têm de ser procurados com o mesmo tipo de ordenação que foi usado na ordenação dos mesmos (ordem natural ou usando um Comparator).

      Em tudo o que envolva ordenação (Collections, Arrays, Sets ordenados, etc), os objectos têm de ser mutuamente comparáveis (do mesmo tipo)!

      Interface java.lang.Comparable - (implements Comparable)
      •  int compareTo(Object) - O Object pode ser implementado com o próprio tipo da classe (por causa dos generics)
      Interface java.util.Comparator  - (implements Comparator)
      • int compare(Object, Object) - Os Objects podem ser implementados com o próprio tipo da classe (por causa dos generics)

      Métodos principais da classe java.util.Iterator
      • boolean hasNext()
      • Object next()

      Generics
       
      A informação de typing (do genérico) não existe em tempo de execução. Só em tempo de compilação. Todo o código "generics" é apenas para compilação.

      Com generics, atribuir a uma referência de um supertipo, um objecto de um subtipo (ou do mesmo tipo) mas com um generic diferente do declarado, nunca irá compilar com generics. O tipo de uma declaração de variável tem de ser igual ao tipo que se passa. Não funciona nem com super nem subtipos.

      Ou seja, o tipo de genérico da referência e o tipo de genérico do objecto ao qual se refere têm de ser idênticos. O polimorfismo aplica-se apenas ao tipo base.

      Tipo_Base <Tipo_Genérico> = Tipo_Base<Tipo_Genérico>;

      O mesmo acontece na invocação de métodos. Não há polimorfismo com generics.

      O polimorfismo é permitido nos arrays. Em runtime a JVM sabe o tipo dos arrays, mas não sabe o tipo das colecções (por causa do compilador apagar o tipo - Type Erasure).


      O uso de Tipo1, indica ao compilador que se pode aceitar qualquer subtipo (?) de genérico do tipo de argumento declarado (Tipo2). Esta indicação implica que nenhum objecto possa ser adicionado à colecção. Se tal suceder um erro de compilação ocorre. Esta indicação é uma excepção à regra do não polimorfismo dos generics.

      ? extends - Usa-se quer para classes quer para interfaces.


      O uso de Tipo1, indica ao compilador que se pode aceitar qualquer tipo (?) genérico do indicado (Tipo2) e também qualquer supertipo do Tipo2. Ou seja, toda a hierarquia superior do Tipo2 e o próprio Tipo2 são aceites. Isto permite adicionar elementos à colecção.

      O uso de Tipo1, indica ao compilador que se pode aceitar qualquer tipo (?) genérico. Contudo não se pode adicionar elementos à colecção.

      Não se pode usar a notação ? (wildcard) na criação de objectos. Apenas é possível nas referências.

      Criando classes genéricas (exemplos com classe genérica):
      • public class Xpto{... - Qualquer identificador Java é válido
      • private List xpto2; -Usar o tipo da classe para o tipo da lista
      • public Xpto (List x){... -Construtor que recebe uma lista do tipo da classe
      • public T getXpto(){... -Retorna-se T
      • public void returnX(T qq)... -Recebe-se T como parâmetro
      • T instânciaDeClasse - Como tipo de variável de classe
      • T[] array - Como tipo de array
      • public class useTwo{ -Dois tipo parametrizados
      • public class Bla{... -Género de limitador de tipo
      Criando métodos construtores genéricos (exemplos em que a classe não é genérica. Só os métodos):
      • public void make(T t){...
      • public doda(T t){...
      • public Radio(T t){... - Construtor

      Convenções na documentação de API's:
      • Element (colecções)
      • Type (usado em tudo excepto colecções)

      Inner Classes

      O código na Inner Class pode aceder aos  membros da enclosing (outer) class, como se a inner class fosse parte da outer class. Uma instância da inner class tem acesso a todos os membros da outer class, incluindo aqueles marcados como private.

      As inner classes são definidas dentro das {} da outer class.
      Uma inner class não pode ter quaisquer declarações static.
      Para se aceder à inner class tem de ser ter uma instância da outer class.

      Exemplos:
      Instanciar uma inner class de dentro da outer class: new InnerClass();
      Instanciar uma inner class de fora da outer class: MyOuter.MyInner x = MyOuter.new MyInner(); (*)
      Referenciar a inner class dentro dela própria: this
      Referenciar a instância da outer class dentro da inner class: MyOuter.this

      (*) Tem mesmo de se usar o nome da classe. Não se pode usar a instância.

      Method-Local Inner Classes

      Definida dentro de um método. Só pode ser instanciada dentro do método onde é declarada mas depois da declaração. Pode aceder a todos os membros da outer class (mesmo os privados). Contudo não consegue ver as variáveis locais do método a não ser que sejam marcadas como final. Este tipo de classes pode ser criada dentro de métodos estáticos (com as mesmas restrições aplicáveis a métodos estáticos).

      Anonymous Inner Classes

      Declaram uma nova classe que não tem nome, mas que é uma subclasse do tipo de declarado no new.

      Ex: Popcorn p = new Popcorn(){....};

      Também pode implementar uma interface.
      Tomar em atenção que só faz sentido implementar ou fazer overriding a métodos da superclasse, pois a variável de referência é sempre a da interface/superclasse (no exemplo acima: Popcorn). Contudo é possível fazer overloading ou criar novos métodos. Estes nunca poderão é ser invocados de fora.

      Aplicam-se as mesmas regras das inner classes.

      Argument-Defined Anonymous Inner Classes


      Definida mesmo dentro de uma chamada a um método como argumento.


      Aplicam-se as mesmas regras das inner classes.


      Static Nested Classes

      É pura e simplesmente um membro estático da enclosing class. Aplicam-se todas as restrições dos métodos static.

      Instanciação de fora: Outer,Nest x = new Outer.Nest();
      Instanciação dentro da Outer é feita de modo normal.


      Nota: Tomar em atenção que nas Anonymous Inner Classes e Argument-Defined Anonymous Inner Classes os construtores são invocados! Ex: new Popcorn() - Invoca o construtor vazio. new Popcorn(10) - O construtor recebe um int, etc.



      Métodos Principais da classe java.lang.Thread (implements java.lang.Runnable)
      • Thread()
      • Thread(String name)  
      • Thread(Runnable) - Neste caso o método run() invocado é o da instância passada.
      • Thread(Runnable, String name) - Neste caso o método run() invocado é o da instância passada.
      • public void run() - A classe Thread espera que exista o método run() sem argumentos, e executa este método numa chamada separada (numa stack diferente) depois da thread começar. Este método é invocado pelo start().
      • start() - Invoca o método run(). Começa a nova thread de execução. A thread passa para o estado Runnable. Assim que poder executar invoca o run(). O método start() apenas pode ser invocado uma vez. Uma IllegalThreadStateException (não checada) é atirada se o método for invocado mais do que uma vez.
      • boolean isAlive() - true se o método start() já foi invocado; false caso start() ainda não tenha sido invocado ou se o método run() já terminou.
      • public final void join() throws InterruptedException - Faz com que uma thread espere até que a outra entre no estado Dead.
      • String getName() - Devolve o nome da thread
      • static Thread currentThread() - Devolve a corrente thread de execução
      • void setName(String) 
      • long getId() - Devolve o id da thread
      • static void sleep(long milis) throws InterruptedException -  (*)
      • static void yeld() - Faz com que a thread passe do estado Running para o estado Runnable. Nada é garantido [dependa da JVM] (*) 
      • public final setPriority(int) - Inteiro entre 1 e 10 (depende a JVM). 
      (*) - Não libertam os locks

      Métodos Principais da Interface java.lang.Runnable
      •  public void run() - Comportamento igual ao método run() da classe Thread. É invocado pelo start().
       Para correr uma Runnable:
      1. Criar a classe que implementa Runnable
      2. Passar a instância para dentro de uma nova Thread (new Thread(Runnable))

      Nota : Tomar em atenção que a invocação directa do método run() (sem ser pelo start()) não cria um nova thread de execução!




      Continua....