java多线程做一件事_关于Java的十件事
java多線程做一件事
那么,您從一開始就一直在使用Java? 還記得那些被稱為“ Oak”的日子,OO仍然是熱門話題,C ++人士認(rèn)為Java沒有機(jī)會(huì),Applet還是一件事嗎?
我敢打賭,您至少不了解以下一半內(nèi)容。 讓我們從本周開始,對(duì)Java的內(nèi)部運(yùn)作產(chǎn)生一些驚喜。
1.沒有被檢查的異常
那就對(duì)了! JVM不知道任何這樣的事情,只有Java語(yǔ)言知道。
今天,每個(gè)人都同意檢查異常是一個(gè)錯(cuò)誤。 正如Bruce Eckel在布拉格GeeCON閉幕致辭中所說的那樣,在Java參與使用受檢查的異常之后,沒有其他語(yǔ)言可以使用,甚至Java 8也不再將它們包含在新的Streams API中( 這可能有些痛苦,當(dāng)您的lambda使用IO或JDBC時(shí) )。
您是否想要證明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;} }這不僅會(huì)編譯,而且實(shí)際上還會(huì)引發(fā)SQLException ,您甚至不需要Lombok的@SneakyThrows 。
- 關(guān)于以上內(nèi)容的更多詳細(xì)信息,可以在本文中或此處的Stack Overflow上找到 。
2.您可以使方法重載僅在返回類型上有所不同
那不會(huì)編譯,對(duì)嗎?
class Test {Object x() { return "abc"; }String x() { return "123"; } }對(duì)。 Java語(yǔ)言不允許在同一個(gè)類中將兩個(gè)方法“替代等效” ,無論它們的throws子句或return類型可能如何不同。
但是請(qǐng)稍等。 Class.getMethod(String, Class...)出Class.getMethod(String, Class...)的Javadoc。 內(nèi)容為:
請(qǐng)注意,一個(gè)類中可能有多個(gè)匹配方法,因?yàn)镴ava語(yǔ)言禁止一個(gè)類聲明具有相同簽名但返回類型不同的多個(gè)方法,而Java虛擬機(jī)卻沒有。 虛擬機(jī)中這種增加的靈活性可用于實(shí)現(xiàn)各種語(yǔ)言功能。 例如,協(xié)變收益可以通過橋接方法實(shí)現(xiàn); bridge方法和被重寫的方法將具有相同的簽名,但返回類型不同。
哇,是的,這很有意義。 實(shí)際上,這幾乎就是您編寫以下內(nèi)容時(shí)發(fā)生的情況:
abstract class Parent<T> {abstract T x(); }class Child extends Parent<String> {@OverrideString x() { return "abc"; } }在Child檢查生成的字節(jié)碼:
// 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實(shí)際上只是字節(jié)碼中的Object 。 很好理解。
合成橋方法實(shí)際上是由編譯器生成的,因?yàn)樵谀承┱{(diào)用位置可能期望Parent.x()簽名的返回類型為Object 。 如果沒有這種橋接方法,則以二進(jìn)制兼容的方式添加泛型是不可能的。 因此,更改JVM以使其具有此功能的痛苦就較小(這也使協(xié)變量重載成為副作用……)聰明吧?
您是否熟悉語(yǔ)言細(xì)節(jié)和內(nèi)部知識(shí)? 然后在這里找到一些更有趣的細(xì)節(jié) 。
3.所有這些都是二維數(shù)組!
class Test {int[][] a() { return new int[0][]; }int[] b() [] { return new int[0][]; }int c() [][] { return new int[0][]; } }對(duì),是真的。 即使您的心理分析器可能無法立即理解上述方法的返回類型,它們也是相同的! 類似于以下代碼:
class Test {int[][] a = {{}};int[] b[] = {{}};int c[][] = {{}}; }你覺得這很瘋狂嗎? 想象一下在上面使用JSR-308 / Java 8類型注釋 。 句法可能性的數(shù)量激增!
@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 [] = {{}}; }輸入注釋。 僅憑其力量超越神秘感的設(shè)備
換句話說:
當(dāng)我這樣做時(shí),我的四周假期前的最后一次提交
我將為您找到上述任何一個(gè)用例的實(shí)際練習(xí)。
4.您沒有條件表達(dá)式
因此,您認(rèn)為使用條件表達(dá)式時(shí)就知道這一切嗎? 我告訴你,你沒有。 你們大多數(shù)人會(huì)認(rèn)為以下兩個(gè)片段是等效的:
Object o1 = true ? new Integer(1) : new Double(2.0);…一樣嗎?
Object o2;if (true)o2 = new Integer(1); elseo2 = new Double(2.0);不。 讓我們進(jìn)行快速測(cè)試
System.out.println(o1); System.out.println(o2);該程序?qū)⒋蛴?#xff1a;
1.0 1是的 有條件的運(yùn)營(yíng)商將實(shí)現(xiàn)數(shù)字式的推廣,如果“被需要”,與認(rèn)為“需要”一個(gè)非常非常非常強(qiáng)的引號(hào)。 因?yàn)?#xff0c;您希望該程序拋出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);- 有關(guān)上述內(nèi)容的更多信息,請(qǐng)參見此處 。
5.您也沒有得到復(fù)合賦值運(yùn)算符
夠古怪嗎? 讓我們考慮以下兩段代碼:
i += j; i = i + j;憑直覺,它們應(yīng)該等效,對(duì)嗎? 但猜猜怎么了。 他們不是! JLS指定:
形式為E1 op = E2的復(fù)合賦值表達(dá)式等效于E1 =(T)(((E1)op(E2))),其中T是E1的類型,只是E1僅被評(píng)估一次。
這是如此美麗,我想引用Peter Lawrey 對(duì)這個(gè)Stack Overflow問題的回答 :
這種轉(zhuǎn)換的一個(gè)很好的例子是使用* =或/ =
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'現(xiàn)在,這有多么有用? 我將在我的應(yīng)用程序中強(qiáng)制轉(zhuǎn)換/乘法字符。 因?yàn)?#xff0c;你知道...
6.隨機(jī)整數(shù)
現(xiàn)在,這更像是一個(gè)難題。 尚未閱讀解決方案。 看看您是否可以自己找到這個(gè)。 當(dāng)我運(yùn)行以下程序時(shí):
for (int i = 0; i < 10; i++) {System.out.println((Integer) i); }…然后“有時(shí)”,我得到以下輸出:
92 221 45 48 236 183 39 193 33 84這怎么可能呢??
。
。
。
。
。
。 擾流板...未來的解決方案...
。
。
。
。
。
好的,解決方案就在這里 ,它與通過反射覆蓋JDK的Integer緩存有關(guān),然后使用自動(dòng)裝箱和自動(dòng)拆箱。 不要在家做! 換句話說,讓我們?cè)龠@樣考慮一下
當(dāng)我這樣做時(shí),我的四周假期前的最后一次提交
7.轉(zhuǎn)到
這是我的最愛之一。 Java有GOTO! 輸入...
int goto = 1;這將導(dǎo)致:
Test.java:44: error: <identifier> expectedint goto = 1;^這是因?yàn)間oto是未使用的關(guān)鍵字 ,以防萬一……
但這不是令人興奮的部分。 令人興奮的部分是,您實(shí)際上可以使用break , continue和帶標(biāo)簽的塊來實(shí)現(xiàn)goto:
向前跳
label: {// do stuffif (check) break label;// do more stuff }在字節(jié)碼中:
2 iload_1 [check] 3 ifeq 6 // Jumping forward 6 ..向后跳
label: do {// do stuffif (check) continue label;// do more stuffbreak label; } while(true);在字節(jié)碼中:
2 iload_1 [check]3 ifeq 96 goto 2 // Jumping backward9 ..8. Java具有類型別名
在其他語(yǔ)言( 例如Ceylon )中,我們可以非常輕松地定義類型別名:
interface People => Set<Person>;這樣構(gòu)造的People類型可以與Set<Person>互換使用:
People? p1 = null; Set<Person>? p2 = p1; People? p3 = p2;在Java中,我們不能在頂級(jí)定義類型別名。 但是我們可以在類或方法的范圍內(nèi)這樣做。 讓我們考慮一下,我們對(duì)Integer , Long等的命名不滿意,我們希望使用更短的名稱: I和L 簡(jiǎn)單:
class Test<I extends Integer> {<L extends Long> void x(I i, L l) {System.out.println(i.intValue() + ", " + l.longValue());} }在上述程序中,對(duì)于Test類的范圍, Integer被“別名”到I ,而對(duì)于x()方法的范圍, Long被“別名”到L 然后我們可以像上面這樣調(diào)用上面的方法:
new Test().x(1, 2L);當(dāng)然,這種技術(shù)不應(yīng)被認(rèn)真對(duì)待。 在這種情況下, Integer和Long都是最終類型,這意味著類型I和L 實(shí)際上是別名(幾乎,賦值兼容只是一種方式)。 如果我們使用了非最終類型(例如Object ),那么我們真的會(huì)使用普通的泛型。
這些愚蠢的把戲足夠了。 現(xiàn)在換個(gè)真正了不起的東西!
9.一些類型關(guān)系是不確定的!
好吧,現(xiàn)在這將變得非常時(shí)髦,因此可以喝杯咖啡并集中精力。 請(qǐng)考慮以下兩種類型:
// A helper type. You could also just use List interface Type<T> {}class C implements Type<Type<? super C>> {} class D<P> implements Type<Type<? super D<D<P>>>> {}現(xiàn)在,類型C和D甚至意味著什么?
它們有些遞歸,以類似于java.lang.Enum遞歸的方式(但略有不同)。 考慮:
public abstract class Enum<E extends Enum<E>> { ... }使用以上規(guī)范,實(shí)際的enum實(shí)現(xiàn)僅僅是語(yǔ)法糖:
// This enum MyEnum {}// Is really just sugar for this class MyEnum extends Enum<MyEnum> { ... }考慮到這一點(diǎn),讓我們回到兩種類型。 以下內(nèi)容可以編譯嗎?
class Test {Type<? super C> c = new C();Type<? super D<Byte>> d = new D<Byte>(); }艱苦的問題, 羅斯·泰特 ( Ross Tate)有了答案。 這個(gè)問題實(shí)際上是無法確定的:
C是Type <的子類型嗎? 超級(jí)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)然后:
D是Type <的子類型嗎? 超級(jí)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) List<List<? super C<C>>> <?: List<? super C<C>> Step 4) D<D<Byte>> <?: Type<? super D<D<Byte>>> Step . . . (expand forever)嘗試在Eclipse中編譯以上代碼,它將崩潰! ( 不用擔(dān)心。我已經(jīng)提交了一個(gè)錯(cuò)誤 )
讓它沉入……
Java中的某些類型關(guān)系是不確定的 !
如果您對(duì)有關(guān)此奇特的Java怪癖的更多詳細(xì)信息感興趣,請(qǐng)閱讀Ross Tate的論文“在Java的類型系統(tǒng)中馴服通配符” (與Alan Leung和Sorin Lerner合著),或者閱讀我們自己關(guān)于將子類型多態(tài)與泛型多態(tài)相關(guān)聯(lián)的想法。
10.類型交點(diǎn)
Java具有一個(gè)非常獨(dú)特的功能,稱為類型交集。 您可以聲明一個(gè)(通用)類型,它實(shí)際上是兩種類型的交集。 例如:
class Test<T extends Serializable & Cloneable> { }泛型類型參數(shù)T ,你綁定的類的實(shí)例Test必須實(shí)現(xiàn) Serializable和Cloneable 。 例如, String不是可能的綁定,但Date是:
// Doesn't compile Test<String> s = null;// Compiles Test<Date> d = null;Java 8中已重用了此功能,您現(xiàn)在可以在其中將類型轉(zhuǎn)換為臨時(shí)類型的交集。 這有什么用? 幾乎沒有,但是如果您想將lambda表達(dá)式強(qiáng)制為這種類型,則別無選擇。 假設(shè)您的方法受到這種瘋狂的類型約束:
<T extends Runnable & Serializable> void execute(T t) {}您想要一個(gè)可Serializable的Runnable ,以防您想在其他地方執(zhí)行它并通過電線發(fā)送它。 Lambda和序列化有點(diǎn)古怪。
Lambda可以序列化 :
如果lambda表達(dá)式的目標(biāo)類型和捕獲的參數(shù)可序列化,則可以對(duì)其進(jìn)行序列化
但是,即使這是真的,他們也不會(huì)自動(dòng)實(shí)現(xiàn)Serializable標(biāo)記接口。 要強(qiáng)制他們使用這種類型,必須強(qiáng)制轉(zhuǎn)換。 但是當(dāng)您只轉(zhuǎn)換為Serializable ...
execute((Serializable) (() -> {}));…然后,lambda將不再可運(yùn)行。
嗯...
所以…
將其強(qiáng)制轉(zhuǎn)換為兩種類型:
execute((Runnable & Serializable) (() -> {}));結(jié)論
我通常只說這是關(guān)于SQL的問題,但現(xiàn)在該是一篇包含以下內(nèi)容的文章了:
Java是僅憑其強(qiáng)大功能就無法解開謎底的設(shè)備。
翻譯自: https://www.javacodegeeks.com/2014/11/10-things-you-didnt-know-about-java.html
java多線程做一件事
總結(jié)
以上是生活随笔為你收集整理的java多线程做一件事_关于Java的十件事的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 街道办事处备案(住房街道备案)
- 下一篇: ddos反射攻击原理(ddos 反射攻击