2018-03-18 部分問題日記

sql中in和exist兩者的區(qū)別

  1. in和exists一般搭配子查詢來使用,in的話也可以單獨的使用in(a,b,c...)這種方式來使用胁塞;
  2. in關鍵字會先執(zhí)行子查詢即對內表的查詢碘举,再與外表做笛卡爾積(即若外表有1000條記錄格侯,內表有100,則會生成1000*100條記錄)吱晒,再根據(jù)條件篩選數(shù)據(jù)甸饱,而exists會先執(zhí)行外表查詢,再進行內外的條件判斷篩選結果(外表結果集為100仑濒,則內表的子查詢會執(zhí)行100次)叹话;
  3. 兩者對索引的使用也存在不同,使用in關鍵字時墩瞳,使用的是外表的索引渣刷,而exists則是使用的內表的索引;所以當外表較大矗烛,使用外表索引辅柴,子查詢內表結果較小的時候,使用in的效率會更高瞭吃,而當外表較小碌嘀,而子查詢內表結果較大,且子查詢使用索引的時候歪架,使用exists效率會更高股冗,若內外表查詢結果集相差不大,兩者效率基本相持和蚪,可根據(jù)所使用的索引來確定具體使用的關鍵字止状;
  4. in中子查詢結果會放入內存,進行條件判斷是在內存中進行的攒霹,而exists每一次的內外條件相比較是在數(shù)據(jù)庫中完成的怯疤;

舉個例子,下列有如下兩個表


t_user

t_order表

有如下兩條SQL

--使用in關鍵字
SELECT *
FROM t_user 
WHERE id IN (
    SELECT user_id
    FROM t_order 
);

--使用exists關鍵字
SELECT t.*
FROM t_user t
WHERE EXISTS (
    SELECT tt.user_id
    FROM t_order tt
    WHERE t.id = tt.user_id
)

最后輸出的結果是一致的


sql的結果

IN

首先分析使用in關鍵字的sql催束,執(zhí)行這條sql首先會先執(zhí)行子查詢即內表t_order表的查詢

SELECT user_id FROM t_order

然后與外表的查詢生成一個笛卡爾積


生成的結果集(未篩選)

然后根據(jù)sql中的條件將t_user的id和t_order的user_id進行比較集峦,不相等的記錄被刪除,最后輸出對應的結果集抠刺。

EXISTS

使用exists的語句塔淤,與in不同,他會默認先查詢外表的查詢

SELECT t.* FROM t_user t
外表查詢結果集

然后在根據(jù)外表查詢結果的每一行速妖,與子查詢內表執(zhí)行一次高蜂,若子查詢的條件符合(本例sql即t_user的id和t_order的user_id相等),則返回true罕容,若不符合則返回false备恤,則刪除外表查詢結果集中的一行挺举,最后完成篩選

EXISTS (
    SELECT tt.user_id
    FROM t_order tt
    WHERE t.id = tt.user_id
)

例子中外表和內表的查詢數(shù)據(jù)都差不多,但是外表查詢用到了主鍵id烘跺,主鍵同時也是默認創(chuàng)建的索引,而內表查詢中未使用索引脂崔,可使用in關鍵字

注意:in關鍵字不對null進行處理滤淳,not in是不會使用索引的,會對內外表進行全掃描砌左,所以效率極低脖咐,而not exists仍會使用內表的索引

2、Java反射機制介紹

JAVA反射機制是在運行狀態(tài)中汇歹,對于任意一個類屁擅,都能夠知道這個類的所有屬性和方法;對于任意一個對象产弹,都能夠調用它的任意一個方法和屬性派歌;這種動態(tài)獲取的信息以及動態(tài)調用對象的方法的功能稱為java語言的反射機制。
Java中使用反射一般是通過Class類這個對象來完成痰哨,JavaAPI中的描述如下:

Class對象

這個類沒有構造方法胶果,Class 對象是在加載類時由 Java 虛擬機以及通過調用類加載器中的defineClass 方法自動構造的。Class對象下有很多方法斤斧,下面介紹一部分常用的方法早抠。
參考:http://blog.csdn.net/sinat_38259539/article/details/71799078

String str = new String("demo");//新建一個String對象
//常用的Class對象獲取方式
Class cla = str.getClass();
cla = String.class;
cla = Class.forName("java.lang.String"); //通過類的真實路徑來返回一個Class類,一般使用這個撬讽,可以動態(tài)獲取所需要的Class對象

Object obj = cla.newInstance(); //通過newInstance返回實例

