关于java-10件你不知道的事
来源:互联网 发布:线切割hl绘图编程退出 编辑:程序博客网 时间:2024/05/17 00:11
1. 像Runtime exceptions一样使用Checked exceptions
下面的代码是正确的!public class Test1 { // No throws clause here public static void main(String[] args) { doThrow(new SQLException()); } static void doThrow(Exception e) { Test1.<RuntimeException>doThrow0(e); } @SuppressWarnings("unchecked") static <E extends Exception> void doThrow0(Exception e) throws E { throw (E) e; }}
2. 在一个类中可以做到重载只有返回类型不同的方法
直接按下面这个类code,是错误的:
class Test { Object x() { return "abc"; } String x() { return "123"; }}它会有编译错误:x() is already defined。因为java语言不允许只有返回类型不同的重载,假设允许,请看这个调用:
void main() { x();}那么这个方法并不确定它调的哪个方法。
但是...等等,查看java文档,看到Class.getMethod(String, Class...)
有如下描述:
“Note that there may be more than one matching method in a class because while the Java language forbids a class to declare multiple methods with the same signature but different return types, the Java virtual machine does not. This increased flexibility in the virtual machine can be used to implement various language features. For example, covariant returns can be implemented with bridge methods; the bridge method and the method being overridden would have the same signature but different return types.”
有桥这个概念,好,那按下面方法code:
abstract class Parent<T> { abstract T x();} class Child extends Parent<String> { @Override String x() { return "abc"; }}然后编译,查看Child类的字节码,可以看到如下:
Compiled from "Child.java"public class Child extends Parent<java.lang.String> {public Child(); java.lang.String x(); java.lang.Object x();}看到了吧,其实,在编译后的字节码中,T就是Object类。这样就好理解了。
3. 所有这些其实都是二维数组
先上代码:
class Test1 { int[][] a() { return new int[0][]; } int[] b() [] { return new int[0][]; } int c() [][] { return new int[0][]; }}
上面三个变量,其实都是一样的,都是二维数组。来个更疯狂的,用到JSR-308 / Java 8 中的 type annotations,可如下code:
@Target(ElementType.TYPE_USE)@interface Crazy {} class Test { @Crazy int[][] a1 = {{}}; int @Crazy [][] a2 = {{}}; int[] @Crazy [] a3 = {{}}; @Crazy int[] b1[] = {{}}; int @Crazy [] b2[] = {{}}; int[] b3 @Crazy [] = {{}}; @Crazy int c1[][] = {{}}; int c2 @Crazy [][] = {{}}; int c3[] @Crazy [] = {{}};}
4. 你并不了解二元表达式
看下面的例子:
Object o1 = true ? new Integer(1) : new Double(2.0);Object o2;if (true) o2 = new Integer(1);else o2 = new Double(2.0);
o1和o2一样么?,答案是错误的!
写个输出语句:
System.out.println(o1.getClass() + " " + o1);System.out.println(o2.getClass() + " " + o2);输出结果是:
class java.lang.Double 1.0
class java.lang.Integer 1
如果需要提升的话,二元表达式会对数字类型自动提升!
你能想象下面的代码会报空指针异常吗?
Integer i = null;Double d = new Double(2.0);Object o = true ? i : d; // NullPointerException!System.out.println(o);
5. 你也不了解组合运算符
你觉得下面两个语句一样吗:
i += j;i = i + j;
答案是不一样!JLS(java语言规范)描述道:
“A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.”
E1 op=E2结果会强转为E1类型!所以有:
byte b = 10;b *= 5.7;System.out.println(b); // prints 57or
char ch = 'A';ch *= 1.5;System.out.println(ch); // prints 'a'
6. 随机整数
当我们执行下面的语句时:
for (int i = 0; i < 10; i++) { System.out.println((Integer) i);}
“有时候”,我们可能得到下面的结果:
12626371711324070119149193你想说,这怎么可能呢!
是的,有可能!只需要重写JDK中的java.lang.Integer.IntegerCache即可,示例代码:
import java.lang.reflect.Field;import java.util.Random;public class Entropy { public static void main(String[] args) throws Exception { // Extract the IntegerCache through reflection Class<?> clazz = Class.forName( "java.lang.Integer$IntegerCache"); Field field = clazz.getDeclaredField("cache"); field.setAccessible(true); Integer[] cache = (Integer[]) field.get(clazz); // Rewrite the Integer cache for (int i = 0; i < cache.length; i++) { cache[i] = new Integer(new Random().nextInt(cache.length)); } // Prove randomness for (int i = 0; i < 10; i++) { System.out.println((Integer) i); } }}
7. GOTO
在java中,想使用goto关键字,不能直接用,只能用continue、break等来代替实现其语义。
但是,其实,java中也有goto关键字!follow me,先code以下代码:
<pre name="code" class="java">public static void main(String[] args) { boolean check = false; label: do { // do stuff if (check) continue label; // do more stuff break label; } while(true);}然后编译,查看字节码,可以看到有:
public static void main(java.lang.String[]); Code: 0: iconst_0 1: istore_1 2: iload_1 3: ifeq 9 6: goto 2 9: return可以看到真的有goto!向前跳转ifeq,向后跳转正是goto。
8. java也有类型别名
其他语言(比如:Ceylon),可以很容易的定义类型别名:
interface People => Set<Person>;并且People和Set<Person>值可以互换:
People? p1 = null;Set<Person>? p2 = p1;People? p3 = p2;对于java,在顶层是不能这样定义类型别名的。但是我们可以在类或方法范围定义。
比如我们可以这么写来把Integer、Long分别用简写I、L替代:
class Test<I extends Integer> { public <L extends Long> void x(I i, L l) { System.out.println(i.intValue() + ", " + l.longValue()); }}在上面的代码中,我们把Integer在Test类中替换为I,把Long在x()方法中替换为L。
当然了,高手都知道,这是范型...
9. 有些类型的关系是不确定的
先定义两个类:
interface Type<T> {}class C implements Type<Type<? super C>> {}class D<P> implements Type<Type<? super D<D<P>>>> {}那么问题来了,C和D的类型是什么呢?
这其实是一种递归,类似enum类型,比如:
public class Enum<E extends Enum<E>> { }它其实是这个:
// Thisenum MyEnum {}// Is really just sugar for thisclass MyEnum extends Enum<MyEnum> { }
回到之前C,D类的问题,下面这个会编译成功么?
class Test { Type<? super C> c = new C(); Type<? super D<Byte>> d = new D<Byte>();}答案肯定是编译不过,会报Error:java: java.lang.StackOverflowError,甚至eclipse下这么写会crash!
其实下面两个问题是不确定的:
(1) C 是 Type<? super C> 的子类吗?
Step 0) C <?: Type<? super C>Step 1) Type<Type<? super C>> <?: Type (inheritance)Step 2) C (checking wildcard ? super C)Step . . . (cycle forever)(2)D 是 Type<? super D<Byte>> 的子类吗?
Step 0) D<Byte> <?: Type<? super C<Byte>>Step 1) Type<Type<? super D<D<Byte>>>> <?: Type<? super D<Byte>>Step 2) D<Byte> <?: Type<? super D<D<Byte>>>Step 3) Type<type<? super C<C>>> <?: Type<? super C<C>>Step 4) D<D<Byte>> <?: Type<? super D<D<Byte>>>Step . . . (expand forever)
10 类型交集
java中有个很奇怪的特性叫类型交集,就是你可以声明一个是两个类型交集的(范型)类。举例:
class Test<T extends Serializable & Cloneable> {}那么Test类实例中的范型参数T必须同时实现Serializable和Cloneable,必须String类就不行,Date类则可以。
// Doesn't compileTest<String> s = null; // CompilesTest<Date> d = null;
或者,还可以这么用:
<T extends Runnable & Serializable> void execute(T t) {}配合java8下的lambda表达式使用:
execute((Serializable) (() -> {}));execute((Runnable & Serializable) (() -> {}));
完毕!
英文原文:https://blog.jooq.org/2014/11/03/10-things-you-didnt-know-about-java/
- 关于java-10件你不知道的事
- 关于JAVA你所不知道的10件事
- 关于Java你可能不知道的10件事
- Java关于多线程你不知道的5件事
- 关于Google你可能不知道的10件事
- 关于PHP你可能不知道的10件事
- 关于PHP你可能不知道的10件事
- 关于PHP你可能不知道的10件事
- 关于PHP你可能不知道的10件事
- 你不知道java的10件事
- 你不知道Java的10件事
- 关于《越狱》,你不知道的5件事
- 关于《越狱》,你不知道的5件事
- 关于程序猿,你不知道的15件事
- 关于程序猿,你不知道的15件事
- 关于邵逸夫:你可能不知道的8件事
- 关于Go,十件你可能不知道的事
- 关于安卓你不知道的6件事
- [从头读历史] 第286节 神之物语 阿耳戈英雄们的故事
- Android短信Mms发送流程
- POJO和javabean的异同
- Vuforia VideoDemo 每次触发视频重新播放
- CSS命名BEM规范
- 关于java-10件你不知道的事
- EAS科目变更辅助账的规律
- 【PM】产品需求管理
- Cocoapods 关于Updating local specs repositories的问题和单独更新/加载某一个库的方法
- Mycat 数据库分库分表中间件
- Nodejs使用mysql
- Android中隐式Intent以及Intent-filter详解 和匹配规则
- 基于caffe在已有模型上进行微调finetune
- The Clocks(暴力搜索)