Java的隐藏特性
在阅读C#的隐藏特性之后,我想知道,Java的一些隐藏function是什么?
双Brace Initialization在几个月前让我吃了一惊,当时我第一次发现它,从来没有听说过它。
ThreadLocals通常并不是广为人知的存储每个线程状态的方法。
由于JDK 1.5 Java具有非常好的实现和强大的并发工具,而不仅仅是锁,它们住在java.util.concurrent中 ,一个特别有趣的例子是java.util.concurrent.atomic子包,它包含实现比较的线程安全基元并且可以映射到这些操作的实际本机硬件支持的版本。
联合types参数方差:
public class Baz<T extends Foo & Bar> {}
例如,如果您想要采用Comparable和Collection两个参数:
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); }
如果给定的两个集合是相等的,或者它们中的任何一个包含给定的元素,则此方法返回true,否则返回false。 需要注意的是,您可以在参数b1和b2上调用Comparable和Collection的方法。
有一天我对实例初始化者感到惊讶。 我正在删除一些代码折叠的方法,最终创build了多个实例初始值设定项:
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"); } }
执行main
方法将显示:
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
我想这些将是有用的,如果你有多个构造函数,并需要通用的代码
他们还提供了用于初始化你的类的语法糖:
List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }}; Map<String,String> codes = new HashMap<String,String>(){{ put("1","one"); put("2","two"); }};
JDK 1.6_07 +包含一个名为VisualVM(bin / jvisualvm.exe)的应用程序,它是许多工具的一个很好的GUI。 看起来比JConsole更全面。
Java 6以来的Classpath通配符。
java -classpath ./lib/* so.Main
代替
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
请参阅http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html
对于我为Java开发人员采访的大多数人来说,标记块是非常令人惊讶的。 这里是一个例子:
// 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; } } } }
谁说在java中goto
只是一个关键字? 🙂
从JDK 1.5开始, 协变式返回types如何呢? 这是相当不好的宣传,因为这是一个不合理的补充,但据我所知,是generics工作绝对必要的。
实际上,编译器现在允许一个子类将重写的方法的返回types缩小为原始方法的返回types的子类。 所以这是允许的:
class Souper { Collection<String> values() { ... } } class ThreadSafeSortedSub extends Souper { @Override ConcurrentSkipListSet<String> values() { ... } }
您可以调用子类的values
方法,并获得sorting的线程安全的String
Set
, 而不必将其转换为ConcurrentSkipListSet
。
还没有见过任何人提到instanceof正在执行的方式,检查null是没有必要的。
代替:
if( null != aObject && aObject instanceof String ) { ... }
只是使用:
if( aObject instanceof String ) { ... }
在finally块中传输控制权将抛出任何exception。 下面的代码不会抛出RuntimeException – 它会丢失。
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; } }
从http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
在枚举中允许方法和构造函数让我感到惊讶。 例如:
enum Cats { FELIX(2), SHEEBA(3), RUFUS(7); private int mAge; Cats(int age) { mAge = age; } public int getAge() { return mAge; } }
你甚至可以有一个“常量特定的类体”,它允许一个特定的枚举值来覆盖方法。
更多文档在这里 。
generics方法的types参数可以像这样明确指定:
Collections.<String,Integer>emptyMap()
你可以使用枚举来实现一个接口。
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; } }
编辑:多年以后….
我在这里使用这个function
public enum AffinityStrategies implements AffinityStrategy {
通过使用接口,开发人员可以定义自己的策略。 使用enum
意味着我可以定义一个集合(五个)内置的集合。
从Java 1.5开始,Java现在有了一个更清晰的用于编写variablesarity的函数的语法。 所以,而不是只传递一个数组,现在你可以做到以下几点
public void foo(String... bars) { for (String bar: bars) System.out.println(bar); }
条自动转换为指定types的数组。 不是一个巨大的胜利,而是一个胜利。
我最喜欢的:将所有线程堆栈跟踪转储到标准输出。
windows: CTRL – 在你的java cmd / console窗口中断
unix: kill -3 PID
有几个人已经发布了关于实例初始化器的例子,这里有一个很好的用处:
Map map = new HashMap() {{ put("a key", "a value"); put("another key", "another value"); }};
如果你只是做一些简单而快速的事情,是一种快速初始化地图的方法。
或者用它来创build一个快速的摆动框架原型:
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 );
当然可以被滥用:
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"); } }); }}); }}); }};
dynamic代理 (在1.3中添加)允许您在运行时定义一个符合接口的新types。 它有一个惊人的时间来派上用场。
最终的初始化可以推迟。
它确保即使在复杂的逻辑stream程中也始终设置返回值。 错过一个例子太容易,偶然返回null。 它不会使返回null不可能,只是很明显,它是有意的:
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; }
我认为Java的另一个“被忽视”的特性是JVM本身。 这可能是最好的虚拟机。 它支持许多有趣和有用的语言(Jython,JRuby,Scala,Groovy)。 所有这些语言都可以轻松无缝地合作。
如果你devise一个新的语言(比如在scala-case中),你可以立即拥有所有现有的库,因此你的语言从一开始就是“有用的”。
所有这些语言都使用HotSpot优化。 VM非常好的监视和debugging。
你可以定义一个匿名的子类,并直接调用一个方法,即使它没有实现接口。
new Object() { void foo(String s) { System.out.println(s); } }.foo("Hello");
java.util.Arrays
的asList方法允许可变参数,generics方法和自动装箱的组合:
List<Integer> ints = Arrays.asList(1,2,3);
使用此关键字来访问从内部类包含类的字段/方法。 在下面,比较人为的例子中,我们想使用来自匿名内部类的容器类的sortAscending字段。 使用ContainerClass.this.sortAscending而不是this.sortAscending伎俩。
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; } }
不是一个真正的function,而是我最近在某个网页上发现的一个有趣的技巧:
class Example { public static void main(String[] args) { System.out.println("Hello World!"); http://Phi.Lho.free.fr System.exit(0); } }
是一个有效的Java程序(虽然它会产生一个警告)。 如果你不明白为什么,请参阅Gregory的答案! ;-)这里的语法突出显示也提供了一个提示!
这不完全是“隐藏的function”,并不是很有用,但在某些情况下可能会非常有趣:
类sun.misc.Unsafe – 将允许您在Java中实现直接内存pipe理 (如果您尝试了很多,您甚至可以使用此代码编写自修改的Java代码):
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); } }; }
在Swing中工作时,我喜欢隐藏的Ctrl – Shift – F1function。
它转储当前窗口的组件树。
(假设您没有将该按键绑定到其他地方)。
每个类文件都以hex值0xCAFEBABE开头,将其识别为有效的JVM字节码。
( 说明 )
我的投票与java.util.concurrent及其并发集合和灵活的执行程序,其中包括线程池,计划任务和协调任务。 DelayQueue是我个人的最爱,在指定的延迟后元素可用。
java.util.Timer和TimerTask可以安全地放置。
此外,不完全隐藏,但在与date和时间相关的其他类的不同包。 java.util.concurrent.TimeUnit在纳秒,微秒,毫秒和秒之间转换时非常有用。
它读取比通常someValue * 1000或someValue / 1000更好。
语言级别的断言关键字。
不是Java语言的一部分,但Sun的JDK附带的javap反汇编程序并不被广泛的使用。
1.5中添加for-each循环结构。 我<3。
// For each Object, instantiated as foo, in myCollection for(Object foo: myCollection) { System.out.println(foo.toString()); }
并且可以在嵌套的实例中使用:
for (Suit suit : suits) for (Rank rank : ranks) sortedDeck.add(new Card(suit, rank));
for-each构造也适用于数组,它隐藏了索引variables而不是迭代器。 以下方法返回int数组中值的总和:
// Returns the sum of the elements of a int sum(int[] a) { int result = 0; for (int i : a) result += i; return result; }
链接到Sun文档
i personally discovered java.lang.Void
very late — improves code readability in conjunction with generics, eg Callable<Void>