Java hidden features

Preview:

DESCRIPTION

Java possui uma série de features que muita gente não conhece. Algumas são bem esquisitas. Outras, nem tanto. Nessa palestra, mostro algumas dessas features.Em breve atualizo com os exemplos.

Citation preview

Java Hidden Features

Traquitanas escondidas ou simplesmente pouco usadas no Java

Josenaldo de Oliveira Matos Filho◦ Analista de Sistema Everis◦ 8 anos de experiência com Java e

desenvolvimento◦ UaiJUG Leader◦ Apaixonado por programação e desenvolvimento

de software◦ http://jnaldo.com

Quem sou eu?

São “features” pouco usadas do Java◦ Nenhuma feature é escondida, apenas obscura,

desconhecida◦ Algumas delas são bem esquisitas◦ Muitas consideradas até mesmo impossíveis

Use com cautela◦ Em alguns casos, são facilidades◦ Porém, em outros, deixam as coisas mais

complicadas. Podem piorar, por exemplo, a legibilidade

O que são Hidden Features

Uma das formas mais estranhas de se criar um Map inicializado é através da Double Brace Initialization.

Ex:

Double Brace Initialization

Map map = new HashMap() {{ put("a key", "a value"); put("another key", "another value"); }};

Veja mais: http://www.c2.com/cgi/wiki?DoubleBraceInitialization

WTF?◦ Classes internas anônimas que herda de HashMap

Portanto, herda métodos como put()◦ Bloco de inicialização

Chamado logo após a chamada a super() Em um construtor sem o “super”, passa a impressão

de eu é chamado antes do construtor Pode ser usado para agrupar lógica usada por vários

construtores É legal, mas evite!

Double Brace Initialization

Uma adição do Java 1.5 ainda pouco conhecida (ou percebida) Um método sobrescrito pode retornar uma subclasse da classe

retornada pelo método da superclasse (ou interface) Necessário para o funcionamento de generics

Covariant Return

class Super { Collection<String> values() { ... }}

class SubClass extends Super { @Override List<String> values() { ... }}

Quer lançar uma NullPointerException?

Lançando NullPointerExcenption

public void mandaNullNaCara() {throw null;

}

Como assim? O compilador pirou? Tá cobrando

propina pra deixar isso passar?

A instrução throw, ao ser processada, avalia a expressão à direita. ◦ Se a expressão gera um Throwable, este é lançado

Ex: throw getException()◦ Se a expressão completa normalmente,

produzindo um valor não nulo, retorna esse valor Ex: throw new SograEmCasaException()

◦ Se a expressão resulta em null, o null é convertido para NullpointerException!

Lançando NullPointerExcenption

Veja mais:http://www.adarshr.com/papers/npehttp://java.sun.com/docs/books/jls/

Quer tirar uma exceção lançada de campo?◦ Faz o return no finally!

O código abaixo não lança a exceção

Brincando com finally

