Java中一些常被忽视的特性
[原文链接]
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
- }
- }
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!
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 格式化字符串
- String w = "world";
- String s = String.format("Hello %s %d", w, 3);
String w = "world"; String s = String.format("Hello %s %d", w, 3);
4 匿名内部类中可以访问final类型的局部变量
- final String foo = "42";
- new Thread() {
- public void run() {
- dowhatever(foo);
- }
- }.start();
final String foo = "42"; new Thread() { public void run() { dowhatever(foo); } }.start();
5 数组类型的对象调用clone方法可以复制一个数组
- int[] arr = {1, 2, 3};
- int[] arr2 = arr.clone();
int[] arr = {1, 2, 3}; int[] arr2 = arr.clone();
6 通过反射可以访问私有成员
- 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+"]";
- }
- }
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);
- }
- }
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();
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="";
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 )
- ;
- }
- }
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;
- }
- }
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是一个关键字, 但是你不能使用它
- int const = 1; // "not a statement"
- const int i = 1; // "illegal start of expression"
int const = 1; // "not a statement" const int i = 1; // "illegal start of expression"
11 C风格的打印语句
- System.out.printf("%d %f %.4f", 3,Math.E,Math.E);
System.out.printf("%d %f %.4f", 3,Math.E,Math.E);
12 匿名内部类可以直接调用子类中定义的方法
- (new Object() {
- public String someMethod(){
- return "some value";
- }
- }).someMethod();
(new Object() { public String someMethod(){ return "some value"; } }).someMethod();
- new Object() {
- void foo(String s) {
- System.out.println(s);
- }
- }.foo("Hello");
new Object() { void foo(String s) { System.out.println(s); } }.foo("Hello");尽管创建的匿名内部类实例并没有实现一个独立的接口, 但是能直接调用不在父类Object中的方法
操作一个list的一部分, 并且对subList的修改会反映到原有list中
- list.subList(from, to).clear();
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);
- }
public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); }
- 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;
- }
- // ......
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 自限定泛型
- class SelfBounded<T extends SelfBounded<T>> {
- }
class SelfBounded<T extends SelfBounded<T>> { }
15 可以在方法中定义一个内部类
- public Foo foo(String in) {
- class FooFormat extends Format {
- public Object parse(String s, ParsePosition pp) { // parse stuff }
- }
- return (Foo) new FooFormat().parse(in);
- }
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;
- }
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);
- }
- }
public class WithoutMain { static { System.out.println("Look ma, no main!!"); System.exit(0); } }运行结果:
在虚拟机停掉之前被调用:
- Runtime.getRuntime().addShutdownHook(new Thread() {
- public void run() {
- endApp();
- }
- });;
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"))
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!"));
- }
- }
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
- public static void main(String[] args) {
- throw null;
- }
public static void main(String[] args) { throw null; }
22 自动装箱中的一些规则
- 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
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
- }
@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() { String[] strings = { "foo", "bar" }; doSomething(strings); } }而以下代码是错误的:
- public class Foo {
- public void doSomething(String[] arg) {}
- public void example() {
- doSomething({ "foo", "bar" });
- }
- }
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;
- }
- }
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;
- }
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");
- }};
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");
- }
- });
- }});
- }});
- }};
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 void foo(String... bars) {
- for (String bar: bars)
- System.out.println(bar);
- }
public void foo(String... bars) { for (String bar: bars) System.out.println(bar); }
29 枚举可以实现一个接口
- 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; }
- }
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;
- }
- }
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;
- }
- }
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 )
- {
- ...
- }
if( null != aObject && aObject instanceof String ) { ... }可以使用以下代码代替(不用判断null)
- if( aObject instanceof String )
- {
- ...
- }
if( aObject instanceof String ) { ... }
34 java1.5中引入的协变返回类型
如果子类覆盖了父类的方法, 子类中的方法可以返回父类中方法的返回值类型或其子类型
- class Souper {
- Collection<String> values() {
- ...
- }
- }
- class ThreadSafeSortedSub extends Souper {
- @Override
- ConcurrentSkipListSet<String> values() {
- ...
- }
- }
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;
- }
- }
- }
- }
// 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");
- }
- }
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
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> {}
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);
- }
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方法