摘要:三元操作符類(lèi)型的轉(zhuǎn)換規(guī)則若兩個(gè)操作數(shù)不可轉(zhuǎn)換,則不做轉(zhuǎn)換,返回值為類(lèi)型。若兩個(gè)操作數(shù)都是直接量數(shù)字,則返回值類(lèi)型為范圍較大者。
三元操作符類(lèi)型的轉(zhuǎn)換規(guī)則:
(1)若兩個(gè)操作數(shù)不可轉(zhuǎn)換,則不做轉(zhuǎn)換,返回值為Object類(lèi)型。
(2)若兩個(gè)操作數(shù)是明確類(lèi)型的表達(dá)式(比如變量),則按照正常的二進(jìn)制數(shù)字來(lái)轉(zhuǎn)換,int類(lèi)型轉(zhuǎn)換為long類(lèi)型,long類(lèi)型轉(zhuǎn)換為float類(lèi)型等。
(3)若兩個(gè)操作數(shù)中有一個(gè)數(shù)字S,另外一個(gè)是表達(dá)式,且其類(lèi)型標(biāo)示為T(mén),那么,若數(shù)字S在T的范圍內(nèi),則轉(zhuǎn)換為T(mén)類(lèi)型;若S超出T類(lèi)型的范圍,則T轉(zhuǎn)換為S類(lèi)型。
(4)若兩個(gè)操作數(shù)都是直接量數(shù)字,則返回值類(lèi)型為范圍較大者。
示例代碼:
@Test public void test() { int i = 80; String s1 = String.valueOf(i < 100 ? 90 : 100); String s2 = String.valueOf(i < 100 ? 90 : 100.0); System.out.println("s1=" + s1); System.out.println("s2=" + s2); }
結(jié)果:
s1=90 s2=90.0
結(jié)論:三元操作符的類(lèi)型務(wù)必一致
clone方法拷貝規(guī)則clone方法提供的是一種淺拷貝方式,也就是說(shuō)它并不會(huì)把對(duì)象的所有屬性全部拷貝一份,而是選擇性的拷貝,它的拷貝規(guī)則如下:
(1)基本變量:如果變量是基本類(lèi)型,則拷貝其值,比如int、float等
(2)對(duì)象:如果變量是一個(gè)實(shí)例對(duì)象,則拷貝地址引用,也就是說(shuō)此時(shí)新拷貝出來(lái)的對(duì)象與原有對(duì)象共享改實(shí)例變量,不受訪(fǎng)問(wèn)權(quán)限的控制。
(3)String字符串:這個(gè)比較特殊,拷貝的也是一個(gè)地址,是個(gè)引用,但是在修改時(shí),它會(huì)從字符串池中重新生成新的字符串,原有的字符串對(duì)象保持不變,在此處我們可以認(rèn)為String是一個(gè)基本類(lèi)型
示例代碼:
@Test public void test() { //定義父親 Person father = new Person("父親"); //定義大兒子 Person s1 = new Person("大兒子", father); //小兒子的信息是通過(guò)大兒子拷貝過(guò)來(lái)的 Person s2 = s1.clone(); s2.setName("小兒子"); System.out.println(s1.getName() + " 的父親是 " + s1.getFather().getName()); System.out.println(s2.getName() + " 的父親是 " + s2.getFather().getName()); s1.getFather().setName("干爹"); System.out.println(s1.getName() + " 的父親是 " + s1.getFather().getName()); System.out.println(s2.getName() + " 的父親是 " + s2.getFather().getName()); }
輔助類(lèi):
class Person implements Cloneable { //姓名 private String name; //父親 private Person father; public Person(String _name) { name = _name; } public Person(String _name, Person _parent) { name = _name; father = _parent; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Person getFather() { return father; } public void setFather(Person father) { this.father = father; } //拷貝的實(shí)現(xiàn) @Override public Person clone() { Person p = null; try { //淺拷貝 p = (Person) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return p; } }
結(jié)果:
大兒子 的父親是 父親 小兒子 的父親是 父親 大兒子 的父親是 干爹 小兒子 的父親是 干爹
結(jié)論:淺拷貝只是Java提供的一種簡(jiǎn)單拷貝機(jī)制,不便于直接使用
字符串池:創(chuàng)建一個(gè)字符串時(shí),首先檢查池中是否有字面值相等的字符串,如果有,則不再創(chuàng)建,直接返回池中該對(duì)象的引用,若沒(méi)有則創(chuàng)建之,然后放到池里,并返回新創(chuàng)建對(duì)象的引用。
示例代碼:
@Test public void test(){ String str1 = "中國(guó)"; String str2 = "中國(guó)"; String str3 = new String("中國(guó)"); String str4 = str3.intern(); //兩個(gè)直接量是否相等 boolean b1 = (str1 == str2); //直接量和對(duì)象是否相等 //直接聲明一個(gè)String對(duì)象(new String)是不會(huì)檢查字符串池的,也不會(huì)把對(duì)象放到池里 boolean b2 = (str1 == str3); //經(jīng)過(guò)intern處理后的對(duì)象與直接量是否相等 //intern會(huì)檢查當(dāng)前的對(duì)象在對(duì)象池(自己理解:字符串池)中是否有字面值相同的引用對(duì)象,如果有則返回池中對(duì)象,如果沒(méi)有則放置到對(duì)象池中,并返回當(dāng)前對(duì)象 boolean b3 = (str1 == str4); System.out.println(b1); System.out.println(b2); System.out.println(b3); }
結(jié)果:
true false true
結(jié)論:推薦使用String直接量賦值
String類(lèi)是一個(gè)不可變對(duì)象:(1)String類(lèi)是final類(lèi),不可繼承,不可能產(chǎn)生一個(gè)String子類(lèi)
(2)在String類(lèi)提供的所有方法中,如果有String返回值,就會(huì)新建一個(gè)String對(duì)象,不對(duì)原對(duì)象進(jìn)行修改,這也保證了元對(duì)象是不可改變的。
(1)使用String類(lèi)的場(chǎng)景:在字符串不經(jīng)常變化的場(chǎng)景中可以使用String類(lèi),例如常量的聲明、少量的變量運(yùn)算等。
(2)使用StringBuffer類(lèi)的場(chǎng)景:在頻繁進(jìn)行字符串的運(yùn)算(如拼接、替換、刪除等),并且運(yùn)行在多線(xiàn)程的環(huán)境中,則可以考慮使用StringBuffer,例如XML解析、HTTP參數(shù)解析和封裝等。
(3)使用StringBuilder類(lèi)的場(chǎng)景:在頻繁進(jìn)行字符串的運(yùn)算(如拼接、替換、刪除等),并且運(yùn)行在單線(xiàn)程的環(huán)境中,則可以考慮使用StringBuilder,如SQL語(yǔ)句的拼裝、JSON封裝等。
在使用加號(hào)進(jìn)行計(jì)算的表達(dá)式中,只要遇到String字符串,則所有的數(shù)據(jù)都會(huì)轉(zhuǎn)成String類(lèi)型進(jìn)行拼接,如果是原始數(shù)據(jù),則直接拼接,如果是對(duì)象,則調(diào)用toString方法的返回值然后拼接
示例代碼:
@Test public void test(){ String str1 = 1 + 2 + " apples"; String str2 = "apples:" + 1 + 2; System.out.println(str1); System.out.println(str2); }
結(jié)果:
3 apples apples:12
結(jié)論:在"+"表達(dá)式中,String字符串具有最高優(yōu)先級(jí)
ArrayList與LinkedListArrayList:
插入:只要插入一個(gè)元素,其后的元素就會(huì)向后移動(dòng)一位,雖然arrayCopy是一個(gè)本地方法,效率非常高, 但頻繁的插入,每次后面的元素都要拷貝一遍,效率就變低了,特別是在頭位置插入元素時(shí)。 刪除:index位置后的元素都要向前移動(dòng)一位,最后一個(gè)位置空出來(lái)了,這又是一次數(shù)組拷貝,和插入一樣, 如果數(shù)據(jù)量大,刪除動(dòng)作必然會(huì)暴露出性能和效率方面的問(wèn)題。 修改:直接替換
LinkedList:
插入:把自己插入到鏈表,然后再把前節(jié)點(diǎn)的next和后節(jié)點(diǎn)的previous指向自己。 刪除:沒(méi)有任何耗時(shí)的操作,全部是引用指針的變更,效率自然高了。 修改:定位方式會(huì)折半遍歷,這是一個(gè)極耗時(shí)的操作。
總結(jié):
LinkedList的插入效率比ArrayList快50倍以上。 LinkedList在處理大批量的刪除動(dòng)作時(shí)比ArrayList快40倍以上。 修改元素,在這一點(diǎn)上LinkedList輸給了ArrayList
結(jié)論:頻繁插入和刪除時(shí)使用LinkedList
subList方法實(shí)現(xiàn)原理它返回的SubList類(lèi)也是AbstractList的子類(lèi),其所以的方法如get、set、add、remove等都是在原始列表上的操作,它自身并沒(méi)有生成一個(gè)數(shù)組或是鏈表,也就是子列表只是原列表的一個(gè)視圖,所有的修改動(dòng)作都反映在了原始列表上。
示例代碼:
@Test public void test(){ //定義一個(gè)包含兩個(gè)字符串的列表 Listlist = new ArrayList<>(2); list.add("A"); list.add("B"); //構(gòu)造一個(gè)包含list列表的字符串列表 List list2 = new ArrayList<>(list); System.out.println("list == list2? " + list.equals(list2)); //subList生成與list相同的列表 List list3 = list.subList(0, list.size()); //list3增加一個(gè)元素 list3.add("C"); System.out.println("list == list2? " + list.equals(list2)); System.out.println("list == list3? " + list.equals(list3)); System.out.println(list.size()); }
結(jié)果:
list == list2? true list == list2? false list == list3? true 3
結(jié)論:subList產(chǎn)生的列表只是一個(gè)視圖,所有的修改動(dòng)作直接作用于原列表
編譯后泛型類(lèi)型轉(zhuǎn)換規(guī)則(1)List
(2)List
(3)List extends E>、List super E>擦除后的類(lèi)型為L(zhǎng)ist
(4)List
(1)無(wú)構(gòu)造函數(shù):Class對(duì)象是在加載類(lèi)時(shí)由Java虛擬機(jī)通過(guò)調(diào)用類(lèi)加載器中的defineClass方法自動(dòng)構(gòu)造的。
(2)可以描述基本類(lèi)型:例如可以使用int.class表示int表示類(lèi)型的類(lèi)對(duì)象
(3)其對(duì)象都是單例模式:一個(gè)Class的實(shí)例可以描述一個(gè)類(lèi),并且只描述一個(gè)類(lèi),反過(guò)來(lái)也成立,一個(gè)類(lèi)只有一個(gè)Class實(shí)例對(duì)象
示例代碼:
@Test public void test() { //類(lèi)的屬性class所引用的對(duì)象與實(shí)例對(duì)象的getClass返回值相同 System.out.println(String.class.equals(new String("").getClass())); System.out.println("ABC".getClass().equals(String.class)); //class實(shí)例對(duì)象不區(qū)分泛型 System.out.println(ArrayList.class.equals(new ArrayList().getClass())); }
結(jié)果:
true true true獲得一個(gè)Class對(duì)象的三種路徑
(1)類(lèi)屬性方式,如String.class
(2)對(duì)象的getClass方法,如new String().getClass()
(3)forName方法加載,如Class.forName("java.lang.String")
getMethod方法獲得的是所以public訪(fǎng)問(wèn)級(jí)別的方法,包括從父類(lèi)繼承的方法
getDeclareMethod方法獲得的是自身類(lèi)的所有方法,包括public、private方法,而且不受限于訪(fǎng)問(wèn)權(quán)限
示例代碼:
@Test public void test() throws NoSuchMethodException { //方法名稱(chēng) String methodName = "doStuff"; Method m1 = Foo.class.getDeclaredMethod(methodName); Method m2 = Foo.class.getMethod(methodName); //Exception in thread "main" java.lang.NoSuchMethodException } //靜態(tài)內(nèi)部類(lèi) static class Foo{ void doStuff(){} }
結(jié)果:
java.lang.NoSuchMethodException
結(jié)論:適時(shí)選擇getDeclaredXXX和getXXX
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68038.html
摘要:上設(shè)置環(huán)境變量,隨便一搜一大堆,不在啰嗦設(shè)置完之后,測(cè)試,找不到命令。再回頭看變量界面,剛才被我刪除引號(hào)的一個(gè)變量,變成了兩個(gè)終于明白怎么回事了,中,會(huì)根據(jù)分好來(lái)分割每個(gè)變量,同一個(gè)變量名中不能出現(xiàn)分好,否則視為單個(gè)變量處理了。 windows上設(shè)置java環(huán)境變量,隨便一搜一大堆,不在啰嗦: JAVA_HOME : D:Program FilesJavajdk1.8.0_141 CL...
摘要:死亡狀態(tài)有兩個(gè)原因會(huì)導(dǎo)致線(xiàn)程死亡方法正常退出而自然死亡。一個(gè)未捕獲的異常終止了方法而使線(xiàn)程猝死。注意,放入的線(xiàn)程不必?fù)?dān)心其結(jié)束,超過(guò)不活動(dòng),其會(huì)自動(dòng)被終止。線(xiàn)程間相互干擾描述了當(dāng)多個(gè)線(xiàn)程訪(fǎng)問(wèn)共享數(shù)據(jù)時(shí)可能出現(xiàn)的錯(cuò)誤。 線(xiàn)程 進(jìn)程與線(xiàn)程的區(qū)別 線(xiàn)程是指進(jìn)程內(nèi)的一個(gè)執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體。一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線(xiàn)程。 線(xiàn)程的五大狀態(tài) 新建狀態(tài)(New):例如...
摘要:標(biāo)簽今天開(kāi)發(fā)的時(shí)候,遇到一個(gè)問(wèn)題,就是在谷歌瀏覽器上發(fā)現(xiàn)使用設(shè)置字體的大小時(shí)候,在字體小于的時(shí)候,不起作用。 標(biāo)簽: web 今天開(kāi)發(fā)的時(shí)候,遇到一個(gè)問(wèn)題,就是在谷歌瀏覽器上發(fā)現(xiàn)使用font-size設(shè)置字體的大小時(shí)候,在字體小于12px的時(shí)候,不起作用。具體解決方案如下:在一些老版本的谷歌瀏覽器中:可以用Chrome的私有屬性禁用瀏覽器文字大小調(diào)整的功能 -webkit-text-...
摘要:非阻塞模型這種也很好理解,由阻塞的死等系統(tǒng)響應(yīng)進(jìn)化成多次調(diào)用查看數(shù)據(jù)就緒狀態(tài)。復(fù)用模型,以及它的增強(qiáng)版就屬于該種模型。此時(shí)用戶(hù)進(jìn)程阻塞在事件上,數(shù)據(jù)就緒系統(tǒng)予以通知。信號(hào)驅(qū)動(dòng)模型應(yīng)用進(jìn)程建立信號(hào)處理程序時(shí),是非阻塞的。 引言 之前的兩篇文章 FastThreadLocal怎么Fast?、ScheduledThreadPoolExecutor源碼解讀 搞的我心力交瘁,且讀源碼過(guò)程中深感功...
摘要:我接觸已經(jīng)很久了,其中微信的就是我貢獻(xiàn)的代碼,然而當(dāng)時(shí)做的時(shí)候比較年輕,而且這個(gè)項(xiàng)目處于一個(gè)很大的代碼重構(gòu)中,借這次機(jī)會(huì)重新用正確的姿勢(shì)接入了一下三方登錄,可以當(dāng)做一個(gè)學(xué)習(xí)接入三方的。 為什么要接入三方登錄 如果你的微信服務(wù)器要做復(fù)雜的邏輯,比如html5、給用戶(hù)提供高級(jí)的服務(wù),并且有很好看的頁(yè)面等等,這種時(shí)候你就需要一個(gè)正常的web服務(wù)器,用戶(hù)打通就需要做三方登錄了。 而如果你決定直...
閱讀 843·2023-04-25 19:40
閱讀 3498·2023-04-25 17:41
閱讀 3013·2021-11-11 11:01
閱讀 2634·2019-08-30 15:55
閱讀 3234·2019-08-30 15:44
閱讀 1363·2019-08-29 14:07
閱讀 488·2019-08-29 11:23
閱讀 1331·2019-08-27 10:54