java類路徑classpath和包

来源:https://www.cnblogs.com/f-ck-need-u/archive/2017/12/27/8127529.html
-Advertisement-
Play Games

類路徑(classpath) java編譯器編譯.java文件和java虛擬機執行.class文件時的路徑和寫法不一樣。 在沒有設置任何classpath環境變數的情況下,javac可以編譯全路徑的.java文件。例如: 編譯後,在.java同路徑目錄下生成class文件。 預設java虛擬機要從c ...


類路徑(classpath)

java編譯器編譯.java文件和java虛擬機執行.class文件時的路徑和寫法不一樣。

在沒有設置任何classpath環境變數的情況下,javac可以編譯全路徑的.java文件。例如:

javac d:\myjava\HelloWorld.java

編譯後,在.java同路徑目錄下生成class文件。

預設java虛擬機要從classpath環境變數的路徑中搜索class文件去執行,對於java虛擬機來說,這不是類文件,而是類。它只有類路徑,而沒有文件系統路徑。而classpath環境變數正是為java虛擬機提供搜索類路徑的環境。註意,虛擬機不會遞歸搜索classpath定義的路徑。

也就是說,上面的java文件可以正確編譯,但卻不能執行。但如果將classpath設置為".;d:\myjava\",則java虛擬機將從當前路徑搜索,從d:\myjava下搜索class文件。

於是上面的HelloWorld.java編譯後,可以直接執行:

java HelloWorld

或者切換到d:\myjava目錄下,執行java HelloWorld

但下麵則是錯誤的方式,最後雖然能正確編譯NewDir.java,但在執行時,將搜索當前目錄(d:\myjava)下是否有NewDir.class,再搜索d:\myjava下是否有NewDir.class,但不會遞歸到子目錄newdir中去搜索class文件。

d:\
cd myjava
javac newdir\NewDir.java
java NewDir

再例如,在d:\myjava\hello下有兩個java源文件,它們的內容分別如下:

d:\myjava\hello
    Cat.java
    Dog.java

Cat.java
=========================
public class Cat {
}

Dog.java
=========================
public class Dog {
    public static void main(String [] args) {
        Cat c = new Cat();
    }
}

其中Dog類中直接new了另一個文件中Cat類的對象,無論是編譯還是運行,這都是能成功的,因為javac編譯器編譯Dog.java時會自動從classpath指定的路徑下搜索Cat.class,正好這能搜索到,且該類又是public類,因此編譯成功。

總之,要明確的是javac編譯器搜索的是文件路徑,和環境變數classpath無關。而java虛擬機搜索的是類文件,嚴格地說是類,搜索路徑由環境變數classpath決定,且有先後順序。

更多的類路徑說明,見下麵的"包"。

包(package)

包是類的集合。在java源文件的第一行(不包括註釋行或空行)寫上package關鍵字並給定包名,即可將該類文件放到包中。

例如,d:\myjava\Cat.java文件:

package com.longshuai.home;
public class Cat {
    public static void main(String[] args) {
        System.out.println("com.longshuai.home.Cat");
    }
}

這表示將Cat類放在com.longshuai.home包中。包應該以反轉後的功能變數名稱取名,防止包重名衝突,當然,這是非必須的。

對於沒有使用package指令的源文件,在編譯時其內的類都會預設當作"裸體類"。

java管理包的方法是以對應包名的目錄層次管理的,例如上面的com.longshuai.home包,應該將該class文件放在com/longshuai/home(如果是windows,則反斜線)下,即com/longshuai/home/Cat.class。

javac在編譯時從路徑上搜索文件。例如,將這個Cat.java放到com/longshuai/home下。執行時java虛擬機從classpath搜索要載入的類文件,而載入類的方式是使用"."連接各類名。所以編譯這個文件和java虛擬機執行這個文件時的方法分別是:

javac com/longshuai/home/Cat.java
java com.longshuai.home.Cat

註意,嵌套的包之間沒有任何關係,例如java.util包和java.util.jar包沒有任何依賴關係。

使用包中的類和導入包(import)

在某個java源文件中,無法直接使用其他文件中的類,除非要使用的這個類正好能被classpath的路徑搜索到。要引用非classpath下的其他類,只能將其添加到classpath或者裝入package中,然後引用包中的類。

引用包中類可以通過指定包名的方式引用來引用。例如:

com.longshuai.home.Cat c = new com.longshuai.home.Cat();

但顯然這很不方便。可以在java源文件的前幾行(但在package命令的後面)使用import指令導入需要使用的包中的類。例如導入Cat類,這樣就可以直接使用該類了:

import com.longshuai.home.Cat;
Cat c = new Cat();

導入包時可以在尾部使用星號"*"通配導入的所有類,只能在尾部使用"*",因為"*"匹配的是類名,而不是包名。也因此,不能在非結尾處使用"*"號來表示導入其他包中的類,例如:

