说明:
1 参考自stackoverflow上的一个帖子以及广大网友的回复: http://stackoverflow.com/questions/15496/hidden-features-of-java?page=4&tab=votes#tab-top
2 在这些回复中,我选择了一些写到这篇博客中,当然也有很多回复我认为没有必要翻译出来.
3 在翻译的过程中,为了快速完成,主要把代码贴过来,只要是对Java比较熟悉的, 看到代码基本上就能理解这个特性.对其他解释性的文字翻译的比较少, 如果感兴趣可以查看原文, 原文地址在上面已经给出.
正文:
1 使用Class<T>进行运行时类型检查
如果一个实例是根据配置文件中的类型创建出来的, 那么在代码中并不能明确确定该实例的类型,使用该方法可以在运行时检查类型
- public interface SomeInterface {
- void doSomething(Object o);
- }
- public abstract class RuntimeCheckingTemplate<T> {
- private Class<T> clazz;
- protected RuntimeChecking(Class<T> clazz) {
- this.clazz = clazz;
- }
- public void doSomething(Object o) {
- if (clazz.isInstance(o)) {
- doSomethingWithGeneric(clazz.cast(o));
- } else {
- // log it, do something by default, throw an exception, etc.
- }
- }
- protected abstract void doSomethingWithGeneric(T t);
- }
- public class ClassThatWorksWithStrings extends RuntimeCheckingTemplate<String> {
- public ClassThatWorksWithStrings() {
- super(String.class);
- }
- protected abstract void doSomethingWithGeneric(T t) {
- // Do something with the generic and know that a runtime exception won't occur
- // because of a wrong type
- }
- }
2 整数自动装箱
- Integer a = 1;
- Integer b = 1;
- Integer c = new Integer(1);
- Integer d = new Integer(1);
- Integer e = 128;
- Integer f = 128;
- assertTrue (a == b); // again: this is true!
- assertFalse(e == f); // again: this is false!
- assertFalse(c == d); // again: this is false!
3 格式化字符串
- final String foo = "42";
- new Thread() {
- public void run() {
- dowhatever(foo);
- }
- }.start();
5 数组类型的对象调用clone方法可以复制一个数组
- 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+"]";
- }
- }
- import java.lang.reflect.*;
- public class AccessibleExample {
- 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);
- System.out.println(foo);
- Field field=Foo.class.getDeclaredField("bar");
- field.setAccessible(true);
- field.set(foo, 23);
- System.out.println(foo);
- }
- }
打印结果:
- String input = "1 fish 2 fish red fish blue fish";
- Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
- System.out.println(s.nextInt());
- System.out.println(s.nextInt());
- System.out.println(s.next());
- System.out.println(s.next());
- s.close();
8 可以使用非英文给标示符命名
- String Überschrift="";
译者注: 中文也可以.
9 访问局部变量比访问成员变量快
- public class Slow {
- /** Loop counter; initialized to 0. */
- private long i;
- public static void main( String args[] ) {
- Slow slow = new Slow();
- slow.run();
- }
- private void run() {
- while( i++ < 10000000000L )
- ;
- }
- }
以上代码平均耗时18.018s
优化后的代码:
- public class Fast {
- /** Loop counter; initialized to 0. */
- private long i;
- public static void main( String args[] ) {
- Fast fast = new Fast();
- fast.run();
- }
- private void run() {
- long i = getI();
- while( i++ < 10000000000L )
- ;
- setI( i );
- }
- private long setI( long i ) {
- this.i = i;
- }
- private long getI() {
- return this.i;
- }
- }
以上代码平均耗时10.509s
10 const是一个关键字, 但是你不能使用它
- (new Object() {
- public String someMethod(){
- return "some value";
- }
- }).someMethod();
- new Object() {
- void foo(String s) {
- System.out.println(s);
- }
- }.foo("Hello");
尽管创建的匿名内部类实例并没有实现一个独立的接口, 但是能直接调用不在父类Object中的方法
操作一个list的一部分, 并且对subList的修改会反映到原有list中
- list.subList(from, to).clear();
以上代码删除原有list中从from到to位置的元素.
译者注: 可查看jdk中ArrayList的源码来验证这一结论.下面贴出部分源码:
- public List<E> subList(int fromIndex, int toIndex) {
- subListRangeCheck(fromIndex, toIndex, size);
- return new SubList(this, 0, fromIndex, toIndex);
- }
SubList作为ArrayList的一个内部类:
- private class SubList extends AbstractList<E> implements RandomAccess {
- private final AbstractList<E> parent;
- private final int parentOffset;
- private final int offset;
- int size;
- SubList(AbstractList<E> parent,
- int offset, int fromIndex, int toIndex) {
- this.parent = parent;
- this.parentOffset = fromIndex;
- this.offset = offset + fromIndex;
- this.size = toIndex - fromIndex;
- this.modCount = ArrayList.this.modCount;
- }
- // ......
- public void add(int index, E e) {
- rangeCheckForAdd(index);
- checkForComodification();
- parent.add(parentOffset + index, e);
- this.modCount = parent.modCount;
- this.size++;
- }
- public E remove(int index) {
- rangeCheck(index);
- checkForComodification();
- E result = parent.remove(parentOffset + index);
- this.modCount = parent.modCount;
- this.size--;
- return result;
- }
- // ......
从add和remove方法可以看出, 对subList的修改反映到了原有list(parent)中.
14 自限定泛型
- public Foo foo(String in) {
- class FooFormat extends Format {
- public Object parse(String s, ParsePosition pp) { // parse stuff }
- }
- return (Foo) new FooFormat().parse(in);
- }
16 Java中可以使用标号
- public int aMethod(){
- http://www.google.com
- return 1;
- }
上面的http:是一个标号, //是注释
17 没有main方法的HelloWorld
- public class WithoutMain {
- static {
- System.out.println("Look ma, no main!!");
- System.exit(0);
- }
- }
运行结果:
在虚拟机停掉之前被调用:
- Runtime.getRuntime().addShutdownHook(new Thread() {
- public void run() {
- endApp();
- }
- });;
19 URL类的equals方法
- new URL("http://www.yahoo.com").equals(new URL("http://209.191.93.52"))
上述代码结果为true
20 在没有声明抛出任何异常的方法中抛出受检查异常
- 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);
- }
- }
- public class ThrowerSample {
- public static void main( String[] args ) {
- Thrower.spit(new RemoteException("go unchecked!"));
- }
- }
21 可以抛出null
- Long value = new Long(0);
- System.out.println(value.equals(0)); //false
- Integer i = 0;
- System.out.println(i.equals(0)); //true
- Integer j = new Integer(0);
- System.out.println(j.equals(0)); //true
- System.out.println(j.equals(i)); //true
- System.out.println(i == j); //false
- Integer m = 0;
- System.out.println(i.equals(m)); //true
- System.out.println(i == m); //true
- Integer x = 128;
- Integer y = 128;
- Integer z = new Integer(128);
- System.out.println(x.equals(y)); //true
- System.out.println(x == y); //fasle
- System.out.println(x.equals(z)); //true
- System.out.println(x == z); //false
23 在finally块中返回
- @SuppressWarnings("finally")
- public static int returnSomething() {
- try {
- throw new RuntimeException("foo!");
- } finally {
- return 1;
- }
- //在这里可以不写return语句
- }
- public static void main(String[] args) {
- System.out.println(returnSomething()); // 返回1
- }
24 数组初始化的误区
以下代码是正确的:
- public class Foo {
- public void doSomething(String[] arg) {}
- public void example() {
- String[] strings = { "foo", "bar" };
- doSomething(strings);
- }
- }
而以下代码是错误的:
- public class Foo {
- public void doSomething(String[] arg) {}
- public void example() {
- doSomething({ "foo", "bar" });
- }
- }
25 内部类中使用this访问外部类成员
- 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;
- }
- }
26 final局部变量可以不再声明的同时初始化
- 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;
- }
27 使用初始化块快速创建对象
- Map map = new HashMap() {{
- put("a key", "a value");
- put("another key", "another value");
- }};
- 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");
- }
- });
- }});
- }});
- }};
28 java1.5中引入可变参数
- 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; }
- }
30 泛型方法可以显示指定类型参数
- enum Cats {
- FELIX(2), SHEEBA(3), RUFUS(7);
- private int mAge;
- Cats(int age) {
- mAge = age;
- }
- public int getAge() {
- return mAge;
- }
- }
32 finally块中的return语句阻止try中异常的抛出
- 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;
- }
- }
33 instanceof关键字不用判断null
- if( null != aObject && aObject instanceof String )
- {
- ...
- }
可以使用以下代码代替(不用判断null)
如果子类覆盖了父类的方法, 子类中的方法可以返回父类中方法的返回值类型或其子类型
- class Souper {
- Collection<String> values() {
- ...
- }
- }
- class ThreadSafeSortedSub extends Souper {
- @Override
- ConcurrentSkipListSet<String> values() {
- ...
- }
- }
35 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;
- }
- }
- }
- }
36 初始化块和静态初始化块
- 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");
- }
- }
打印结果如下:
- 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
- public class Baz<T extends Foo & Bar> {}
意为:T是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);
- }
在foo方法中, 可以使用Comparable接口中的compareTo方法