public static void fazAlgumaCoisa() { try { //Faz alguma coisa… throw new RuntimeException(); } finally { return; } }

Quem for pego fazendo isso vai sofrer vudu reverso!◦ Um erro é para ser

tratado ou lançado, nunca escondido!

Atenção

Veja Mais: http://jamesjava.blogspot.com/2006/03/dont-return-in-

finally-clause.html

Como lançar uma exceção CHECADA de um método que não declara exceção!

Agora mais bizarro ainda!

import java.rmi.RemoteException;

class Thrower { public static void spit(final Throwable exception) { class EvilThrower<T extends Throwable> { @SuppressWarnings("unchecked") private void sneakyThrow(Throwable exception)

throws T { throw (T) exception; } }

new EvilThrower<RuntimeException>().sneakyThrow(exception); }}

Agora mais bizarro ainda!public class ThrowerSample { public static void main( String[] args ) { Thrower.spit(new RemoteException("go unchecked!")); }}

Mim não gostar de lançar

exceção assim!

Java não tem goto, mas...

Labeled Blocks

// codigo

saifora:{ for (int i = 0; i < N; ++i) { for (int j = i; j < N; ++j) { for (int k = j; k < N; ++k) { //mais código pog break saifora; } } }}

Quero ver isso funcionar!

Labeled Blockspublic static String getErrorMsg(String _data){    String _errMsg = “”;     VALIDATION:    {        if (_data.length() > 10)        {            _errMsg = “ERR: Data length exceed 10 chars”;            break VALIDATION;        }         // Resto docódigo de validação    }     // Tratamento da mensagem de erro    if (_errMsg.length() != 0)    {        _errMsg += “\nPlease fix the error.”;     }     return _errMsg;}

Problem?

Muita gente não sabe, mas enums podem:◦ Ter Métodos◦ Ter Atributos◦ Ter Construtores◦ Implementar interfaces

Enum

Veja mais:http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

Enum

enum Caes{ MINOTAURO(2), TITAN(3), SADAM(7);

private int idade; Caes(int idade) { this.idade = idade; } public int getIdade() { return idade; }}

Enumpublic enum Salas implements Sala{ PRIMEIRA{ public Sala norte() { return SEGUNDA; } }, SEGUNDA{ public Sala sul() { return PRIMEIRA; } }

public Sala norte() { return null; } public Sala sul() { return null; } public Sala lest() { return null; } public Sala oeste() { return null; }}

public interface Sala{ public Sala norte(); public Sala sul(); public Sala leste(); public Sala oeste();}

Desde a versão 1.5, o Java aceita parâmetros variáveis

Var args

public void foo(String... bars) { for (String bar: bars) System.out.println(bar);}

public void test() {

foo("first","second","third")}

Printf e String.format Printf do entrou na versão 1.5

String.format funciona analogamente, mas retorna ao invés de imprimir

double x = 27.5;double y = 33.75;System.out.printf("x = %f y = %g", x, y);

double x = 27.5;double y = 33.75;String s = String.format("x = %f y = %g", x, y);System.out.println(“String.format = “ + s);

Divisão por 0public class teste { public static void main(String[] args) {   try{     int x = 15; int z = 0;      double y = x / z;      System.out.println(“A divisão é “ + y);    }catch(ArithmeticException a){     System.out.println(“Erro!! Divisão por zero!!!”);    }  }}

Ok. Isto lança uma ArithmeticExceptio

n

Divisão por 0public class teste { public static void main(String[] args) { try{ double x = 15;

double z = 0; double y = x / z; System.out.println(“A divisão é “ + x); }catch(ArithmeticException a){ System.out.println(“Erro!! Divisão por zero!!!”); } }}

WTF???????

Quer ver um dump da hierarquia de componentes numa aplicação Swing?◦ Ctrl + Shift + F1◦ Resultado no console◦ Boa ferramenta para depuração!

Swing

Qual o resultado disso?

E isso?

Brincando com URLs

new URL("http://www.guj.com.br").equals(new URL("http://208.109.100.149") )

public int umMetodo(){ System.out.println(“Acessando o Google:”); http://www.google.com return 1;}

Como acessar os métodos e campos privados de fora dessa classe?

Arrebentando o encapsulamento

public class Foo { private int bar; public Foo() { setBar(17); } private void setBar(int bar) { this.bar=bar; } public int getBar() { return bar; } public String toString() { return "Foo[bar="+bar+"]"; }}

Arrebentando o encapsulamentoimport java.lang.reflect.*;

public class Arrebenta { public static void main(String[] args) throws NoSuchMethodException,IllegalAccessException, InvocationTargetException, NoSuchFieldException { Foo foo=new Foo(); System.out.println(foo); Method method=Foo.class.getDeclaredMethod ("setBar", int.class); method.setAccessible(true); method.invoke(foo, 42);

Arrebentando o encapsulamento System.out.println(foo); Field field=Foo.class.getDeclaredField("bar"); field.setAccessible(true); field.set(foo, 23); System.out.println(foo); }}

Isso vai dar merda!

Acesso esquisitopublic class Foo { static int fubar = 42;

Foo getFoo() { return null; }

public static void main(String args[]) { Foo foo = new Foo(); System.out.println(foo.getFoo().fubar); }}// saida: 42

Agora você tá de

sacanagem!

É possível criar um programa sem Main!

Classe sem main!

public class WithoutMain { static { System.out.println("Look man, no main!!"); System.exit(0); }}

$ java WithoutMainLook man, no main!!

Distribuída com o JDK a partir da versão1.6_07 Profiler leve Integra uma série de ferramentas de linha de

comando

VisualVM

Veja mais:http://visualvm.java.net/

Todo arquivo .class começa com o valor hexadecimal 0xCAFEBABE, para identificá-lo como um arquivo de Bytecode válido.

Quer exibir uma Splash screen?◦ Basta rodar o programa com o parâmetro de

máriona virtual splash:caminho

Curiosidades

java -splash:imagem.jpeg -jar Reverso.jar

Classes anônimas Você pode definir uma classe anônima e

imediatamente chamar um método, mesmo que ela não implemente nenhuma interface

new Object() { void foo(String s) { System.out.println(s); }}.foo("Hello");

Permite a criação de uma thread eu será chamada somente quando a JVM for encerrada◦ Global JVM Finalizer◦ Liberar recursos◦ Matar programas

Funciona com System.exit(), ou com CTRL-C / kill -15◦ Obviamente, não funciona com kill -9, em *nix

Shutdown Hooks

Shutdown Hooks

Runtime.getRuntime().addShutdownHook( new Thread() { public void run() { endApp(); }});;

Perguntas