import com.longshuai.home.*; //導入com.longshuai.home包中的所有類
import com.longshuai.*;      //導入com.longshuai包中所有類,但不會導入com.longshuai.home中的類,
                             //因為雖然層次之間有嵌套,但這些包沒有任何關係
import com.*.*;              //這是錯誤的寫法

如果導入的包中有同名的類,則在引用同名類的時候會產生衝突錯誤,例如java.util和java.sql包中都有Date類,

import java.util.*;
import java.sql.*;

public class Test {
    public static void main(String [] args) {
        Date today = new Date();
    }
}

編譯:

javac Test.java
Test.java:11: 錯誤: 對Date的引用不明確
        Date today = new Date();
        ^
  java.sql 中的類 java.sql.Date 和 java.util 中的類 java.util.Date 都匹配
Test.java:11: 錯誤: 對Date的引用不明確
        Date today = new Date();
                         ^
  java.sql 中的類 java.sql.Date 和 java.util 中的類 java.util.Date 都匹配
2 個錯誤

這時可以顯式導入Date類,或者在使用Date類的時候指定包名。也就是說下麵兩種方法都正確:

//方法一:
import java.util.*;
import java.sql.*;
import java.util.Date;

//方法二:
import java.util.*;
import java.sql.*;

public class Test {
    public static void main(String [] args) {
        java.util.Date today = new java.util.Date();
    }
}

除了可以導入包中的類,還可以靜態導入包中類中的靜態方法和靜態變數,只需加上static關鍵字並指定要導入的內容即可。例如:

import static java.lang.System.*;
import static java.lang.System.out;

靜態導入方法後,就可以省略首碼,例如:

import static java.lang.System.out;

public class ClassName {
    public static void main() {
        out.println("HelloWorld");//等價於System.out.println("HelloWorld");
    }
}

將package歸檔成jar包

java虛擬機可以直接識別jar包。可以將package名稱對應的路徑使用jar命令歸檔成jar包。jar命令使用說明如下:

jar
用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files .
..
選項:
    -c  創建新檔案
    -t  列出檔案目錄
    -x  從檔案中提取指定的 (或所有) 文件
    -u  更新現有檔案
    -v  在標準輸出中生成詳細輸出
    -f  指定檔案文件名
    -m  包含指定清單文件中的清單信息
    -n  創建新檔案後執行 Pack200 規範化
    -e  為捆綁到可執行 jar 文件的獨立應用程式
        指定應用程式入口點
    -0  僅存儲; 不使用任何 ZIP 壓縮
    -P  保留文件名中的前導 '/' (絕對路徑) 和 ".." (父目錄) 組件
    -M  不創建條目的清單文件
    -i  為指定的 jar 文件生成索引信息
    -C  更改為指定的目錄並包含以下文件
如果任何文件為目錄, 則對其進行遞歸處理。
清單文件名, 檔案文件名和入口點名稱的指定順序
與 'm', 'f''e' 標記的指定順序相同。

例如,將當前目錄下的a.class和b.class打包到test.jar中:

jar cvf test.jar a.class b.class

查看jar包中的文件列表,會遞歸顯示:

jar -tf test.jar
META-INF/
META-INF/MANIFEST.MF
jiecheng.class

例如,將com目錄歸檔到d:\dp.jar中。

jar cvf d:\dp.jar com/
已添加清單
正在添加: com/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: com/longshuai/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: com/longshuai/home/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: com/longshuai/home/Bird.class(輸入 = 420) (輸出 = 291)(壓縮了 30%)
正在添加: com/longshuai/home/Bird.java(輸入 = 136) (輸出 = 100)(壓縮了 26%)
正在添加: com/longshuai/home/Cat.class(輸入 = 417) (輸出 = 289)(壓縮了 30%)
正在添加: com/longshuai/home/Cat.java(輸入 = 134) (輸出 = 99)(壓縮了 26%)

有了jar文件,就可以直接設置classpath的路徑為jar文件名,這樣在搜索類文件時就會直接從jar文件內搜索。例如classpath設置為:

.;d:\myjava;d:\dp.jar

類搜索機制

在java虛擬機搜索類文件時,除了classpath環境變數指定的路徑,還會先搜索兩個預設的路徑:jre/lib和jre/lib/ext下的jar文件中似乎否有待搜索的類。

例如,當classpath設置為".;d:\myjava;d:\myjar.jar"時,要搜索com.longshuai.com.Cat類文件:
(a).先搜索jre/lib和jre/lib/ext下的jar文件;
(b).再搜索當前目錄下是否有com\longshuai\com\Cat.class;
(c).再搜索d:\myjava\Cat.class;
(d).搜索d:\myjar.jar文件中是否有com.longshuai.com.Cat類。

