Java日記2018-07-02

  1. 丑數(shù)
//49. 丑數(shù)
    public static int ugly(int n){
        if(n<1) return 0;
        int[] arr=new int[n];
        int index2=0;
        int index3=0;
        int index5=0;
        arr[0]=1;
        int min=0;
        for(int i=1;i<n;i++){
            //丑數(shù)的計算是通過動態(tài)規(guī)劃的方法,arr[i]是前一個素數(shù)與2 3 5的因子的乘積的最小值獲取。一定一定要注意是乘積
            min = min(arr[index2]*2,arr[index3]*3,arr[index5]*5);
            arr[i]=min;
            while(arr[index2]*2<min) index2++;
            while(arr[index3]*3<min) index3++;
            while(arr[index5]*5<min) index5++;
        }
        System.out.println(arr[n-1]);
        return arr[n-1];
    }
  1. 第一個只出現(xiàn)一次的字符位置
    這題也簡單,使用整數(shù)數(shù)組的值是否等于1判斷是否有重復值。
    有個有意思的地方是初始化數(shù)組英國選取多少?這個時候就了解基本數(shù)據(jù)類型占有大小
    Byte 1 個字節(jié)
    short 2個字節(jié)
    int 4個字節(jié)
    long 8個字節(jié)
    float 4個字節(jié)
    double 8個字節(jié)
    Boolean 1個字節(jié) (前7位是0)
    char 2個字節(jié) 采用unicode編碼,它的前128字節(jié)編碼與ASCII兼容
    所以初始化時候用的是int[] cnt = new int[256]
public static int findonce(String str){
        if(str==null) return -1;
        int[] cnt = new int[256];
        Arrays.fill(cnt, 0);
        for(int i=0;i<str.length();i++) {
            cnt[str.charAt(i)]++;
        }
        for (int i = 0; i < str.length(); i++)
            if (cnt[str.charAt(i)] == 1){
                System.out.println(i);
                 return i;
            }
               
        return -1;
    }
  1. 二叉搜索樹的第 K 個結(jié)點
//54. 二叉搜索樹的第 K 個結(jié)點
    private static int cnt=0;
    private static TreeNode res ;
    public static TreeNode KthNode(TreeNode root,int k){
        inorder(root,k);
        return res;
    }
    public static void inorder(TreeNode root,int k){
        if(root==null|| cnt>=k) return;
        inorder(root.left,k);
        cnt++;
        System.out.println("root:"+root.val+" cnt:"+cnt);
        if(cnt==k) res=root;
        inorder(root.right,k);
    }
  1. 加載

加載是類加載的一個階段,注意不要混淆。

加載過程完成以下三件事:

通過一個類的全限定名來獲取定義此類的二進制字節(jié)流。
將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時存儲結(jié)構(gòu)。
在內(nèi)存中生成一個代表這個類的 Class 對象,作為方法區(qū)這個類的各種數(shù)據(jù)的訪問入口。
其中二進制字節(jié)流可以從以下方式中獲?。?/p>

從 ZIP 包讀取,這很常見,最終成為日后 JAR、EAR、WAR 格式的基礎(chǔ)。
從網(wǎng)絡(luò)中獲取,這種場景最典型的應(yīng)用是 Applet。
運行時計算生成,這種場景使用得最多得就是動態(tài)代理技術(shù),在 java.lang.reflect.Proxy 中,就是用了 ProxyGenerator.generateProxyClass 的代理類的二進制字節(jié)流。
由其他文件生成,典型場景是 JSP 應(yīng)用,即由 JSP 文件生成對應(yīng)的 Class 類。
從數(shù)據(jù)庫讀取,這種場景相對少見,例如有些中間件服務(wù)器(如 SAP Netweaver)可以選擇把程序安裝到數(shù)據(jù)庫中來完成程序代碼在集群間的分發(fā)。

2. 驗證

確保 Class 文件的字節(jié)流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全。

  • 文件格式驗證:驗證字節(jié)流是否符合 Class 文件格式的規(guī)范,并且能被當前版本的虛擬機處理。
  • 元數(shù)據(jù)驗證:對字節(jié)碼描述的信息進行語義分析,以保證其描述的信息符合 Java 語言規(guī)范的要求。
  • 字節(jié)碼驗證:通過數(shù)據(jù)流和控制流分析,確保程序語義是合法、符合邏輯的。
  • 符號引用驗證:發(fā)生在虛擬機將符號引用轉(zhuǎn)換為直接引用的時候,對類自身以外(常量池中的各種符號引用)的信息進行匹配性校驗。

3. 準備

類變量是被 static 修飾的變量,準備階段為類變量分配內(nèi)存并設(shè)置初始值,使用的是方法區(qū)的內(nèi)存。

實例變量不會在這階段分配內(nèi)存,它將會在對象實例化時隨著對象一起分配在 Java 堆中。(實例化不是類加載的一個過程,類加載發(fā)生在所有實例化操作之前,并且類加載只進行一次,實例化可以進行多次)

初始值一般為 0 值,例如下面的類變量 value 被初始化為 0 而不是 123。

public static int value = 123;

如果類變量是常量,那么會按照表達式來進行初始化,而不是賦值為 0。

public static final int value = 123;

4. 解析

將常量池的符號引用替換為直接引用的過程。

5. 初始化

初始化階段才真正開始執(zhí)行類中的定義的 Java 程序代碼。初始化階段即虛擬機執(zhí)行類構(gòu)造器 <clinit>() 方法的過程。

在準備階段,類變量已經(jīng)賦過一次系統(tǒng)要求的初始值,而在初始化階段,根據(jù)程序員通過程序制定的主觀計劃去初始化類變量和其它資源。

  1. 類加載器分類
    啟動類加載器(Bootstrap ClassLoader)此類加載器負責將存放在 <JAVA_HOME>\lib 目錄中的,或者被 -Xbootclasspath 參數(shù)所指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別,如 rt.jar,名字不符合的類庫即使放在 lib 目錄中也不會被加載)類庫加載到虛擬機內(nèi)存中。啟動類加載器無法被 Java 程序直接引用,用戶在編寫自定義類加載器時,如果需要把加載請求委派給啟動類加載器,直接使用 null 代替即可。

擴展類加載器(Extension ClassLoader)這個類加載器是由 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)實現(xiàn)的。它負責將 <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系統(tǒng)變量所指定路徑中的所有類庫加載到內(nèi)存中,開發(fā)者可以直接使用擴展類加載器。

應(yīng)用程序類加載器(Application ClassLoader)這個類加載器是由 AppClassLoader(sun.misc.Launcher$AppClassLoader)實現(xiàn)的。由于這個類加載器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般稱為系統(tǒng)類加載器。它負責加載用戶類路徑(ClassPath)上所指定的類庫,開發(fā)者可以直接使用這個類加載器,如果應(yīng)用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器

  1. 自定義類加載器實現(xiàn)

FileSystemClassLoader 是自定義類加載器,繼承自 java.lang.ClassLoader,用于加載文件系統(tǒng)上的類。它首先根據(jù)類的全名在文件系統(tǒng)上查找類的字節(jié)代碼文件(.class 文件),然后讀取該文件內(nèi)容,最后通過 defineClass() 方法來把這些字節(jié)代碼轉(zhuǎn)換成 java.lang.Class 類的實例。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容