//獲取對應類蕊连、接口的構造函數(shù)
Constructor[] cons  =cla.getConstructors(); //獲取所有的public的構造函數(shù)
Constructor con  = cla.getConstructor(int.class); //獲取對應參數(shù)類型的public構造函數(shù),class入?yún)⒖勺?cons  = cla.getDeclaredConstructors(); //獲取所有構造函數(shù)
con  = cla.getDeclaredConstructors(char.class); //獲取對應入?yún)㈩愋偷乃袠嬙旌瘮?shù)

//獲取對應類游昼、接口的成員變量
Field[] fields = cla.getFields(); //獲取所有的public成員變量
Field field = cla.getField("demo"); //獲取對應名稱public成員變量
field.set(obj, "demo"); //對應靜態(tài)變量進行賦值甘苍,參數(shù):1、實例烘豌,2羊赵、修改后的數(shù)據(jù)
fields = cla.getDeclaredFields();
field = cla.getDeclaredField("demo");

//獲取類、接口下的成員方法
Method[] methods = cla.getMethods(); //獲取所有的public成員方法
Method method = cla.getMethod("demo", String.class); //獲取對應名稱的public成員方法
methods = cla.getDeclaredMethods();
method = cla.getDeclaredMethod("demo", String.class);
method.invoke(obj, "demo"); //調用方法扇谣,入?yún)ⅲ旱谝粋€實例昧捷,第二個對應的是入?yún)? 
//調用main函數(shù)
method = cla.getMethod("main", String[] args);
method.invoke(obj, (Object)new String[]{"d","e","m","o"});

3、獲得實例中的new和newInstance的區(qū)別

  1. 兩者加載的構造器不同罐寨,new關鍵字可以調用任意的pulbic構造器靡挥,newInstance只能調用無參構造器;
  2. 用new關鍵字時鸯绿,類可以沒有被加載跋破,而使用newInstance必須保證類已經被加載了簸淀;
  3. new,強類型毒返,相對高效租幕,newInstance,弱類型拧簸,低效率劲绪;
  4. new關鍵字完成了類加載、類的實例化盆赤,而newInstance則需要手動完成類加載贾富,Class.forName("java.lang.String")這行代碼完成了類的加載;
  5. newInstance可以通過傳入ClassName來動態(tài)的加載類的實例牺六,而不需要顯式的調用類的構造器
//用new創(chuàng)建對象颤枪,可以調用無參或者有參的public構造函數(shù)
String str1 = new String();

//用newInstance
Class cla = Class.forName("java.lang.String"); //初始化,完成類的加載
Object obj = cla.newInstance(); //實例化
String str2 = (String)obj; //向下轉型為子類

4淑际、單例模式中餓漢模式和懶漢模式的區(qū)別

共同特點:構造器為私有化
(1)畏纲、懶漢模式:延遲加載,當被使用時才會加載春缕,“時間換空間策略”霍骄,單純的懶漢模式是非線程安全的,若有多個線程同時進入getInstance方法淡溯,線程1先進入if代碼塊后读整,線程二同時控制代碼,會造成兩個實例被返回咱娶,可以通過使用靜態(tài)內部類(靜態(tài)內部類在外部類加載時會進行初始化)或者雙重檢查(靜態(tài)變量上需添加volatile米间,由于指令重排問題會導致線程不安全)的方式來達到線程安全的要求
(2)、餓漢模式:類加載時膘侮,實例已經完成屈糊,存放于內存中,“空間換時間”策略琼了,線程安全

餓漢模式

public class SingletonDemo1(){
      private static SingletonDemo1 singletonDemo1 = new SingletonDemo1();      
      private SingletonDemo1(){
            //私有構造函數(shù)
      }
      private static SingletonDemo1 getInstance(){
              return singletonDemo1;
      }
}

懶漢模式

public class SingletonDemo2(){
      private static SingletonDemo2 singletonDemo2 = null;      
      private SingletonDemo2(){
            //私有構造函數(shù)
      }
      private static SingletonDemo2 getInstance(){
             if(singletonDemo2  == null){ //懶漢單例模式的實例未被創(chuàng)建
                 singletonDemo2  = new SingletonDemo2();
             }
            return singletonDemo2 ;
      }
}

懶漢模式-雙重檢查

public class SingletonDemo2(){
      private static volatile SingletonDemo2 singletonDemo2 = null;      
       private SingletonDemo2(){
            //私有構造函數(shù)
      }
      private static SingletonDemo2 getInstance(){
             if(singletonDemo2  == null){ //懶漢單例模式的實例未被創(chuàng)建
                 synchronized(SingletonDemo2.class){ 
                     if(singletonDemo2  == null){
                          singletonDemo2  = new SingletonDemo2();
                     }
                  }
             }
            return singletonDemo2 ;
      }
}