如果在某個java源文件中引用了某個類,則在編譯時,將通過以下幾種方式判斷該類是否合理有效:

(1).搜索導入的包類中是否包含該類。
(2).搜索隱式導入的java.lang包,該包是預設導入的。
(3).當前文件中是否定義了該類。
(4).按照類路徑的搜索規則((a)-(d))搜索其中是否有該類。

繼承

類與類之間能體現"什麼是什麼"的語義邏輯,就能實現類的繼承。例如,貓是動物,那麼貓類可以繼承動物類,而貓類稱為子類,動物類稱為父類。

子類繼承父類後,子類就具有了父類所有的成員,包括成員變數、方法。實際上在記憶體中,new子類對象時,heap中劃分了一部分區域存放從父類繼承來的屬性。例如,new parent得到的區域A,new child得到的區域B,區域A在區域B中。

子對象中之所以包含父對象,是因為在new子對象的時候,首先調用子類構造方法構造子對象,在開始構造子對象的時候又首先調用父類構造方法構造父對象。也就是說,在形成子對象之前,總是先形成父對象,然後再慢慢的補充子對象中自有的屬性。具體內容見"繼承時構造方法的重寫super()"。

子類不僅具有父類的成員,還具有自己獨有的成員,例如有自己的方法、自己的成員變數。子類、父類中的成員名稱不同時這很容易理解,但它們也可能是同名的。如果子類中有和父類繼承的同名方法,例如父類有eat()方法,子類也有eat()方法,則這可能是方法的重寫(見下文)。如果子類中的成員變數和父類的成員變數同名,則它們是相互獨立的,例如父類有name屬性,子類還自己定義了一個name屬性,這是允許的,因為可以分別使用this和super來調用它們。

繼承類時使用extends關鍵字。繼承時,java只允許從一個父類繼承。

class Person  {
    String name;
    int age;

    void eat() { System.out.println("eating...");}
    void sleep() {System.out.println("sleep...");}
}

class Student extends Person {
    int studentID;

    Student(int id,String name,int age) {
        this.name = name;
        this.age = age;
        this.studentID = id;
    }

    void study() {System.out.println("studing...");}
}

public class Inherit {
    public static void main(String[] args) {
        Student s1 = new Student(1,"Malongshuai",23);
        System.out.println(s1.studentID+","+s1.name+","+s1.age);
        s1.eat();
        s1.sleep();
        s1.study();
    }
}

註:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一. 問題: 在使用solr時, 分詞器解析中文的時候, 是一個一個字解析的. 這並不是我們想要的結果. 而在lucene中, 使用的中文分詞器是 IKAnalyzer. 那麼在solr裡面, 是不是任然可以用這個呢. 二. 整合 ik 1. 修改schema配置文件 打開如下路徑中的managed ...
  • #有‘*’為重點import timeprint(time.time())#以秒的形式返回******time.sleep(3) ******print(time.clock()) #cpu執行的時間print(time.gmtime()) # 結構化時間,本初子午線那裡的時間time.struct ...
  • 一 前段時間自學了一段時間的Python,想著濃一點項目來練練手。看著大佬們一說就是爬了100W+的數據就非常的羡慕,不過對於我這種初學者來說,也就爬一爬圖片。 我相信很多人的第一個爬蟲程式都是爬去貼吧的圖片,嗯,我平時不玩貼吧,加上我覺得豆瓣挺良心的,我就爬了豆瓣首頁上面的圖片。其實最剛開始是想爬 ...
  • 本文簡單的介紹了Servlet處理響應的基本流程以及Servlet的生命周期 ...
  • 一、wxPython介紹 1、wxPython是Python語言的一套優秀的GUI圖形庫。wxPython可以很方便的創建完整的、功能鍵全的GUI用戶界面。 wxPython是作為優秀的跨平臺GUI庫wxWidgets的Python封裝和Python模塊的方式提供給用戶的。 2、wxPython是跨 ...
  • 原題是這樣的: 給出一個字元串數組S,找到其中所有的亂序字元串(Anagram)。如果一個字元串是亂序字元串,那麼他存在一個字母集合相同,但順序不同的字元串也在S中。 樣例 對於字元串數組 ["lint","intl","inlt","code"] 返回 ["lint","inlt","intl"] ...
  • Pandas基礎篇 Pandas基於Numpy開發,提供了很多高級的數據處理功能。 1、Pandas中的數據對象 Series和DataFrame是Pandas中最常用的兩個對象。 1.1 Series對象 是Pandas中最基本的對象,可用Numpy的數組處理函數直接對Series對象進行處理。支 ...
  • 許可權修飾符 許可權修飾符包括public、private、protected和不加任何修飾符的default,它們都可以修飾方法和變數。其中public和預設的default(不加任何修飾符)這兩個還可以修飾class。private和protected修飾類的情況只能在使用內部類時修飾,正常情況下不 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...