Java 與 C# 語法差異

基礎語法的差異

1. 靜態類

Java 靜態類裏面可以聲明非靜態的屬性和方法,C# 靜態類只能包含靜態的屬性和靜態的方法等

public  class People {
     static String outerStaticField = "I'm static in OuterClass";

    // 靜態內部類
    static class StaticNestedClass {
        String innerField = "嵌套內部靜態類的非靜態字段";
        static String staticFile="嵌套內部靜態類的靜態字段";
        public void printFields() {
            // 可以訪問外部類的靜態字段
            System.out.println(outerStaticField);
            // 但不能訪問外部類的非靜態字段,因爲靜態內部類不持有外部類的實例引用
            // System.out.println(outerNonStaticField); // 這會導致編譯錯誤
            System.out.println(innerField);
        }
    }
}

 2. 自定義字符串的語法糖

C# 中可以使用$"....{變量}."  的語法糖去動態寫字符串值,也可以用string.Format方式

string s = "123";
string a1 = $"{s}666";
string a2 = string.Format("{0}666",s);

Java只能通過 String.format 方式,並且C#是直接用{0}代替字符串,而Java是s%代表字符串變量, %d代表整數 等 

String s = "123";
String a = String.format("%s666", s);
StringBuilder 用法兩者都是差不多,只是 C# 提供的方法多一些

3. foreach循環

C#的foreach

String[] names = { "James", "Larry", "Tom", "Lacy" };
foreach (string name in names)
{
    Console.WriteLine(name);
}

Java中沒有foreach, 代替的是 增強型for循環

String[] names = { "James", "Larry", "Tom", "Lacy" };
for (String name : names) {
    System.out.println(name);
}

4. 獲取時間

Java推薦使用 LocalDate 類

        //方式一:LocalDate類(需要 Java 8 及以上)
        // 獲取當前日期        
        LocalDate date2 = LocalDate.now().plusDays(1); // 增加一天
        System.out.println(date2);
        // 獲取完整日期時間(包含T) ps: 2024-04-28T16:39:38.342
        LocalDateTime fullDate = LocalDateTime.now();
        System.out.println(fullDate);
        // 格式化日期時間(不包含T)  ps:2024-04-28 16:39:38
        LocalDateTime fullDate2 = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDate = fullDate2.format(formatter);
        System.out.println(formattedDate);

        // 方式二:Date 類(Java 7 以及之前的版本)
        //  使用 Date 類(Java 7 以及之前的版本):
        Date date = new Date();
        // 使用 toString() 函數顯示日期時間
        System.out.println(date);
        
        //方式三:使用 Calendar 類(所有版本中都可以使用,但是寫法相對負責)
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1); // 增加一天
        System.out.println(calendar.getTime());

 5. 數據結構

5.1  集合

C# 中只提供了List<T> 方式的集合,集合順序是有序的,按順序插入,還不能按照索引插入。

Java中提供了List和Set兩種,List又分爲ArrayList 和 LinkedList 。Set 分爲 HashSet 和 TreeSet

ArrayList(最常用的集合):
特點: 動態數組,可變大小。
優點: 高效的隨機訪問和快速尾部插入。
缺點: 中間插入和刪除相對較慢。
LinkedList: 特點: 雙向鏈表,元素之間通過指針連接。 優點: 插入和刪除元素高效,迭代器性能好。 缺點: 隨機訪問相對較慢。 HashSet: 特點: 無序集合,基於HashMap實現。 優點: 高效的查找和插入操作。 缺點: 不保證順序。
TreeSet: 特點:TreeSet 是有序集合,底層基於紅黑樹實現,不允許重複元素。 優點: 提供自動排序功能,適用於需要按順序存儲元素的場景。 缺點: 性能相對較差,不允許插入 null 元素。

List 和 Set 區別:

  1. 重複元素:List 允許存儲重複元素,而 Set 不允許重複元素。

  2. 元素的順序:List 是有序的集合,它按照元素插入的順序進行存儲並且可以根據索引訪問元素;而 Set 是無序的集合,它不保證元素的存儲順序,也不能通過索引訪問元素。

  3. 底層實現方式:List 通常以數組或鏈表的形式實現,例如 ArrayList 和 LinkedList;而 Set 通常以哈希表的形式實現,例如 HashSet 和 TreeSet

   // 使用 List 存儲重複元素
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("apple");
        System.out.println(list);  // 輸出: [apple, banana, apple]

        // 使用 Set 存儲不重複元素
        Set<String> set = new HashSet<>();
        set.add("apple");
        set.add("banana");
        set.add("apple");  // 重複元素不會被加入
        System.out.println(set);  // 輸出: [apple, banana]

ArrayList 和 LinkedList 區別

  1. 數據存儲方式:ArrayList 基於動態數組實現,支持隨機訪問,即可以通過索引直接訪問元素;LinkedList 基於雙向鏈表實現,不支持隨機訪問,只能通過迭代器或者從頭/尾部遍歷來訪問元素。

  2. 插入和刪除操作:對於 ArrayList,在列表中間或頭部插入/刪除元素時,由於需要移動元素,性能略低於鏈表;對於 LinkedList,由於只需要調整節點的指針,插入/刪除性能很好

        // 使用 ArrayList
        List<Integer> arrayList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            arrayList.add(i);
        }
        
        // 使用 LinkedList
        List<Integer> linkedList = new LinkedList<>();
        for (int i = 0; i < 10; i++) {
            linkedList.add(i);
        }

        // 訪問元素
        System.out.println(arrayList.get(5)); // 輸出: 5
        System.out.println(linkedList.get(5)); // 此處需要遍歷鏈表,輸出: 5

        // 插入和刪除操作
        arrayList.add(5, 100); // 在索引爲5的位置插入100
        linkedList.add(5, 100); // 在索引爲5的位置插入100

        arrayList.remove(5); // 移除索引爲5的元素
        linkedList.remove(5); // 移除索引爲5的元素

HashSet 和 TreeSet 區別

  1. 內部實現:HashSet 使用哈希表來存儲元素,它允許使用 null 作爲元素,是一個無序的集合;TreeSet 基於紅黑樹(一種自平衡的二叉查找樹)實現,它不允許使用 null 作爲元素,是一個有序的集合。

  2. 元素排序:HashSet 不保證元素的順序,元素存儲的順序可能與插入順序不同;TreeSet 則根據元素的自然順序或者提供的比較器進行排序,並且提供了一些額外的有序集合操作方法。

  3. 插入和檢索效率:HashSet 插入、刪除和查找元素的效率通常較高,平均時間複雜度爲 O(1);TreeSet 對於插入、刪除和查找元素的效率較低,平均時間複雜度爲 O(logn),因爲它需要維持紅黑樹的平衡。

  // 使用 HashSet
        Set<String> hashSet = new HashSet<>();
        hashSet.add("banana");
        hashSet.add("apple");
        hashSet.add("orange");
        System.out.println(hashSet);  // 輸出:[orange, banana, apple]

        // 使用 TreeSet
        Set<String> treeSet = new TreeSet<>();
        treeSet.add("banana");
        treeSet.add("apple");
        treeSet.add("orange");
        System.out.println(treeSet);  // 輸出:[apple, banana, orange]

5.2 鍵值對

C# 中使用 Dictionary<Key, Value> 

Java使用  Map<Key,Value> 。其中分爲 HashMap和 TreeMap

HashMap(最常用的):
特點: 基於哈希表實現的鍵值對存儲結構。
優點: 高效的查找、插入和刪除操作。
缺點: 無序,不保證順序。
TreeMap: 特點: 基於紅黑樹實現的有序鍵值對存儲結構。 優點: 有序,支持按照鍵的順序遍歷。 缺點: 插入和刪除相對較慢。

基本使用

 // 創建一個新的 HashMap
        Map<String, Integer> map = new HashMap<>();

        // 添加元素
        map.put("apple", 10);
        map.put("banana", 20);
        map.put("orange", 15);

        // 讀取元素
        System.out.println("獲取鍵爲 banana 的值:" + map.get("banana"));  // 輸出:20

        // 修改元素
        map.put("apple", 25);

        // 輸出Map內容
        System.out.println("修改後的Map內容:");
        System.out.println(map);  // 輸出:{orange=15, apple=25, banana=20}

        // 移除元素
        map.remove("orange");

        // 輸出Map內容
        System.out.println("移除元素後的Map內容:");
        System.out.println(map);  // 輸出:{apple=25, banana=20}

        // 遍歷元素
        System.out.println("遍歷Map內容:");
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

 

6. 類型通配符:?

在C# 中沒有這個類型通配符。

Java中相當於Object,只是比Object範圍更廣泛,?包括了Object。類型通配符更加靈活,並提供了更多的編譯時類型安全性和約束,能夠更好地適應泛型編程的需求.使用類型通配符時,編譯器可以進行更嚴格的類型檢查,確保類型的兼容性。而Object類型在編譯時不提供類型檢查,可能導致運行時的類型轉換錯誤。

public class Printer {
    public void printValue(List<?> list) {
        for (Object item : list) {
            System.out.println(item);
        }
    }
}
public static void printValue2( List<? extends Number> list) {
        for (Object item : list) {
            System.out.println(item);
        }
}

 

 

 

面向對象語法

1. 繼承

C# 不管是繼承類還是接口直接使用:進行繼承。

調用父級的方法使用base關鍵字。

如果需要重寫需要在被繼承的父類中寫virtual,override,abstract 關鍵字,在重寫的子類中用 override關鍵字

public class Parent
{
    public  void eat()
    {
        Console.WriteLine("Parent's logic");
    }
    public virtual void food()
    {
        Console.WriteLine("Parent's logic");
    }
}

public class Child : Parent
{
    public void test()
    {
        base.eat();
    }
    public override void food()
    {
        Console.WriteLine("Child's logic");
    }
}

public class GrandChild : Child
{
    // GrandChild 繼承了 Child 類
    public override void food()
    {
        Console.WriteLine("Child's logic");
    }
}

 

在 Java 中,繼承使用關鍵字extends 來繼承父類, 使用 implements 關鍵字繼承多個接口

調用父級的方法使用 super 關鍵字。

子類要重寫父類的方法,只需要在子類中使用 @Override 註解來顯式地標記即可

        class Parent {
            void printMessage() {
                System.out.println("Parent's logic");
            }
            void eat()
            {
                System.out.println("Parent's logic");
            }
        }
    
        class Child extends Parent {
            @Override
            void printMessage() {
                System.out.println("Child's logic");
                super.eat();
            }
        }
    
        class GrandChild extends Child {
            // GrandChild 繼承了 Child 類
        }

 2. 泛型

c# 泛型方法約束條件是寫在尖括號內的泛型參數後面的where子句中,具體來說,where子句是在方法的返回類型之後、緊跟在尖括號後的泛型參數列表之後的位置

public static T Maximum<T>(T x, T y, T z) where T : IComparable<T> {
    // 方法體
}

 

JAVA泛型方法的約束條件位置不一樣,寫在返回類型之前的尖括號中的。具體來說,約束條件緊跟在方法修飾符(如public static等)後的尖括號中,並用關鍵字"extends"指定泛型參數的邊界

public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
    // 方法體
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章