Holder式逻锐,通過靜態(tài)內部類實現(xiàn)懶加載

public class Singleton {
    private static class SingletonHolder{
        static {
            System.out.println("單例內部類被初始化");
        }
                private static Singleton singleton = new Singleton();
        private SingletonHolder(){
            System.out.println("單例內部類構造函數(shù)調用");
        }
    }
    
    private Singleton(){
        System.out.println("靜態(tài)內部類調用外部類的私有構造函數(shù)");
        if (SingletonHolder.singleton !=null) {
            try {
                throw new IllegalAccessException("單例對象已經被實例化,請不要非法反射構造函數(shù)");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static Singleton getInstance(){
        return SingletonHolder.singleton;
    }
}

Holder懶加載結果

public class SingleTonTest { //測試Holder的懶加載
    public static void main(String[] args) throws ClassNotFoundException  {
        System.out.println("類載入---------");
        Class cla = Class.forName("demo.Singleton"); //完成單例類的加載
        System.out.println("類載入完成------"+cla);
        System.out.println("獲取單例實例-----");
        Singleton singleton = Singleton.getInstance(); //獲取單例類的實例
        System.out.println("獲取單例結束-----"+singleton);
    }
}

控制臺輸出結果


執(zhí)行順序
  1. 可以從輸出結果中看到在完成單例類加載的時候雕薪,靜態(tài)內部類并未被初始化昧诱,此時單例類的唯一實例還未被調用創(chuàng)建,不會占用內存空間所袁。
  2. 在獲取單例實例時盏档,即靜態(tài)內部類被調用時,靜態(tài)內部類首先完成了初始化燥爷,調用了外部類的構造函數(shù)生成實例蜈亩,完成懶加載懦窘;
  3. 此方法在實現(xiàn)懶加載的同時,亦保證了線程安全稚配,且未使用synchronized悲觀鎖畅涂,性能好
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市道川,隨后出現(xiàn)的幾起案子午衰,更是在濱河造成了極大的恐慌,老刑警劉巖愤惰,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赘理,居然都是意外死亡宦言,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門商模,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奠旺,“玉大人,你說我怎么就攤上這事施流∠炀危” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵瞪醋,是天一觀的道長忿晕。 經常有香客問我,道長银受,這世上最難降的妖魔是什么践盼? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮宾巍,結果婚禮上咕幻,老公的妹妹穿的比我還像新娘。我一直安慰自己顶霞,他們只是感情好肄程,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著选浑,像睡著了一般蓝厌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上古徒,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天褂始,我揣著相機與錄音,去河邊找鬼描函。 笑死崎苗,一個胖子當著我的面吹牛狐粱,可吹牛的內容都是我干的。 我是一名探鬼主播胆数,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肌蜻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了必尼?” 一聲冷哼從身側響起蒋搜,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎判莉,沒想到半個月后豆挽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡券盅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年帮哈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锰镀。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡娘侍,死狀恐怖,靈堂內的尸體忽然破棺而出泳炉,到底是詐尸還是另有隱情憾筏,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布花鹅,位于F島的核電站氧腰,受9級特大地震影響,放射性物質發(fā)生泄漏刨肃。R本人自食惡果不足惜容贝,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望之景。 院中可真熱鬧斤富,春花似錦、人聲如沸锻狗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轻纪。三九已至油额,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刻帚,已是汗流浹背潦嘶。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留崇众,地道東北人掂僵。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓航厚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親锰蓬。 傳聞我的和親對象是個殘疾皇子幔睬,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法芹扭,內部類的語法麻顶,繼承相關的語法,異常的語法舱卡,線程的語...
    子非魚_t_閱讀 31,625評論 18 399
  • 一. Java基礎部分.................................................
    wy_sure閱讀 3,810評論 0 11
  • 轉 # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    呂品?閱讀 9,723評論 0 44
  • 1辅肾、水的一生 水,可以是水轮锥,也可以是冰矫钓,是蒸汽。 放在杯子里交胚,被人喝掉份汗,是一生盈电;化作山間流水蝴簇,源源不斷,又是一生匆帚。...
    藍柿閱讀 331評論 4 4
  • 追趕火車于我而言熬词,真算得上經驗豐富了。 周五的下午吸重,腦子里便策劃坐哪趟車互拾,往往擔心臨時有事故意把時...
    吳二水_bf67閱讀 317評論 1 1