Depois de ler os Recursos ocultos do C # , perguntei-me: Quais são alguns dos recursos ocultos do Java?
Depois de ler os Recursos ocultos do C # , perguntei-me: Quais são alguns dos recursos ocultos do Java?
Respostas:
A inicialização com cinta dupla me pegou de surpresa alguns meses atrás, quando eu a descobri, nunca tinha ouvido falar antes.
ThreadLocals normalmente não são tão amplamente conhecidos como uma maneira de armazenar o estado por thread.
Como o JDK 1.5 Java possui ferramentas de simultaneidade extremamente bem implementadas e robustas além de apenas bloqueios, elas vivem em java.util.concurrent e um exemplo especificamente interessante é o subpacote java.util.concurrent.atomic que contém primitivas seguras para threads que implementam a comparação operação de swap e pode mapear para versões suportadas por hardware nativas reais dessas operações.
União de junta na variação do parâmetro de tipo:
public class Baz<T extends Foo & Bar> {}
Por exemplo, se você quiser usar um parâmetro comparável e uma coleção:
public static <A, B extends Collection<A> & Comparable<B>>
boolean foo(B b1, B b2, A a) {
return (b1.compareTo(b2) == 0) || b1.contains(a) || b2.contains(a);
}
Esse método artificial retorna true se as duas coleções fornecidas forem iguais ou se uma delas contiver o elemento especificado, caso contrário, false. O ponto a ser observado é que você pode invocar métodos de Comparable e Collection nos argumentos b1 e b2.
Fiquei surpreso com os inicializadores de instância outro dia. Eu estava excluindo alguns métodos dobrados em código e acabei criando vários inicializadores de instância:
public class App {
public App(String name) { System.out.println(name + "'s constructor called"); }
static { System.out.println("static initializer called"); }
{ System.out.println("instance initializer called"); }
static { System.out.println("static initializer2 called"); }
{ System.out.println("instance initializer2 called"); }
public static void main( String[] args ) {
new App("one");
new App("two");
}
}
A execução do main
método exibirá:
static initializer called
static initializer2 called
instance initializer called
instance initializer2 called
one's constructor called
instance initializer called
instance initializer2 called
two's constructor called
Eu acho que isso seria útil se você tivesse vários construtores e precisasse de código comum
Eles também fornecem açúcar sintático para inicializar suas aulas:
List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};
Map<String,String> codes = new HashMap<String,String>(){{
put("1","one");
put("2","two");
}};
O JDK 1.6_07 + contém um aplicativo chamado VisualVM (bin / jvisualvm.exe) que é uma boa interface gráfica do usuário em cima de muitas das ferramentas. Parece mais abrangente que o JConsole.
Curingas de caminho de classe desde o Java 6.
java -classpath ./lib/* so.Main
Ao invés de
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
Consulte http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html
Para a maioria das pessoas que entrevisto para posições de desenvolvedor Java, os blocos rotulados são muito surpreendentes. Aqui está um exemplo:
// code goes here
getmeout:{
for (int i = 0; i < N; ++i) {
for (int j = i; j < N; ++j) {
for (int k = j; k < N; ++k) {
//do something here
break getmeout;
}
}
}
}
Quem disse goto
em java é apenas uma palavra-chave? :)
E quanto aos tipos de retorno covariantes existentes desde o JDK 1.5? É muito pouco divulgado, pois é uma adição pouco sexy, mas, pelo que entendi, é absolutamente necessário para os genéricos funcionarem.
Essencialmente, o compilador agora permite que uma subclasse restrinja o tipo de retorno de um método substituído a uma subclasse do tipo de retorno do método original. Portanto, isso é permitido:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
Você pode chamar o values
método da subclasse e obter um thread classificado a salvo Set
de String
s sem precisar converter para o ConcurrentSkipListSet
.
A transferência de controle em um bloco finalmente descarta qualquer exceção. O código a seguir não gera RuntimeException - ele está perdido.
public static void doSomething() {
try {
//Normally you would have code that doesn't explicitly appear
//to throw exceptions so it would be harder to see the problem.
throw new RuntimeException();
} finally {
return;
}
}
From http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
Ninguém viu menção de instância de implementação, de forma que a verificação de nulo não é necessária.
Ao invés de:
if( null != aObject && aObject instanceof String )
{
...
}
Apenas use:
if( aObject instanceof String )
{
...
}
free
entrar ou delete
entrar em C / C ++. Um conceito tão fundamental.
Permitir métodos e construtores em enums me surpreendeu. Por exemplo:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
Você pode até ter um "corpo de classe específico constante" que permite que um valor de enum específico substitua métodos.
Mais documentação aqui .
mAge
deve ser final. Raramente existe uma razão para os campos não finais nas enumerações.
Os parâmetros de tipo para métodos genéricos podem ser especificados explicitamente da seguinte maneira:
Collections.<String,Integer>emptyMap()
public static <T> T foo(T t)
. Você pode fazer chamadas paraClass.<Type>foo(t);
return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()
. Também é útil para algumas invocações de métodos em que um simples Collections.emptyMap () causaria um erro de compilação.
Você pode usar enumerações para implementar uma interface.
public interface Room {
public Room north();
public Room south();
public Room east();
public Room west();
}
public enum Rooms implements Room {
FIRST {
public Room north() {
return SECOND;
}
},
SECOND {
public Room south() {
return FIRST;
}
}
public Room north() { return null; }
public Room south() { return null; }
public Room east() { return null; }
public Room west() { return null; }
}
EDIT: Anos depois ....
Eu uso esse recurso aqui
public enum AffinityStrategies implements AffinityStrategy {
Usando uma interface, os desenvolvedores podem definir suas próprias estratégias. Usando um enum
meio, posso definir uma coleção (de cinco) incorporada.
A partir do Java 1.5, o Java agora possui uma sintaxe muito mais limpa para escrever funções de variável variável. Então, em vez de apenas passar uma matriz, agora você pode fazer o seguinte
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
barras é automaticamente convertida em matriz do tipo especificado. Não é uma vitória enorme, mas mesmo assim uma vitória.
Meu favorito: despejar todos os rastreamentos da pilha de threads para o padrão.
windows: CTRL- Breakna janela java cmd / console
unix: kill -3 PID
Break
tecla.
Algumas pessoas postaram sobre inicializadores de instância, eis um bom uso para isso:
Map map = new HashMap() {{
put("a key", "a value");
put("another key", "another value");
}};
É uma maneira rápida de inicializar mapas se você estiver apenas fazendo algo rápido e simples.
Ou use-o para criar um protótipo de quadro de giro rápido:
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.add( new JLabel("Hey there"){{
setBackground(Color.black);
setForeground( Color.white);
}});
panel.add( new JButton("Ok"){{
addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent ae ){
System.out.println("Button pushed");
}
});
}});
frame.add( panel );
Claro que pode ser abusado:
JFrame frame = new JFrame(){{
add( new JPanel(){{
add( new JLabel("Hey there"){{
setBackground(Color.black);
setForeground( Color.white);
}});
add( new JButton("Ok"){{
addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent ae ){
System.out.println("Button pushed");
}
});
}});
}});
}};
Proxies dinâmicos (adicionados em 1.3) permitem definir um novo tipo em tempo de execução que esteja em conformidade com uma interface. É útil um número surpreendente de vezes.
a inicialização final pode ser adiada.
Ele garante que mesmo com um fluxo complexo de valores de retorno lógicos sejam sempre definidos. É muito fácil perder um caso e retornar nulo por acidente. Não torna impossível retornar nulo, apenas óbvio que é de propósito:
public Object getElementAt(int index) {
final Object element;
if (index == 0) {
element = "Result 1";
} else if (index == 1) {
element = "Result 2";
} else {
element = "Result 3";
}
return element;
}
Eu acho que outro recurso "esquecido" do java é a própria JVM. É provavelmente a melhor VM disponível. E suporta muitas linguagens interessantes e úteis (Jython, JRuby, Scala, Groovy). Todos esses idiomas podem cooperar com facilidade e facilidade.
Se você cria um novo idioma (como no caso de scala), imediatamente tem todas as bibliotecas disponíveis e, portanto, seu idioma é "útil" desde o início.
Todos esses idiomas fazem uso das otimizações do HotSpot. A VM é muito bem monitorada e depurável.
Você pode definir uma subclasse anônima e chamar diretamente um método, mesmo que não implemente interfaces.
new Object() {
void foo(String s) {
System.out.println(s);
}
}.foo("Hello");
start()
) não está realmente definido na subclasse ...
O método asList in java.util.Arrays
permite uma boa combinação de varargs, métodos genéricos e caixa automática:
List<Integer> ints = Arrays.asList(1,2,3);
Arrays.asList
tem o recurso incomum que você pode set()
elementos, mas não add()
ou remove()
. Por isso, costumo envolvê-lo em um new ArrayList(...)
ou em um Collections.unmodifiableList(...)
, dependendo se quero ou não a lista modificável.
Usando esta palavra - chave para acessar campos / métodos de conter classe de uma classe interna. No exemplo abaixo, bastante artificial, queremos usar o campo sortAscending da classe de contêiner da classe interna anônima. Usar ContainerClass.this.sortAscending em vez de this.sortAscending faz o truque.
import java.util.Comparator;
public class ContainerClass {
boolean sortAscending;
public Comparator createComparator(final boolean sortAscending){
Comparator comparator = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
if (sortAscending || ContainerClass.this.sortAscending) {
return o1 - o2;
} else {
return o2 - o1;
}
}
};
return comparator;
}
}
MyActivity.this
.
Não é realmente um recurso, mas um truque divertido que descobri recentemente em algumas páginas da Web:
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
é um programa Java válido (embora gere um aviso). Se você não vê o porquê, veja a resposta de Gregory! ;-) Bem, o destaque da sintaxe aqui também dá uma dica!
Isso não é exatamente "recursos ocultos" e não é muito útil, mas pode ser extremamente interessante em alguns casos:
Classe sun.misc.Unsafe - permitirá implementar o gerenciamento direto de memória em Java (você pode até escrever código Java auto-modificável com isso se você tentar muito):
public class UnsafeUtil {
public static Unsafe unsafe;
private static long fieldOffset;
private static UnsafeUtil instance = new UnsafeUtil();
private Object obj;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe)f.get(null);
fieldOffset = unsafe.objectFieldOffset(UnsafeUtil.class.getDeclaredField("obj"));
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
Ao trabalhar no Swing, eu gosto do oculto Ctrl- Shift-F1 recurso.
Despeja a árvore de componentes da janela atual.
(Supondo que você não tenha vinculado essa tecla a outra coisa.)
Todo arquivo de classe começa com o valor hexadecimal 0xCAFEBABE para identificá-lo como bytecode válido da JVM.
( Explicação )
Meu voto vai para java.util.concurrent, com suas coleções simultâneas e executores flexíveis, permitindo, entre outros, conjuntos de threads, tarefas agendadas e tarefas coordenadas. O DelayQueue é meu favorito pessoal, onde os elementos são disponibilizados após um atraso especificado.
java.util.Timer e TimerTask podem ser colocados com segurança em repouso.
Além disso, não exatamente oculto, mas em um pacote diferente das outras classes relacionadas à data e hora. java.util.concurrent.TimeUnit é útil ao converter entre nanossegundos, microssegundos, milissegundos e segundos.
Ele lê muito melhor que o usual someValue * 1000 ou someValue / 1000.
CountDownLatch
e CyclicBarrier
- tão útil!
Palavra- chave de afirmação no nível do idioma .
Não é realmente parte da linguagem Java, mas o desmontador javap que acompanha o JDK da Sun não é amplamente conhecido ou usado.
A adição da construção de loop for-each em 1.5. Eu <3.
// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
System.out.println(foo.toString());
}
E pode ser usado em instâncias aninhadas:
for (Suit suit : suits)
for (Rank rank : ranks)
sortedDeck.add(new Card(suit, rank));
A construção for-each também é aplicável a matrizes, onde oculta a variável index em vez do iterador. O método a seguir retorna a soma dos valores em uma matriz int:
// Returns the sum of the elements of a
int sum(int[] a) {
int result = 0;
for (int i : a)
result += i;
return result;
}
i
aqui é super confuso, pois a maioria das pessoas espera que eu seja um índice e não o elemento da matriz.
eu descobri pessoalmente java.lang.Void
muito tarde - melhora a legibilidade do código em conjunto com os genéricos, por exemploCallable<Void>