Java中一些常被忽视的特性
[原文链接]
说明:
1 参考自stackoverflow上的一个帖子以及广大网友的回复: http://stackoverflow.com/questions/15496/hidden-features-of-java?page=4&tab=votes#tab-top
2 在这些回复中,我选择了一些写到这篇博客中,当然也有很多回复我认为没有必要翻译出来.
3 在翻译的过程中,为了快速完成,主要把代码贴过来,只要是对Java比较熟悉的, 看到代码基本上就能理解这个特性.对其他解释性的文字翻译的比较少, 如果感兴趣可以查看原文, 原文地址在上面已经给出.
1 使用Class<T>进行运行时类型检查
如果一个实例是根据配置文件中的类型创建出来的, 那么在代码中并不能明确确定该实例的类型,使用该方法可以在运行时检查类型
[java] view plaincopyprint?
- 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 整数自动装箱
[java] view plaincopyprint?
- 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 格式化字符串
[java] view plaincopyprint?
- 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类型的局部变量
[java] view plaincopyprint?
- 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方法可以复制一个数组
[java] view plaincopyprint?
- int[] arr = {1, 2, 3};
- int[] arr2 = arr.clone();
int[] arr = {1, 2, 3};int[] arr2 = arr.clone();
6 通过反射可以访问私有成员
[java] view plaincopyprint?
- 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+"]";
}
}
[java] view plaincopyprint?
- 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);
}
}
打印结果:
[java] view plaincopyprint?
- Foo[bar=17]
- Foo[bar=42]
- Foo[bar=23]
Foo[bar=17]Foo[bar=42]
Foo[bar=23]
7 使用Scanner解析字符串
[java] view plaincopyprint?
- 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 可以使用非英文给标示符命名
[java] view plaincopyprint?
- String Überschrift="";
String Überschrift="";
译者注: 中文也可以.
9 访问局部变量比访问成员变量快
[java] view plaincopyprint?
- 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
优化后的代码:
[java] view plaincopyprint?
- 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是一个关键字, 但是你不能使用它
[java] view plaincopyprint?
- 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风格的打印语句
[java] view plaincopyprint?
- System.out.printf("%d %f %.4f", 3,Math.E,Math.E);
System.out.printf("%d %f %.4f", 3,Math.E,Math.E);
12 匿名内部类可以直接调用子类中定义的方法
[java] view plaincopyprint?
- (new Object() {
- public String someMethod(){
- return "some value";
- }
- }).someMethod();
(new Object() {public String someMethod(){
return "some value";
}
}).someMethod();
[java] view plaincopyprint?
- 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中的方法
13 List.subList()创建原有list的一个视图
操作一个list的一部分, 并且对subList的修改会反映到原有list中
[java] view plaincopyprint?
- list.subList(from, to).clear();
list.subList(from, to).clear();
以上代码删除原有list中从from到to位置的元素.
译者注: 可查看jdk中ArrayList的源码来验证这一结论.下面贴出部分源码:
[java] view plaincopyprint?
- 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);
}
SubList作为ArrayList的一个内部类:
[java] view plaincopyprint?
- 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 自限定泛型
[java] view plaincopyprint?
- class SelfBounded<T extends SelfBounded<T>> {
- }
class SelfBounded<T extends SelfBounded<T>> {}
15 可以在方法中定义一个内部类
[java] view plaincopyprint?
- 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中可以使用标号
[java] view plaincopyprint?
- public int aMethod(){
- http://www.google.com
- return 1;
- }
public int aMethod(){http://www.google.com
return 1;
}
上面的http:是一个标号, //是注释
17 没有main方法的HelloWorld
[java] view plaincopyprint?
- 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);
}
}
运行结果:
[java] view plaincopyprint?
- $ java WithoutMain
- Look ma, no main!!
$ java WithoutMainLook ma, no main!!
18 Shutdown钩子
在虚拟机停掉之前被调用:
[java] view plaincopyprint?
- Runtime.getRuntime().addShutdownHook(new Thread() {
- public void run() {
- endApp();
- }
- });;
Runtime.getRuntime().addShutdownHook(new Thread() {public void run() {
endApp();
}
});;
19 URL类的equals方法
[java] view plaincopyprint?
- 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 在没有声明抛出任何异常的方法中抛出受检查异常
[java] view plaincopyprint?
- 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
[java] view plaincopyprint?
- public static void main(String[] args) {
- throw null;
- }
public static void main(String[] args) {throw null;
}
22 自动装箱中的一些规则
[java] view plaincopyprint?
- 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块中返回
[java] view plaincopyprint?
- @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 数组初始化的误区
以下代码是正确的:
[java] view plaincopyprint?
- 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);
}
}
而以下代码是错误的:
[java] view plaincopyprint?
- 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访问外部类成员
[java] view plaincopyprint?
- 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局部变量可以不再声明的同时初始化
[java] view plaincopyprint?
- 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 使用初始化块快速创建对象
[java] view plaincopyprint?
- 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");
}};
[java] view plaincopyprint?
- 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中引入可变参数
[java] view plaincopyprint?
- 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 枚举可以实现一个接口
[html] view plaincopyprint?
- 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 泛型方法可以显示指定类型参数
[java] view plaincopyprint?
- Collections.<String,Integer>emptyMap()
Collections.<String,Integer>emptyMap()
31 枚举中可以有构造方法和普通方法
[java] view plaincopyprint?
- 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中异常的抛出
[java] view plaincopyprint?
- 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
[java] view plaincopyprint?
- if( null != aObject && aObject instanceof String )
- {
- ...
- }
if( null != aObject && aObject instanceof String ){
...
}
可以使用以下代码代替(不用判断null)
[html] view plaincopyprint?
- if( aObject instanceof String )
- {
- ...
- }
if( aObject instanceof String ){
...
}
34 java1.5中引入的协变返回类型
如果子类覆盖了父类的方法, 子类中的方法可以返回父类中方法的返回值类型或其子类型
[java] view plaincopyprint?
- 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中可以使用标号进行流程控制
[java] view plaincopyprint?
- // 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 heregetmeout:{
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 初始化块和静态初始化块
[java] view plaincopyprint?
- 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");
}
}
打印结果如下:
[java] view plaincopyprint?
- 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 calledstatic initializer2 called
instance initializer called
instance initializer2 called
one's constructor called
instance initializer called
instance initializer2 called
two's constructor called
37 在泛型的类型限定中使用&限定接口
[html] view plaincopyprint?
- public class Baz<T extends Foo & Bar> {}
public class Baz<T extends Foo & Bar> {}
意为:T是Foo的子类型, 并且实现了Bar接口
[java] view plaincopyprint?
- 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方法
以上是 Java中一些常被忽视的特性 的全部内容, 来源链接: utcz.com/z/393210.html