在阅读完C#的隐藏特性后,我想知道Java有哪些隐藏特性?
双括号初始化在几个月前我第一次发现时让我感到惊讶,以前从未听说过。
ThreadLocal通常不像锁那样广泛地被认知为存储每个线程状态的方法。
自JDK 1.5以来,Java已经拥有极其良好实现和强大的并发工具,除了锁之外,它们还存在于java.util.concurrent中,其中一个特别有趣的例子是java.util.concurrent.atomic子包,其中包含实现比较和交换操作的线程安全原语,并可以映射到这些操作的实际本机硬件支持版本。
类型参数的联合变量:
public class Baz<T extends Foo & Bar> {}
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 的方法。
前几天我被实例初始化程序惊到了。我删除了一些代码折叠方法,结果创建了多个实例初始化程序:
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以来,支持类路径通配符。
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开始就已经实施的协变返回类型怎么样?虽然这是一个不太引人注目的补充,但据我所知,它对于泛型的使用绝对必要。
本质上,编译器现在允许子类将重写方法的返回类型缩小为原始方法返回类型的子类。 因此,下面的内容是被允许的:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
你可以调用子类的values
方法,并获得一个排序的线程安全Set
,其中包含String
,无需将其向下转换为ConcurrentSkipListSet
。
在 finally 块中转移控制权会丢弃任何异常。以下代码不会抛出 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
在Java中,finally语句块是无论try和catch语句块是否抛出异常都会执行的。然而,在finally块中使用return语句可能会导致一些奇怪的问题。因为如果在try或catch块中存在return语句,它将覆盖finally块中的返回值,从而可能导致不可预测的行为。
一个更好的解决方案是在finally块之前定义一个变量,并将其设置为要返回的值。然后在finally块中不要使用return语句,而是通过变量返回值。
还没有看到有人提到 instanceof 被实现成不需要检查 null 的方式。
而是:
if( null != aObject && aObject instanceof String )
{
...
}
只需使用:
if( aObject instanceof String )
{
...
}
让枚举中包含方法和构造函数让我感到惊讶。例如:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
您甚至可以使用“常量专用类体”,让特定的枚举值重写方法。
更多文档请参见这里。
mAge
应该是 final 的。在枚举类型中,很少有非 final 的字段是必要的。 - Joachim Sauer