Java,Hello World,《算法》環境搭建中的問題,用 cmd 和 IntelliJ Idea 分別編譯和運行 Java 程序


▶ IntelliJ idea 下載和安裝(http://www.jetbrains.com/idea/)

▶ 新建項目(如圖),注意選擇 SDK 類型和位置

● 在 src 目錄中新建一個 Package,在該 Package 中新建一個 class,在編輯器中寫該類的一個函數(主函數)如圖,點擊右上角錘子可以 build,或者在 build 和 run 選項卡中選擇相應選項

● 執行結果

 

▶ 嘗試運行了書中的一個代碼(二分搜索與白名單),發現環境配置過程中有很多問題,姑且先把成功了的過程寫在這里,僅供參考。

● 工作目錄為 "testJava",文件目錄如下,IntelliJ Idea 中建立了包 package01 和其中的一個類 class01.java,源文件放在其中(原始代碼如下,大意是輸入白名單文件和待篩查文件,輸出白名單中不存在的值)。自動編譯生成的文件是 class01.class。輸入白名單數據 tinyW.txt,待篩查文件 tinyT.txt。

D:\CODE\JAVA\TESTJAVA
│  testJava.iml
│  
├─.idea
│      misc.xml
│      modules.xml
│      workspace.xml
│      
├─out
│  └─production
│      └─testJava
│          └─package01
│                  class01.class
│                  
└─src
    └─package01
            class01.java
 1 package package01;
 2 
 3 import java.util.Arrays;
 4 
 5 import edu.princeton.cs.algs4.StdIn;
 6 import edu.princeton.cs.algs4.StdOut;
 7 import edu.princeton.cs.algs4.In;
 8 
 9 public class class01
10 {
11     private class01() {}
12 
13     public static int indexOf(int[] a, int key)
14     {
15         int lo = 0, hi = a.length - 1;
16         while (lo <= hi)
17         {
18             int mid = lo + (hi - lo) / 2;
19             if      (key < a[mid]) hi = mid - 1;
20             else if (key > a[mid]) lo = mid + 1;
21             else return mid;
22         }
23         return -1;
24     }
25 
26     @Deprecated
27     public static int rank(int key, int[] a
28     {
29         return indexOf(a, key);
30     }
31 
32     public static void main(String[] args)
33     {
34         In in = new In(args[0]);
35         int[] whitelist = in.readAllInts();
36 
37         Arrays.sort(whitelist);
38 
39         while (!StdIn.isEmpty())
40         {
41             int key = StdIn.readInt();
42             if (class01.indexOf(whitelist, key) == -1)
43                 StdOut.println(key);
44         }
45     }
46 }

● 前提工作:JDK 版本和 JRE 版本要對應(https://www.oracle.com/technetwork/java/javase/downloads/index.html),否則會能編譯不能運行,報錯為 UnsupportedClassVersionError;安裝教材附帶的類庫 algs4(https://algs4.cs.princeton.edu/code/,拖到中間一些的部分),需要管理員權限運行,會自動下載和安裝到用戶目錄,設置環境變量。相關鏈接(https://blog.csdn.net/fsx892512592/article/details/6038448,https://blog.csdn.net/u014629433/article/details/51593164,https://blog.csdn.net/u011240877/article/details/52457904)

● 使用命令行進行操作:將輸入文件 tinyW.txt 和 tinyT.txt 放到 src 目錄下,如圖所示。這里有若干可以說的事情:

   ① 設置環境變量 CLASSPATH 為 "." 以及 algs4.jar 的絕對路徑,可以在我的電腦的屬性里添加,也可以在命令行里臨時添加,還可以在 javac 命令中以選項的方式添加;有說法認為需要附上當前目錄 ".",我測試中有的代碼需要加,有的代碼不需要,以防萬一還是加上吧。如果不添加環境變量,則編譯報錯 "程序包edu.princeton.cs.algs4不存在" 以及后續的 "找不到符號XXX"(程序用到了 algs4 中的 In,StdIn,StdOut 等方法),如下圖所示。相關鏈接(https://blog.csdn.net/skyebefreeman/article/details/56495637)

D:\Code\Java\testJava\src\package01>javac class01.java      // 不添加環境變變量的編譯
class01.java:5: 錯誤: 程序包edu.princeton.cs.algs4不存在
import edu.princeton.cs.algs4.StdIn;
                             ^
class01.java:6: 錯誤: 程序包edu.princeton.cs.algs4不存在
import edu.princeton.cs.algs4.StdOut;
                             ^
class01.java:7: 錯誤: 程序包edu.princeton.cs.algs4不存在
import edu.princeton.cs.algs4.In;
                             ^
class01.java:34: 錯誤: 找不到符號
        In in = new In(args[0]);
        ^
  符號:   類 In
  位置: 類 class01
class01.java:34: 錯誤: 找不到符號
        In in = new In(args[0]);
                    ^
  符號:   類 In
  位置: 類 class01
class01.java:39: 錯誤: 找不到符號
        while (!StdIn.isEmpty())
                ^
  符號:   變量 StdIn
  位置: 類 class01
class01.java:41: 錯誤: 找不到符號
            int key = StdIn.readInt();
                      ^
  符號:   變量 StdIn
  位置: 類 class01
class01.java:43: 錯誤: 找不到符號
                StdOut.println(key);
                ^
  符號:   變量 StdOut
  位置: 類 class01
8 個錯誤

  ② 代碼首行寫了包名,運行時需要退到含有完整包名那一層目錄再運行。實測代碼中不加包名(把源代碼第一行注釋掉)仍能正確編譯,但是運行時會出現下面的效果,總之都無法加載主類(注意是兩種錯誤)。相關鏈接(https://www.zhihu.com/question/36537093,http://www.cnblogs.com/wangxiaoha/p/6293340.html,https://blog.csdn.net/codefellow/article/details/76601885,https://blog.csdn.net/u014427391/article/details/79743318,https://www.cnblogs.com/xyhz0310/p/6803950.html)

D:\Code\Java\testJava\src\package01>java class01.class tinyW.txt < tinyT.txt            // 內層執行,代碼無包名
錯誤: 找不到或無法加載主類 class01.class
原因: java.lang.ClassNotFoundException: class01.class

D:\Code\Java\testJava\src\package01>java package01.class01.class tinyW.txt < tinyT.txt  // 內層執行,代碼有包名
錯誤: 找不到或無法加載主類 package01.class01.class
原因: java.lang.ClassNotFoundException: package01.class01.class

D:\Code\Java\testJava\src\package01>cd ..

D:\Code\Java\testJava\src>java class01 tinyW.txt < tinyT.txt                            // 外層執行,代碼無包名
錯誤: 找不到或無法加載主類 class01
原因: java.lang.ClassNotFoundException: class01

D:\Code\Java\testJava\src>java package01.class01 tinyW.txt < tinyT.txt                  // 外層執行,代碼有包名
錯誤: 找不到或無法加載主類 package01.class01
原因: java.lang.NoClassDefFoundError: class01 (wrong name: package01/class01)

  ③ 同時使用輸入文件和重定向將兩個文件喂給程序,輸出了正確的結果,這里沒有太大問題。

● Idea 中先准備庫路徑(類似添加環境變量):File → Project Structure → Modules → 右邊的 "+" → JARs or directories → 選擇上面安裝的 algs4.jar(C:\User\Username\algs4\algs4.jar)→ 左邊 □ 不清楚是否要勾上,右邊的 Compile / Run / Test / Provided 不清楚要選哪個,姑且選了 compile。相關鏈接(https://blog.csdn.net/t95921/article/details/53585225)

● 點擊原諒錘編譯,生成字節碼文件在 out 目錄下,缺少庫則會報錯,缺少包名仍能正確編譯

● 設置運行時配置(原諒錘右邊的框)如下圖。寫了主類(好像必填),輸入參數(注意輸入文件的相對路徑是相對工作目錄而言的,不要像上面 cmd 方式那樣放進 src 或 out 目錄),工作目錄,類路徑,其他沒有改動

● 至此,程序能夠正常開始運行,但還有點問題。

  ① 直接運行會發現程序會卡在 while (!StdIn.isEmpty()) 。理由是此時 Std 中內容不明,反正找不到可以作為輸入結束的字符,所以會一直掛住。用 step into 去看會進入 StdIn.java ,如下所示,卡在 return 這一行上。需要運行時(卡住以后)在 運行窗口中手動補充結尾符 "^D"(Ecplise 或 Linux 環境中可能是 "^Z"),解決問題。相關鏈接(https://www.zhihu.com/question/62001393,https://blog,.csdn.net/dmbjzhh/article/details/80525487,https://stackoverflow.com/questions/18437181/simulate-input-from-stdin-when-running-a-program-in-intellij,https://stackoverflow.com/questions/34972425/executing-nothing-java-project-in-intellij-idea,https://stackoverflow.com/questions/14991760/stdin-isempty-java,http://www.1point3acres.com/bbs/thread-2463-1-1.html)

 1 public final class StdIn
 2 {
 3     ...
 4     
 5     public static boolean isEmpty()
 6     {
 7         return !scanner.hasNext();
 8     }
 9 
10     ...
11 }

  ② 源代碼使用運行參數是 "tinyW.txt < tinyT.txt",嘗試打印輸入參數,發現 arg[0] = "tinyW.txt";arg[1] = "<";arg[2] = "tinyT.txt",理論上應該沒有問題(主函數自行處理 "<" 后的重定向文件參數),不清楚原因,不能自動完成輸入。

  ③ 另一種解決方案,最后我把代碼改成如下所示(不耐煩用 StdIn 和重定向輸入,而是手工讀取和檢測邊界),運行參數為 "tinyW.txt tinyT.txt",能夠正確輸出結果。本章下一篇博客才成功使用教材自帶的 StdIn / StdOut 等方法,可以作為參考。

 1 package package01;
 2 
 3 import java.util.Arrays;
 4 
 5 import edu.princeton.cs.algs4.StdOut;
 6 import edu.princeton.cs.algs4.In;
 7 
 8 public class class01
 9 {
10     private class01() {}
11 
12     public static int indexOf(int[] a, int key)
13     {
14         int lo = 0, hi = a.length - 1;
15         while (lo <= hi)
16         {
17             int mid = lo + (hi - lo) / 2;
18             if      (key < a[mid]) hi = mid - 1;
19             else if (key > a[mid]) lo = mid + 1;
20             else return mid;
21         }
22         return -1;
23     }
24 
25     @Deprecated
26     public static int rank(int key, int[] a)
27     {
28         return indexOf(a, key);
29     }
30 
31     public static void main(String[] args)
32     {
33         In in = new In(args[0]);
34         In in2 = new In(args[1]);
35 
36         int[] whitelist = in.readAllInts();
37         int[] test = in2.readAllInts();
38 
39         Arrays.sort(whitelist);
40         Arrays.sort(test);
41         
42         for(int i=0;i<test.length;i++)
43         {
44             int key = test[i];
45             if (class01.indexOf(whitelist, key) == -1)
46                 StdOut.println(key);
47         }
48     }
49 }

 

▶ 其他問題

● 修改項目的類名,要注意類文件名和代碼中用到類名的地方都要改掉

● 命令行 javac 默認支持 ASCII 編碼,代碼里有中文注釋要去掉,或者在 javac 命令中使用選項 -encoding UTF-8 來改變使用的編碼類型。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM