【.Net vs Java? 】 看一看二者的類有多像?


1. 包(Package)、命名空間(NameSpace)

1.1 概念

在Java中常用的是包(Package),較少提到NameSpace的概念。Java官方文檔中這樣說:

為了使類型更易於查找和使用,避免命名沖突並控制訪問,程序員將相關類型的組捆綁到包中。

定義:包是一組提供訪問保護和名稱空間管理的相關類型。 請注意,類型是指類、接口、枚舉和注釋類型。 枚舉和注解類型分別是特殊類型的類和接口,因此在本課中通常將類型簡稱為類和接口。

根據這里的概念,Package基本上是對應C#的NameSpace的。

無論是Java還是C#,每個類都有屬於一個包/命名空間:

  • Java:
package cn.flylolo.entity;
public class Pig extends Animal{

}
  • C#:
namespace cn.flylolo.entity;
public class Pig : Animal{

}

1.2 命名規則

  • Java一般用域名倒序的方式來作為包名,多個單詞用“.”分隔,同時這也對應着目錄的層級關系。

  • C#中也可以用這樣的規則來命名NameSpace,也見過這樣的命名方式,但不強制;並且與目錄也可以沒有關聯關系。

1.3 引用方式

  • Java引用包:
import cn.flylolo.entity.Pig;
  • C# 引用命名空間:
using cn.flylolo.entity.Pig;

C#的命名空間別名:若要引用同名的不同類,處理方式都是寫全包/命名空間的名稱。C#中覺得較長不美觀可以在using的時候設置別名:

using entityPig = cn.flylolo.entity.Pig;

在代碼中可以直接使用別名引用。

2.訪問修飾符

上一節,Java的包與C#的命名空間類似,但針對訪問修飾符,包又與C#的程序集類似。

C# Java 含義
public public 相同,訪問不受限制。
protected C#,訪問限於包含類或派生自包含類的類型。
private private 訪問限於包含類。
internal或不添加修飾符 不添加修飾符 同一(包/程序集)可訪問。
protected internal protected 相同,訪問限於當前(包/程序集)或派生自包含類的類型。
private protected 訪問限於包含類或當前程序集中派生自包含類的類型。 自 C# 7.2 之后可用。

3.類與文件

Java中,一個.java文件中,只允許有一個Public的類,並且文件名與此類名一般相同。

C#中則無上述限制。

4.繼承,sealed與final

4.1 繼承一個類或實現接口:

  • C#用“:" 符號。

  • Java繼承類用extends關鍵字,實現接口用implements關鍵字。

4.2 不想讓一個類被繼承:

  • Java 用final關鍵字:
public final class Shape
  • C# 用sealed關鍵字:
public sealed class Shape

注意: JDK15的時候,Java也提供了sealed關鍵字,用於限制繼承,例如下列代碼

public sealed class Shape permits Circle, Square, Rectangle {
}

通過sealed+permits兩個關鍵字,限制了子類只能是Circle, Square, Rectangle這三個。

5.Static

  • C#,有靜態類和靜態方法。

  • Java,有靜態類和靜態方法,但靜態類只能是內部類,詳見下一節。

6. 內部類、嵌套類

6.1 C#的內部類

C#的內部類比較簡單,類似如下代碼:

namespace cn.flylolo.nestedclass;

/**
 * @author luozhichao
 * @date 2021/10/15 17:50
 */
public class OuterClass
{
    public String outerClassName = "outerClass's name";

    public void printNestedClassName()
    {
        //無法直接調用內部類的變量
        //Console.WriteLine(NestedClass.nestedClassName);
        Console.WriteLine(NestedStaticClass.nestedClassName);
    }

    public class NestedClass
    {
        public String nestedClassName = "nestedClass's name";

        public void printOuterClassName()
        {
            //error 不可以直接調用外部類的對象
            //Console.WriteLine(outerClassName);
        }

    }

    public static class NestedStaticClass
    {
        public static String nestedClassName = "NestedStaticClass's name";

        public static void printOuterClassName()
        {
            //error 不可以直接調用外部類的對象
            //Console.WriteLine(outerClassName);
        }
    }
}
class Test
{
    public static void main(String[] args)
    {
        OuterClass.NestedClass nestedClass = new OuterClass.NestedClass();

        //可以直接調用靜態內部類的方法。
        string str = OuterClass.NestedStaticClass.nestedClassName;

    }
}

代碼中做了一些注釋,可以看到,對於非靜態的內部類,外部類就像給其加了一層“命名空間”,可以通過new OuterClass.NestedClass()的方式進行創建。

對應靜態內部類,可以通過OuterClass.NestedStaticClass的方式直接調用其方法和屬性,當然這也由對應的訪問修飾符決定,例如將NestedStaticClass設置為private,則OuterClass可以直接調用NestedStaticClass,而上例中的Main方法則無法調用NestedStaticClass了。

6.2 Java的內部類

再看一下Java的內部類:

public class OuterClass {
    public String outerClassName = "outerClass's name";

    public void getNestedClassName() {
        String staticString = NestedStaticClass.staticString;
        //無法直接調用非靜態內部類的變量
        //String str = NestedClass.nestedClassName;
    }

    public NestedClass getNestedClass() {
        //可以直接new
        return new NestedClass();
    }


    class NestedClass {
        public String nestedClassName = "nestedClass's name";

        public void printOuterClassName() {
            //可以直接調用外部類的對象
            System.out.println(outerClassName);
        }

        public OuterClass getOuter() {
            //返回外部類實例
            return OuterClass.this;
        }
    }

    static class NestedStaticClass {
        public String nestedClassName = "NestedStaticClass's name";
        public static String staticString = "staticString";

        public void printOuterClassName() {
            //error 不可以直接調用外部類的對象
            //System.out.println(outerClassName);
        }

        //error 無法返回外部類實例
//        public OuterClass getOuter(){
//            return OuterClass.this;
//        }
    }
}
class Test{
    public static void main(String[] args) {
        //不允許直接通過new的方式創建OuterClass.NestedClass
        //OuterClass.NestedClass nestedClass1 = new OuterClass.NestedClass();

        //只能通過外部類的實例創建內部類
        OuterClass outerClass = new OuterClass();
        //通過方法返回內部類實例
        OuterClass.NestedClass nestedClass = outerClass.getNestedClass();
        //通過.new關鍵字
        OuterClass.NestedClass nestedClass1 = outerClass.new NestedClass();

        //通過內部類實例獲取外部類實例
        System.out.println(nestedClass1.getOuter().outerClassName);
        nestedClass.printOuterClassName();

        String staticString = OuterClass.NestedStaticClass.staticString;
        OuterClass.NestedStaticClass nestedStaticClass = new OuterClass.NestedStaticClass();
        System.out.println(nestedStaticClass.nestedClassName);

    }
}

可見,Java的內部類“玩法比較多,完全寫來下可以說是一個比較大的專題了,簡要列舉一下與C#的內部類的不同之處。

6.3 非靜態內部類總結

  • 外部類都無法訪問內部類的的方法和屬性,但Java的內部類可以訪問外部類的方法和屬性,C#的不可以,Java內外部類互相訪問提供了“.New”和“.this"關鍵字。
  • 創建內部類,new的對象不同,C#通過“new 外部類.內部類() ”方式創建,Java不允許這樣,需要外部類的實例,即:”外部類實例.new 內部類()“。
  • 除了上述的內部類定義方式,Java的內部類可以出現在外部類的方法、語句塊中。

6.4 靜態內部類總結

  • C#的靜態類中不允許有非靜態方法和成員屬性,Java的靜態內部類中可以有。
  • C#和Java的內部類可以直接通過“外部類.內部類”的方式訪問,具體要考慮內部類對應的訪問修飾符。
  • C#的內部類不允許被new出新實例,Java的可以。
  • Java通過直接的方式訪問內部類,只允許訪問靜態方法和成員屬性。通過new的方式產生的實例,即可以訪問靜態成員也可以訪問非靜態成員。但不建議通過這種方式訪問靜態成員。

6.5 其他

  • Java還可以通過內部類的方式實現匿名類、多重繼承等。
  • Java8之后,一些情形可以通過lamda簡化內部類的寫法。

首發地址:C#與Java類的區別


免責聲明!

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



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