作者: admin

  • Java筆試面試總結—try、catch、finally語句中有return 的各類情況

    Java筆試面試總結—try、catch、finally語句中有return 的各類情況

    前言

    之前在刷筆試題和面試的時候經常會遇到或者被問到 try-catch-finally 語法塊的執行順序等問題,今天就抽空整理了一下這個知識點,然後記錄下來。

    正文

    本篇文章主要是通過舉例的方式來闡述各種情況,我這裏根據 try-catch-finally 語法塊分為兩種大情況討論:try-catch 語法塊和 try-catch-finally 語句塊,然後再在每種情況里再去具體討論。

    一、try-catch 語句塊

    我們可以看看下面程序:

    public static void main(String[] args) {
    
        System.out.println(handleException0());
      }
    
      /**
       * try,catch都有return
       * @return
       */
      private static String handleException0() {
        try{
          System.out.println("try開始");
          String s = null;
          int length = s.charAt(0);
          System.out.println("try結束");
          return "try塊的返回值";
        }catch (Exception e){
          System.out.println("捕獲到了異常");
          return "catch的返回值";
        }
      }
    

    執行結果:

    try開始
    捕獲到了異常
    catch的返回值

    分析:程序首先執行 try 塊裏面的代碼,try 塊裏面發現有異常,try 塊後面的代碼不會執行(自然也不會return),然後進入匹配異常的那個 catch 塊,然後進入 catch 塊裏面將代碼執行完畢,當執行到 catch 裏面的return 語句的時候,程序中止,然後將此 return 的最終結果返回回去。

    二、try-catch-finally 語句塊

    這種語法塊我分為了 4 種情況討論,下面進行一一列舉。

    1、第一種情況,try 塊裏面有 return 的情況,並且捕獲到異常

    例1:

    public static void main(String[] args) {
      String result = handleException1();
      System.out.println(result);
    }
    private static String handleException1() {
      try{
        System.out.println("try開始");
        String str = null;
        int length = str.length();
        System.out.println("try結束");
      }catch (Exception e){
        System.out.println("捕獲到了異常");
      }finally {
        System.out.println("finally塊執行完畢了");
      }
      return "最終的結果";
    }
    

    例1執行的結果如下:

    try開始
    捕獲到了異常
    finally塊執行完畢了
    最終的結果

    例2:

    public static void main(String[] args) {
      String result = handleException2();
      System.out.println(result);
    }
    private static String handleException2() {
      try{
        System.out.println("try開始");
        String str = null;
        int length = str.length();
        System.out.println("try結束");
        return "try塊的返回值";
      }catch (Exception e){
        System.out.println("捕獲到了異常");
      }finally {
        System.out.println("finally塊執行完畢了");
      }
      return "最終的結果";
    }
    

    例2的執行結果如下:

    try開始
    捕獲到了異常
    finally塊執行完畢了
    最終的結果

    分析:首先 例1 和 例2 的結果是很顯然的,當遇到異常的時候,直接進入匹配到相對應的 catch 塊,然後繼續執行 finallly 語句塊,最後將 return 結果返回回去。

    第二種情況:try塊裏面有return的情況,但是不會捕獲到異常

    例3:

    思考:下面代碼try語句塊中有return語句,那麼是否執行完try語句塊就直接return退出方法了呢?

    public static void main(String[] args) {
      String result = handleException3();
      System.out.println(result);
    }
    private static String handleException3() {
      try{
      	System.out.println("");
        return "try塊的返回值";
      }catch (Exception e){
        System.out.println("捕獲到了異常");
      }finally {
        System.out.println("finally塊執行完畢了");
      }
      return "最終的結果";
    }
    

    例3的執行結果如下:

    finally塊執行完畢了
    try塊的返回值

    分析:例3的結果其實我們可以通過打斷點的方式去看看程序的具體執行流程,通過打斷點我們可以發現,代碼先執行 try塊 里的代碼,當執行到 return 語句的時候,handleException3方法並沒有立刻結束,而是繼續執行finally塊里的代碼,finally塊里的代碼執行完后,緊接着回到 try 塊的 return 語句,再把最終結果返回回去, handleException 方法執行完畢。

    第三種情況:try塊和finally裏面都有return的情況

    例4:

    public static void main(String[] args) {
        System.out.println(handleException4());
      }
    
      /**
       * 情況3:try和finally中均有return
       * @return
       */
      private static String handleException4() {
        try{
          System.out.println("");
          return "try塊的返回值";
        }catch (Exception e){
          System.out.println("捕獲到了異常");
        }finally {
          System.out.println("finally塊執行完畢了");
          return "finally的返回值";
        }
      //  return "最終的結果";//不能再有返回值
      }
    

    例4的執行結果:

    finally塊執行完畢了
    finally的返回值

    分析:需要注意的是,當 try 塊和 finally 裏面都有 return 的時候,在 try/catch/finally 語法塊之外不允許再有return 關鍵字。我們還是通過在程序中打斷點的方式來看看代碼的具體執行流程。代碼首先執行 try 塊 里的代碼,當執行到 return 語句的時候,handleException4 方法並沒有立刻結束,而是繼續執行 finally 塊里的代碼,當發現 finally 塊里有 return 的時候,直接將 finally 里的返回值(也就是最終結果)返回回去, handleException4 方法執行完畢。

    第四種情況:try塊,catch塊,finally塊都有return

    例5:

    public static void main(String[] args) {
        System.out.println(handleException5());
      }
    
      /**
       * 情況4:try,catch,finally都有return
       * @return
       */
      private static String handleException5() {
        try{
          System.out.println("try開始");
          int[] array = {1, 2, 3};
          int i = array[10];
          System.out.println("try結束");
          return "try塊的返回值";
        }catch (Exception e){
          e.printStackTrace();//這行代碼其實就是打印輸出異常的具體信息
          System.out.println("捕獲到了異常");
          return "catch的返回值";
        }finally {
          System.out.println("finally塊執行完畢了");
          return "finally的返回值";
        }
    //    return "最終的結果";
      }
    

    例5的執行結果:

    try開始
    捕獲到了異常
    finally塊執行完畢了
    finally的返回值
    java.lang.ArrayIndexOutOfBoundsException: 10
    at com.example.javabasic.javabasic.ExceptionAndError.TryCatchFinally.handleException5(TryCatchFinally.java:25)
    at com.example.javabasic.javabasic.ExceptionAndError.TryCatchFinally.main(TryCatchFinally.java:14)

    分析:程序首先執行try塊裏面的代碼,try塊裏面發現有異常,try塊後面的代碼不會執行(自然也不會return),然後進入匹配異常的那個catch塊,然後進入catch塊裏面將代碼執行完畢,當執行到catch裏面的return語句的時候,程序不會馬上終止,而是繼續執行finally塊的代碼,最後執行finally裏面的return,然後將此return的最終結果返回回去。

    總結

    其實,我們通過以上例子我們可以發現,不管return關鍵字在哪,finally一定會執行完畢。理論上來說try、catch、finally塊中都允許書寫return關鍵字,但是執行優先級較低的塊中的return關鍵字定義的返回值將覆蓋執行優先級較高的塊中return關鍵字定義的返回值。也就是說finally塊中定義的返回值將會覆蓋catch塊、try塊中定義的返回值;catch塊中定義的返回值將會覆蓋try塊中定義的返回值。
    再換句話說如果在finally塊中通過return關鍵字定義了返回值,那麼之前所有通過return關鍵字定義的返回值都將失效——因為finally塊中的代碼一定是會執行的。

    公眾號:良許Linux

    有收穫?希望老鐵們來個三連擊,給更多的人看到這篇文章

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※別再煩惱如何寫文案,掌握八大原則!

  • Spring IoC 循環依賴的處理

    Spring IoC 循環依賴的處理

    前言

    本系列全部基於 Spring 5.2.2.BUILD-SNAPSHOT 版本。因為 Spring 整個體系太過於龐大,所以只會進行關鍵部分的源碼解析。

    本篇文章主要介紹 Spring IoC 是怎麼解決循環依賴的問題的。

    正文

    什麼是循環依賴

    循環依賴就是循環引用,就是兩個或多個 bean 相互之間的持有對方,比如A引用B,B引用A,像下面偽代碼所示:

    public class A {
        private B b;
        
        // 省略get和set方法...
    }
    
    public class B {
        private A a;
        
        // 省略get和set方法...
    }
    

    Spring 如何解決循環依賴

    Spring IoC 容器對循環依賴的處理有三種情況:

    1. 構造器循環依賴:此依賴 Spring 無法處理,直接拋出 BeanCurrentlylnCreationException 異常。
    2. 單例作用域下的 setter 循環依賴:此依賴 Spring 通過三級緩存來解決。
    3. 非單例的循環依賴:此依賴 Spring 無法處理,直接拋出 BeanCurrentlylnCreationException 異常。

    構造器循環依賴

    還是假設上面的A和B類是構造器循環依賴,如下所示:

    public class A {
        private B b;
        
        public A(B b) {
            this.b = b;
        }
        
        // 省略get和set方法...
    }
    
    public class B {
        private A a;
        
        public B(A a) {
            this.a = a;
        }
        
        // 省略get和set方法...
    }
    

    然後我們在 XML 中配置了構造器自動注入,如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="a" class="com.leisurexi.ioc.circular.reference.A" autowire="constructor" />
    
        <bean id="b" class="com.leisurexi.ioc.circular.reference.B" autowire="constructor" />
    
    </beans>
    

    那麼我們在獲取 A 時,首先會進入 doGetBean() 方法(該方法在Spring IoC bean 的加載中分析過),會進行到如下代碼塊:

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
        // 省略其它代碼...
        
        // 如果 bean 的作用域是單例
        if (mbd.isSingleton()) {
            // 創建和註冊單例 bean
            sharedInstance = getSingleton(beanName, () -> {
                try {
                    // 創建 bean 實例
                    return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                    destroySingleton(beanName);
                    throw ex;
                }
            });
            // 獲取bean實例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
        
        // 省略其它代碼...
     
    }
    

    上面方法中的 getSingleton() 方法會判斷是否是第一次創建該 bean,如果是第一次會先去創建 bean,也就是調用 ObjectFacoty 的 getObject() 方法,即調用 createBean() 方法創建 bean 前,會先將當前正要創建的 bean 記錄在緩存 singletonsCurrentlyInCreation 中。

    在創建A時發現依賴 B,便先去創建 B;B在創建時發現依賴A,此時A因為是通過構造函數創建,所以沒創建完,便又去創建A,發現A存在於 singletonsCurrentlyInCreation,即正在創建中,便拋出 BeanCurrentlylnCreationException 異常。

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        // 加鎖
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            // 一級緩存中不存在當前 bean,也就是當前 bean 第一次創建
            if (singletonObject == null) {
                // 如果當前正在銷毀 singletons,拋出異常
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                // 創建單例 bean 之前的回調
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    // 獲取 bean 實例
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
    				}
                // 省略異常處理...
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    // 創建單例 bean 之後的回調
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    // 將 singletonObject 放入一級緩存,並從二級和三級緩存中移除
                    addSingleton(beanName, singletonObject);
                }
            }
            // 返回 bean 實例
            return singletonObject;
        }
    }
    
    // 單例 bean 創建前的回調方法,默認實現是將 beanName 加入到當前正在創建 bean 的緩存中,
    // 這樣便可以對循環依賴進行檢測
    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }
    
    // 單例 bean 創建后的回調方法,默認實現是將 beanName 從當前正在創建 bean 的緩存中移除
    protected void afterSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
            throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
        }
    }
    
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            // 這邊bean已經初始化完成了,放入一級緩存
            this.singletonObjects.put(beanName, singletonObject);
            // 移除三級緩存
            this.singletonFactories.remove(beanName);
            // 移除二級緩存
            this.earlySingletonObjects.remove(beanName);
            // 將 beanName 添加到已註冊 bean 緩存中
            this.registeredSingletons.add(beanName);
        }
    }
    

    setter循環依賴

    還是假設上面的A和B類是 field 屬性依賴注入循環依賴,如下所示:

    public class A {
        private B b;
        
        // 省略get和set方法...
    }
    
    public class B {
        private A a;
        
        // 省略get和set方法...
    }
    

    然後我們在 XML 中配置了按照類型自動注入,如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="a" class="com.leisurexi.ioc.circular.reference.A" autowire="byType" />
    
        <bean id="b" class="com.leisurexi.ioc.circular.reference.B" autowire="byType" />
    
    </beans>
    

    Spring 在解決單例循環依賴時引入了三級緩存,如下所示:

    // 一級緩存,存儲已經初始化完成的bean
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    // 二級緩存,存儲已經實例化完成的bean
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    
    // 三級緩存,存儲創建bean實例的ObjectFactory
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    // 按先後順序記錄已經註冊的單例bean
    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
    

    首先在創建A時,會進入到 doCreateBean() 方法(前面的流程可以查看Spring IoC bean 的創建一文),如下:

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
        // 獲取bean的實例
        BeanWrapper instanceWrapper = null;
        if (instanceWrapper == null) {
            // 通過構造函數反射創建bean的實例,但是屬性並未賦值
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 獲取bean的實例
        final Object bean = instanceWrapper.getWrappedInstance();
        
        // 省略其它代碼...
    
        // bean的作用域是單例 && 允許循環引用 && 當前bean正在創建中
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
        // 如果允許bean提前曝光
        if (earlySingletonExposure) {
            // 將beanName和ObjectFactory形成的key-value對放入singletonFactories緩存中
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }
        
        // 省略其它代碼...
        
    }
    

    在調用 addSingletonFactory() 方法前A的實例已經創建出來了,只是還未進行屬性賦值和初始化階段,接下來將它放入了三級緩存中,如下:

    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        // 加鎖
        synchronized (this.singletonObjects) {
            // 如果一級緩存中不包含當前bean
            if (!this.singletonObjects.containsKey(beanName)) {
                // 將ObjectFactory放入三級緩存
                this.singletonFactories.put(beanName, singletonFactory);
                // 從二級緩存中移除
                this.earlySingletonObjects.remove(beanName);
                // 將beanName加入到已經註冊過的單例bean緩存中
                this.registeredSingletons.add(beanName);
            }
        }
    }
    

    接下來A進行屬性賦值階段(會在後續文章中單獨分析這個階段),發現依賴B,便去獲取B,發現B還沒有被創建,所以走創建流程;在B進入屬性賦值階段時發現依賴A,就去調用 getBean() 方法獲取A,此時會進入 getSingleton() 方法(該方法的調用流程在Spring IoC bean 的加載一文中分析過),如下:

    public Object getSingleton(String beanName) {
        // allowEarlyReference設置為true表示允許早期依賴
        return getSingleton(beanName, true);
    }
    
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 先從一級緩存中,檢查單例緩存是否存在
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果為空,並且當前bean正在創建中,鎖定全局變量進行處理
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                // 從二級緩存中獲取
                singletonObject = this.earlySingletonObjects.get(beanName);
                // 二級緩存為空 && bean允許提前曝光
                if (singletonObject == null && allowEarlyReference) {
                    // 從三級緩存中獲取bean對應的ObjectFactory
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        // 調用預先設定的getObject(),獲取bean實例
                        singletonObject = singletonFactory.getObject();
                        // 放入到二級緩存中,並從三級緩存中刪除
                        // 這時bean已經實例化完但還未初始化完
                        // 在該bean未初始化完時如果有別的bean引用該bean,可以直接從二級緩存中取出返回
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
    

    嘗試一級緩存 singletonObjects (肯定沒有,因為A還沒初始化完全),嘗試二級緩存 earlySingletonObjects(也沒有),嘗試三級緩存 singletonFactories,由於A通過 ObjectFactory 將自己提前曝光了,所以B能夠通過 ObjectFactory.getObject() 拿到A對象(雖然A還沒有初始化完全,但是總比沒有好呀)。B拿到A后順利創建並初始化完成,調用上面分析過的 addSingleton() 方法將自己放入一級緩存中。此時返回A中,A也能順利拿到完全初始化的B進行後續的階段,最後也將自己放入一級緩存中,並從二級和三級緩存中移除。

    過程圖如下所示:

    非單例循環依賴

    對於非單例的 bean,Spring 容器無法完成依賴注入,因為 Spring 容器不進行緩存,因此無法提前暴露一個創建中的 bean。

    總結

    本文主要介紹了 Spring 對三種循環依賴的處理,其實還有一種字段循環依賴,比如 @Autowired 註解標註的字段,但它和 setter 循環依賴的解決方法一樣,這裏就沒有多說。

    最後,我模仿 Spring 寫了一個精簡版,代碼會持續更新。地址:https://github.com/leisurexi/tiny-spring。

    參考

    • 《Spring 源碼深度解析》—— 郝佳
    • https://juejin.im/post/5c98a7b4f265da60ee12e9b2

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • C++ Primer Plus(四)

    完整閱讀C++ Primer Plus 

      系統重新學習C++語言部分,記錄重要但易被忽略的,關鍵但易被遺忘的。

     

    友元、異常和其他

      1、拋出異常類時,雖然catch的是一個引用,但是也會產生一次拷貝,因為當拋出異常的函數在棧解退的過程中會會調用異常類的析構函數,異常類將不復存在。

      2、如果有一個異常類層次結構,應該這樣排列catch塊:將捕獲位於層次結構最下面的異常類的catch語句放在最前面,將捕獲基類異常的catch語句放在最後面。拋出異常的順序要與catch塊相反。

      3、在catch語句中使用基類對象時,將捕獲所有的派生類對象,但派生類特性將被剝去,因此將使用虛方法的基類版本。

      4、 將dynamic_cast用於引用時,由於沒有與空指針對應的引用值,因此無法使用特殊的引用值來表示失敗,當請求不正確時,將引發bad_cast的異常。

      5、reinterpret_cast運算符並不支持所有的類型轉換,例如,可以將指針類型轉換為足以存儲指針的整數,但不能將指針轉換為更小的整型或浮點型。另一個限制是,不能將函數指針和數據指針互相轉換。

     

    string類和標準模板庫

      6、使用new分配內存時,可以使用auto_ptr、unique_ptr、shared_ptr、但只有unique_ptr有使用new[]和delete[]的版本。

      7、在unique_ptr為右值時,可以將其賦值給shared_ptr,模板shared_ptr包含一個顯式構造函數,可以用於將右值unique_ptr轉換為shared_ptr。

      8、對於所有內置的算術運算符、關係運算符和邏輯運算符,STL都提供了等價的函數符(仿函數)。

      9、valarray模板類重載了許多運算符,可以直接參与大多數數值運算;slice類可用作數組索引,它接受三個值初始值:起始索引、索引數、跨距。

    1 valarry<double> arr(10);
    2 arr[slice(1,4,3)] = 10;

      slice(1,4,3)創建的對象表示選擇4個索引,這可以將arr的第1、4、7、10個元素都設置為10。

      10、迭代器類型

    Input iterator(輸入迭代器)  讀,不能寫;只支持自增運算
    Output iterator(輸出迭代器) 寫,不能讀;只支持自增運算
    Forward iterator(前向迭代器) 讀和寫;只支持自增運算
    Bidirectional iterator(雙向迭代器) 讀和寫;支持自增和自減運算
    Random access iterator(隨機訪問迭代器) 讀和寫;支持完整的迭代器算術運算

     

    輸入、輸出和文件

      11、對於標準錯誤輸出,是沒有緩衝區的。

      12、在使用cout時,可以使用成員函數width()設置下一次輸出時的字段寬度,默認右對齊並以空格填充空白字段,當字段寬度不足時,C++不對截斷輸出寬度;使用成員函數fill()用來填充空白字段;使用成員函數precision()來設置浮點數輸出精度;成員函數setf()與unsetf()提供了更豐富的輸出格式設置方法,但使用標準控制符將更加簡單。

      13、對於cin的get()方法和getline()方法來說,如果沒有讀取到任何字符(getline()將換行符視為一個字符),則設置failbit;如果讀取了最大數目的字符,但行中還有其他字符,getline()將設置failbit。

      14、cin的peak()方法可以查看輸入流中的下一個字符,gcount()方法可以返回最後一個非格式化抽取方法讀取的字符數,putback()方法可以將字符插入到輸入字符串中。

      15、fstream類中的方法seekg()和seekp()分別將輸入指針和輸出指針移到指定的文件位置,事實上,由於fstream類使用緩衝區來存儲中間數據,因此指針指向的是緩衝區中的位置,而不是實際的文件。

      16、fstream類中的方法tellg()和tellp()方法分別返回輸入流、輸出流當前指針的位置,對於fstream對象,輸入輸出指針將一前一后地移動,因此它們的返回值相同。但對於使用istream對象來管理輸入流,而使用ostream對象來管理同一個文件的輸出流,則輸入指針和輸出指針將彼此獨立的移動。

      17、關於如何生成臨時文件,使用tmpnam()可以生產TMP_NAM個不同的文件名,其中每個文件名包含的字符不超過L_tmpnam個。

      18、C++庫還提供了sstream族(包含ostringstream類和istringstream類),它們使用相同的接口提供程序和string對象之間的IO。

     

    探討C++新標準

      19、新標準引入的移動語義,用來修飾六個特殊函數的default關鍵字,用來刪除任意成員函數的delete關鍵字,以及使用類似初始化列表的方式在一個構造函數中使用另一個構造函數(被稱為委託構造),以及使用using 類名::函數名,使基類所有的非特殊成員函數對派生類可以用(繼承構造函數),以及显示聲明重寫(覆蓋)某個虛函數的標識符override,以及禁止派生類覆蓋特定的虛函數標識符final。

      20、C++11引入lambda表達的主要目的是能夠將類似於函數的表達式用作接受函數指針或函數符的函數的參數。

      21、C++提供了多個包裝器對象,用於給其他編程接口提供更一致或更合適的接口。C++11提供了包括模板bind(替代bind1st和bind2nd)、men_fn(將成員函數作為常規函數傳遞)和reference_wrapper(創建行為像引用但可被複制的對象)以及funtion(以統一的方式處理多種類似於函數的形式,使用模板時可減少可執行代碼的規模)。

      22、正確使用遞歸實現可變參數模板。

      23、C++11增加了對并行編程的支持,以及相當多的新增庫等。

     

    附錄

      24、C++允許定義指向類成員(包括數據和函數)的指針,這種語法需要使用到成員解除引用運算符(* 、->*)。

      25、C++11新增了alignof運算符,它接受一個類型作為參數,返回這個類型的對齊方式;noexcept關鍵字用於指出函數不會引發異常,它也可以用作運算符,判斷表達式是否可能引發異常,不引發返回true。

      26、STL提供了豐富的全局函數,包括查詢,排序,複製等一系列算法。

      

      2020年6月2日,星期二,凌晨2點01分,首次完整讀完這本書,共勉。

      學如逆水行舟,不進則退;心似平原放馬,易縱難收。

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    ※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※台北網頁設計公司全省服務真心推薦

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※新北清潔公司,居家、辦公、裝潢細清專業服務

    ※推薦評價好的iphone維修中心

  • vue中使用element2

    vue中使用element2

    阻止谷歌下記住密碼

    當我們將input框的類型設置為密碼框的時候,就會出現下面這種效果,不僅樣式不統一,有的時候,密碼框的上面並不是用戶名,而是其他的內容,也會被強制显示為用戶名:

     首先需要解決樣式問題:

     #app input:-webkit-autofill {
        -webkit-text-fill-color: #fff !important;
        -webkit-box-shadow: none !important;
        background-color: transparent;
        background-image: none;
        transition: background-color 999999s ease-in-out, color 999999s ease-in-out;
      }

     其次,阻止谷歌自帶的記住密碼:

     回車重定向

     單個el-input獲得焦點時,點擊鍵盤迴車,會觸發路由重定向。

    解決方法:@submit.native.preven t阻止表單默認事件

     日期時間框的默認值在IE無法清除

    element的日期框添加默認值后,在ie下,默認的清空按鈕無法清空默認日期值:

     

     

     數據應該是已經清空了,但是DOM沒有刷新,所以需要強制刷新DOM:

     

     自定義表頭

    <template>
        <div>
            <el-table-column
                v-for="(item, idx) in list"
                :key="idx"
                v-bind="item" :show-overflow-tooltip="true">
                <tHeader
                    v-if="item.children"
                    :list="item.children">
                </tHeader>
            </el-table-column>
        </div>
    </template>
    <script>
    export default {
        name: 'tHeader',
        props: [
            'list'
        ],
        methods: {
            repairEleSortBug() {
                this.list.unshift(this.list.pop());
            }
        },
        
        created() {
                //修復elementUI排序倒置的bug(將數組最後一個放到第一個)
            this.repairEleSortBug();
        }
    };
    </script>

     

     

     

     對象監聽

    在vue中可以通過監聽一個變量的值變化觸發相應事件,但是當需要監聽的變量是個複雜對象時,通常在外出是監聽不到對象裏面值的變化,這時就需要深度監聽:

     

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
    【其他文章推薦】

    ※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    ※台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※回頭車貨運收費標準

  • 航空業減碳動起來 澳航允2050年前碳排減到零

    摘錄自2019年11月11日中央社報導

    澳洲航空今(11日)允諾加入英國航空(British Airways)母公司「國際航空集團」(IAG),要在2050年前,把淨碳排降至零。澳航(Qantas)執行長喬伊斯(Alan Joyce)發布聲明說,氣候變遷的憂慮「真實存在」,「我們之所以做這件事,是因為這件事很重要」。

    來自環保團體「反抗滅絕」(Extinction Rebellion, XR)與環保小鬥士桑柏格(Greta Thunberg)壓力越來越大之際,國際航空集團上月允諾2050年前把淨碳排減到零,是首家做此承諾的大型航空公司。航空業者整體則已答應要在2050年前把碳排量減至2005年的一半。

    澳航表示,希望能把淨碳排控制在2020年水準,並在10年間投資5000萬澳元開發永續能源來減碳,與傳統航空燃料相比,可減少8成的碳排。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • 澳洲野火燒破千人家園 雪梨收災難性警告

    摘錄自2019年11月11日ETtoday 綜合報導

    澳洲東部森林野火自8日起延燒多日,造成3人死亡、數十人受傷以及上千人失去家園,仍在燃燒的上百處火場燒掉了至少150棟的住宅。當局指出,恐怕連雪梨及周邊地區也會受影響,12日將迎接「災難性」野火威脅。

    外電報導,新南威爾斯州(New South Wales)及昆士蘭州(Queensland)等地接連傳出災情,當局派出將近1300名消防員也沒能撲滅燒了4天的大火,只能宣布災區進入「緊急狀態」,並警告人口最多的雪梨地區,高溫恐飆破攝氏37度,要面臨「災難性」(catasrophic)的野火威脅。

    這也是澳洲2009年推出新的「火情危險評級制度」(Fire Danger Rating,分為中等、高、非常高、嚴重、極高及災難性)後,雪梨第一次面臨「災難性」等級,預計12日雪梨會出現攝氏37度高溫、強風、乾燥等,不排除比澳洲東部當初被野火襲擊時更嚴重。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    ※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※台北網頁設計公司全省服務真心推薦

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※新北清潔公司,居家、辦公、裝潢細清專業服務

    ※推薦評價好的iphone維修中心

  • 非洲黑猩猩擄走人類小孩 源自於棲地銳減

    摘錄自2019年11月12日ETtoday綜合報導

    非洲烏干達黑猩猩原始棲地逐年喪失,引爆人類與猩猩之間的激烈衝突。《國家地理》雜誌網站近日報導,當地黑猩猩為了覓食,不僅破壞農作物,甚至學會對人類發動攻擊;當地自2014年以來,已經發生多起兒童遭猩猩擄走事件,其中一人甚至被猩猩開膛剖肚,內臟還被吃掉。

    在野外,雄性黑猩猩有時會獵捕其他猴子或山羊,並食用獵物的肉果腹;他們雖然對人類保持警覺心,但這也使他們變得更具侵略性。自從2014年以來,陸續發生多起孩童遭黑猩猩攻擊事件,造成至少3人死亡,另有至少6人受傷。目前還無法確定黑猩猩為何突然開始襲擊人類兒童,但據信與烏干達西部自然棲地逐漸被農田侵蝕有關。

    烏干達野生動物管理局(UWA)表示,當局已經意識到猩猩攻擊兒童的問題,但面對黑猩猩的棲地森林和自然家園遭破壞也感到無能為力,理由是人們普遍認為開闢農地來維持生計,比起保育森林更加重要。

    據悉,非洲大陸大約只剩下30萬頭野生黑猩猩,烏干達野生動物管理局考慮透過一系列教育性活動,向人們宣導保育森林的重要性。

     

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    ※台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※回頭車貨運收費標準

  • 管理出包? 大堡礁集水區驗出高濃度殺蟲劑

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    ※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

    ※教你寫出一流的銷售文案?

    ※超省錢租車方案

  • 神秘疾病侵襲 加勒比海珊瑚礁群拉警報

    摘錄自2019年11月12日中央通訊社綜合報導

    短短一年多來,墨西哥加勒比海地區的珊瑚因為遭到一種罕為人知「石珊瑚組織損失症」(SCTLD)侵襲,已經損失30%。這種疾病會造成珊瑚鈣化和死亡。

    專家警告,這種疾病可能造成大部分中美洲珊瑚礁(Mesoamerican Reef)死亡。這處龐大的弧狀珊瑚礁群範圍廣達超過1000公里,為墨西哥、貝里斯、瓜地馬拉和宏都拉斯等國家共有。

    SCTLD已使加勒比海地區陷入困境,這種疾病可能摧毀環礁地區民眾賴以為生的觀光產業。中美洲珊瑚礁是僅次於澳洲大堡礁的世界第2大珊瑚礁。科學家表示,旅遊業太發達非常有可能讓問題火上加油。

    「健康珊瑚礁、健康人民」在墨西哥的協調人員蘇鐸(Melina Soto)說,SCTLD只需幾週時間,就可以殺死需要花費數十年生長起來的珊瑚組織。蘇鐸表示:「如果以這種速度繼續下去,這個生態系統將會在未來的5到10年內崩潰。」

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※別再煩惱如何寫文案,掌握八大原則!

  • 水上太陽能火災 消防車要用特別款──千葉・山倉風災事件啟示錄

    文:宋瑞文(加州能源特約撰述)

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※南投搬家公司費用需注意的眉眉角角,別等搬了再說!

    ※新北清潔公司,居家、辦公、裝潢細清專業服務