钦州网站建设设计,企业查询信息系统,二建报考条件,百度一下电脑版首页java多线程做一件事那么#xff0c;您从一开始就一直在使用Java#xff1f; 还记得那些被称为“ Oak”的日子#xff0c;OO仍然是热门话题#xff0c;C 人士认为Java没有机会#xff0c;Applet还是一件事吗#xff1f; 我敢打赌#xff0c;您至少不了解以下一半内容。 … java多线程做一件事 那么您从一开始就一直在使用Java 还记得那些被称为“ Oak”的日子OO仍然是热门话题C 人士认为Java没有机会Applet还是一件事吗 我敢打赌您至少不了解以下一半内容。 让我们从本周开始对Java的内部运作产生一些惊喜。 1.没有被检查的异常 那就对了 JVM不知道任何这样的事情只有Java语言知道。 今天每个人都同意检查异常是一个错误。 正如Bruce Eckel在布拉格GeeCON闭幕致辞中所说的那样在Java参与使用受检查的异常之后没有其他语言可以使用甚至Java 8也不再将它们包含在新的Streams API中 这可能有些痛苦当您的lambda使用IO或JDBC时 。 您是否想要证明JVM不知道这样的事情 尝试以下代码 public class Test {// No throws clause herepublic static void main(String[] args) {doThrow(new SQLException());}static void doThrow(Exception e) {Test.RuntimeException doThrow0(e);}SuppressWarnings(unchecked)static E extends Exception void doThrow0(Exception e) throws E {throw (E) e;}
} 这不仅会编译而且实际上还会引发SQLException 您甚至不需要Lombok的SneakyThrows 。 关于以上内容的更多详细信息可以在本文中或此处的Stack Overflow上找到 。 2.您可以使方法重载仅在返回类型上有所不同 那不会编译对吗 class Test {Object x() { return abc; }String x() { return 123; }
} 对。 Java语言不允许在同一个类中将两个方法“替代等效” 无论它们的throws子句或return类型可能如何不同。 但是请稍等。 Class.getMethod(String, Class...)出Class.getMethod(String, Class...)的Javadoc。 内容为 请注意一个类中可能有多个匹配方法因为Java语言禁止一个类声明具有相同签名但返回类型不同的多个方法而Java虚拟机却没有。 虚拟机中这种增加的灵活性可用于实现各种语言功能。 例如协变收益可以通过桥接方法实现 bridge方法和被重写的方法将具有相同的签名但返回类型不同。 哇是的这很有意义。 实际上这几乎就是您编写以下内容时发生的情况 abstract class ParentT {abstract T x();
}class Child extends ParentString {OverrideString x() { return abc; }
} 在Child检查生成的字节码 // Method descriptor #15 ()Ljava/lang/String;// Stack: 1, Locals: 1java.lang.String x();0 ldc String abc [16]2 areturnLine numbers:[pc: 0, line: 7]Local variable table:[pc: 0, pc: 3] local: this index: 0 type: Child// Method descriptor #18 ()Ljava/lang/Object;// Stack: 1, Locals: 1bridge synthetic java.lang.Object x();0 aload_0 [this]1 invokevirtual Child.x() : java.lang.String [19]4 areturnLine numbers:[pc: 0, line: 1] 因此 T实际上只是字节码中的Object 。 很好理解。 合成桥方法实际上是由编译器生成的因为在某些调用位置可能期望Parent.x()签名的返回类型为Object 。 如果没有这种桥接方法则以二进制兼容的方式添加泛型是不可能的。 因此更改JVM以使其具有此功能的痛苦就较小这也使协变量重载成为副作用……聪明吧 您是否熟悉语言细节和内部知识 然后在这里找到一些更有趣的细节 。 3.所有这些都是二维数组 class Test {int[][] a() { return new int[0][]; }int[] b() [] { return new int[0][]; }int c() [][] { return new int[0][]; }
} 对是真的。 即使您的心理分析器可能无法立即理解上述方法的返回类型它们也是相同的 类似于以下代码 class Test {int[][] a {{}};int[] b[] {{}};int c[][] {{}};
} 你觉得这很疯狂吗 想象一下在上面使用JSR-308 / Java 8类型注释 。 句法可能性的数量激增 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);
elseo2 new Double(2.0); 不。 让我们进行快速测试 System.out.println(o1);
System.out.println(o2); 该程序将打印 1.0
1 是的 有条件的运营商将实现数字式的推广如果“被需要”与认为“需要”一个非常非常非常强的引号。 因为您希望该程序抛出NullPointerException吗 Integer i new Integer(1);
if (i.equals(1))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指定 形式为E1 op E2的复合赋值表达式等效于E1 TE1opE2其中T是E1的类型只是E1仅被评估一次。 这是如此美丽我想引用Peter Lawrey 对这个Stack Overflow问题的回答 这种转换的一个很好的例子是使用* 或/ byte b 10;
b * 5.7;
System.out.println(b); // prints 57 要么 byte b 100;
b / 2.5;
System.out.println(b); // prints 40 要么 char ch 0;
ch * 1.1;
System.out.println(ch); // prints 4 要么 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);
} …然后“有时”我得到以下输出 92
221
45
48
236
183
39
193
33
84 这怎么可能呢 。 。 。 。 。 。 扰流板...未来的解决方案... 。 。 。 。 。 好的解决方案就在这里 它与通过反射覆盖JDK的Integer缓存有关然后使用自动装箱和自动拆箱。 不要在家做 换句话说让我们再这样考虑一下 当我这样做时我的四周假期前的最后一次提交 7.转到 这是我的最爱之一。 Java有GOTO 输入... int goto 1; 这将导致 Test.java:44: error: identifier expectedint goto 1;^ 这是因为goto是未使用的关键字 以防万一…… 但这不是令人兴奋的部分。 令人兴奋的部分是您实际上可以使用break continue和带标签的块来实现goto 向前跳 label: {// do stuffif (check) break label;// do more stuff
} 在字节码中 2 iload_1 [check]
3 ifeq 6 // Jumping forward
6 .. 向后跳 label: do {// do stuffif (check) continue label;// do more stuffbreak label;
} while(true); 在字节码中 2 iload_1 [check]3 ifeq 96 goto 2 // Jumping backward9 ..8. Java具有类型别名 在其他语言 例如Ceylon 中我们可以非常轻松地定义类型别名 interface People SetPerson; 这样构造的People类型可以与SetPerson互换使用 People? p1 null;
SetPerson? p2 p1;
People? p3 p2; 在Java中我们不能在顶级定义类型别名。 但是我们可以在类或方法的范围内这样做。 让我们考虑一下我们对Integer Long等的命名不满意我们希望使用更短的名称 I和L 简单 class TestI extends Integer {L extends Long void x(I i, L l) {System.out.println(i.intValue() , l.longValue());}
} 在上述程序中对于Test类的范围 Integer被“别名”到I 而对于x()方法的范围 Long被“别名”到L 然后我们可以像上面这样调用上面的方法 new Test().x(1, 2L); 当然这种技术不应被认真对待。 在这种情况下 Integer和Long都是最终类型这意味着类型I和L 实际上是别名几乎赋值兼容只是一种方式。 如果我们使用了非最终类型例如Object 那么我们真的会使用普通的泛型。 这些愚蠢的把戏足够了。 现在换个真正了不起的东西 9.一些类型关系是不确定的 好吧现在这将变得非常时髦因此可以喝杯咖啡并集中精力。 请考虑以下两种类型 // A helper type. You could also just use List
interface TypeT {}class C implements TypeType? super C {}
class DP implements TypeType? super DDP {} 现在类型C和D甚至意味着什么 它们有些递归以类似于java.lang.Enum递归的方式但略有不同。 考虑 public abstract class EnumE extends EnumE { ... } 使用以上规范实际的enum实现仅仅是语法糖 // This
enum MyEnum {}// Is really just sugar for this
class MyEnum extends EnumMyEnum { ... } 考虑到这一点让我们回到两种类型。 以下内容可以编译吗 class Test {Type? super C c new C();Type? super DByte d new DByte();
} 艰苦的问题 罗斯·泰特 Ross Tate有了答案。 这个问题实际上是无法确定的 C是Type 的子类型吗 超级C Step 0) C ?: Type? super C
Step 1) TypeType? super C ?: Type (inheritance)
Step 2) C (checking wildcard ? super C)
Step . . . (cycle forever) 然后 D是Type 的子类型吗 超级D Byte Step 0) DByte ?: Type? super CByte
Step 1) TypeType? super DDByte ?: Type? super DByte
Step 2) DByte ?: Type? super DDByte
Step 3) ListList? super CC ?: List? super CC
Step 4) DDByte ?: Type? super DDByte
Step . . . (expand forever) 尝试在Eclipse中编译以上代码它将崩溃 不用担心。我已经提交了一个错误 让它沉入…… Java中的某些类型关系是不确定的 如果您对有关此奇特的Java怪癖的更多详细信息感兴趣请阅读Ross Tate的论文“在Java的类型系统中驯服通配符” 与Alan Leung和Sorin Lerner合着或者阅读我们自己关于将子类型多态与泛型多态相关联的想法。 10.类型交点 Java具有一个非常独特的功能称为类型交集。 您可以声明一个通用类型它实际上是两种类型的交集。 例如 class TestT extends Serializable Cloneable {
} 泛型类型参数T 你绑定的类的实例Test必须实现 Serializable和Cloneable 。 例如 String不是可能的绑定但Date是 // Doesnt compile
TestString s null;// Compiles
TestDate d null; Java 8中已重用了此功能您现在可以在其中将类型转换为临时类型的交集。 这有什么用 几乎没有但是如果您想将lambda表达式强制为这种类型则别无选择。 假设您的方法受到这种疯狂的类型约束 T extends Runnable Serializable void execute(T t) {} 您想要一个可Serializable的Runnable 以防您想在其他地方执行它并通过电线发送它。 Lambda和序列化有点古怪。 Lambda可以序列化 如果lambda表达式的目标类型和捕获的参数可序列化则可以对其进行序列化 但是即使这是真的他们也不会自动实现Serializable标记接口。 要强制他们使用这种类型必须强制转换。 但是当您只转换为Serializable ... execute((Serializable) (() - {})); …然后lambda将不再可运行。 嗯... 所以… 将其强制转换为两种类型 execute((Runnable Serializable) (() - {}));结论 我通常只说这是关于SQL的问题但现在该是一篇包含以下内容的文章了 Java是仅凭其强大功能就无法解开谜底的设备。 翻译自: https://www.javacodegeeks.com/2014/11/10-things-you-didnt-know-about-java.htmljava多线程做一件事