Java筆記:數組,異常,泛型

来源:https://www.cnblogs.com/guyuyun/archive/2020/06/08/13069095.html
-Advertisement-
Play Games

一、數組 數組也是一種引用類型,其父類是Object,使用“數據類型[]”聲明,如“int[] array”表示聲明瞭一個元素類型為int類型的數組array。 數組初始化語法: // 靜態初始化語法,即定義的時候就初始化好了所有的元素 int[] array1 = {100, 55, 30}; / ...


一、數組

數組也是一種引用類型,其父類是Object,使用“數據類型[]”聲明,如“int[] array”表示聲明瞭一個元素類型為int類型的數組array。

數組初始化語法:

// 靜態初始化語法,即定義的時候就初始化好了所有的元素
int[] array1 = {100, 55, 30};
// 動態初始化語法,初始化時只定義好數組中元素的個數,new int[5]表示創建一個
// 有5個int類型元素的數組,但是並沒有初始化數組中元素的值,只是賦予了預設值,即
// 基本數據類型的預設值和引用類型的預設值null。
int[] array2 = new int[5];

 

使用數組時,應註意以下幾點:

  • 數組是一種容器,數組當中可以存儲基本數據類型的數據,也可以存儲引用數據類型的數據。對於基本數據類型,數組中存儲的是數據的值,而引用類型,數組當中存儲的是對象的引用,即記憶體地址。
  • 數組因為是引用類型,所以數組對象是存儲在堆記憶體當中的。
  • 數組一旦創建,其長度是不可變的。
  • 數組中的元素的數據類型是統一的,如int數組則表示此數組中的元素全部都是int類型的。
  • 所有數組對象都有length屬性(註意不是length方法),用來獲取數組中元素的個數。
  • 數組中在存儲時,數組中的元素的記憶體地址都是連續的。
  • 數組對象的記憶體地址是數組中第一個元素所在的記憶體地址。
  • 使用下標訪問數組時,如果下標超出了數組的長度,則會發生ArrayIndexOutOfBoundsException異常。

數組的訪問和賦值:直接通過下標進行訪問和賦值即可,如“array1[0]=22;”。

數組的優點和缺點:

  • 優點:根據下標去檢索元素時效率極高,因為數組中的元素在空間地址上是連續的,並且每個元素占用的記憶體空間是相同的,檢索某個元素時只需要根據數組記憶體地址的起始位置就可以算出這個元素的記憶體地址,所以檢索第100個元素和第100萬個元素的地址的時間都是一樣的。
  • 缺點:一個是,為了保證數組中每個元素的記憶體地址連續性,所以在數組中間的某個位置刪除或增加元素時,會涉及到元素的向前或者向後位移的操作,此時的效率就會極低。另外一個是,數組不能存儲大數據量,因為很難在記憶體空間上找到一塊特別大的連續的記憶體空間。

數組擴容:Java中數組擴容的原理或者說方法是將小容量的數組使用“System.arraycopy”方法拷貝到大容量的數組當中,然後刪除小容量的數組,Java中數組的擴容效率是較低的,所以在數組的使用當中,應該儘量避免數組的拷貝和擴容。

二維數組:二維數組,包括三位數組等多位數組,其實就是數組中的元素又是一個數組,多少維其實由這個數組的元素“套了多少層”決定的,二維就是數組中的元素是一個一維數組,同理,三位數組中的元素是一個二維數組,然後以此類推即可。

// 靜態初始化語法
int[][] a = {
    {1, 2, 3},
    {4, 5, 6},
    {9}
};

// 動態初始化語法
int[][] array = new int[3][4];

 

Arrays工具類:這個工具類最常用的就是sort和binarySearch這兩個方法,但是註意,二分查找方法的前提是數組已經排好序了。

import java.util.Arrays;


public class ArrayToolsTest{
    public static void main(String[] args){
        int[] myArray = {3, 2, 6, 4};
        // sort方法可以將一個數組排序,但是註意,sort方法並沒有返回值,
        // 即不是返回排好序的數組,而是直接排序傳入的數組
        Arrays.sort(myArray);

        // 二分查找演算法的前提是需要數組已經排好序了
        // 返回值為元素在數組中的下標,元素在數組中不存在則返回-1
        // 但是這個方法多用來判斷數組中有沒有這個元素,因為如果數組中該元素
        // 不只一個的話,那麼返回的下標不一定是第一個元素的下標
        int indexd = Arrays.binarySearch(myArray, 6);
    }
}

 

 

二、異常

1、對異常的理解

異常也是類,每一個異常類都可以創建異常對象。

異常繼承結構:通過幫助文檔中可以看到,java.lang.Object --> java.lang.Throwable,而Throwable下有兩個子類Error和Exception,它們都是可以拋出的,對於這兩個子類分支,Error分支下的子類(包括Error自身)稱之為錯誤,錯誤一旦發生,通常是直接就退出程式了,沒有辦法及時去處理。而Exception分支下的子類(包括Exception自身)稱之為異常,異常是可以在代碼層面提前去處理的,Exception的子類又可以分為兩個分支,一個分支是RuntimeException及其子類,稱為運行時異常,另一個分支就是除RuntimeException外的其它Exception的直接子類,也稱為編譯時異常。

編譯時異常:之所以稱之為編譯時異常,是因為在編譯階段就可以發現並提醒程式員提前處理這種異常,對於這類異常怎麼提前去處理,還是得要實際使用中多練才能有更深的體會。

運行時異常:這類異常在編譯時不會報錯,但是編譯通過之後在運行時又會出錯,所以叫運行時異常,比如對於表達式10/0,除數為0肯定是錯的,但是編譯器並不會識別並提醒,編譯通過之後運行的時候肯定就會報錯了。

異常處理:處理異常的方式有兩種,一種是使用throws關鍵字和throw關鍵字,將異常拋出給上一級,讓上一級去處理(上一級此時必須處理這個異常);另一種是使用“try...catch”語句把異常捕獲,但是註意,捕獲到了這個異常不一定要去處理它,讓它直接“過”也是允許的。

2、throws拋出異常

throws使用示例:

public class ThrowsTest{
    public static void main(String[] args){
        // 這裡在編譯時會發生錯誤,也就是編譯時異常,之所以有這個異常
        // 因為在func定義中有throws關鍵字,表示這個方法在執行過程中可能會發生
        // 對應的異常(ClassNotFoundException),所以它的上一級必須去處理
        // 這個異常,不處理的話,編譯器就會不通過。
        func();
    }
    
    // 使用throws關鍵字拋出可能發生的異常
    public static void func() throws ClassNotFoundException{
        System.out.println("my func!!!");
        
        // 使用throw手動拋出一個異常
        throw new ClassNotFoundException("未找到類異常!");
    }
}

 

關於throws的使用,需要註意:

  • throws拋出的異常,通常有兩種處理方式,一種是繼續使用throws關鍵字向上一級拋出同樣的異常,即調用者自身不處理這個異常,讓再上一級去處理。另一種是使用try...catch語句去捕獲拋出的異常。
  • Java內置類或者我們自己定義的類如果有使用throws關鍵字,就表示它是編譯時異常,使用的時候必須要去處理它。
  • throws拋異常時,既可以拋出具體的異常,也可以拋出它的某個父類異常,最頂級的異常類可以是Exception類,它包含了所有異常。
  • 使用throws的時機就是如果這個異常希望調用者來處理,那麼就是用throws拋出它,其他情況應該使用try捕獲的方式。

3、try捕獲異常

try使用示例:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ExceptionTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            // 將可能會發生異常的語句放在try的語句塊中
            // try語句塊中的代碼一定會去執行,直到發生異常為止
            fis = new FileInputStream("Z:\\Study\\temp.md");
            System.out.println(10 / 0);
        } catch (ArithmeticException e) {  // 捕獲可能會發生的異常
            // 捕獲到異常後,對異常進行處理
            // catch語句塊中的代碼只有捕獲到異常之後才會執行
            // ArithmeticException e這個語句相當於是聲明一種引用類型的變數,類似於方法的形參,e保存的是異常對象的記憶體地址,並且可以在catch語句塊中去使用這個對象引用e。
            System.out.println("發生算術異常!!!");
        } catch (FileNotFoundException e) {  // 可以使用多個catch語句塊捕獲不同的異常
            // 多個catch時會從上到下依次捕獲,執行了一個catch之後,其他的catch就不會執行了
            // 並且多個catch語句時,應該遵循從上到下的“從小到大”捕獲,即具體異常在前,它的父類型依次往後
            System.out.println("文件不存在!!!");
        } finally {
            // finally塊中的語句無論是否發生異常都會處理,哪怕try塊最後有個return語句
            // 執行到return語句時也會先執行finally中的語句,再執行return
            // 可以用來處理一些無論是否發生異常都要處理的操作,如關閉文件流等
            if (fis != null){
                try{
                    fis.close();
                } catch(IOException e) {
                    e.printStackTrace();
                }
                
            }
            System.out.println("關閉文件等其他操作。。。");
        }
    }
}

 

註意,catch捕獲的異常可以是具體的異常,也可以是具體異常的父類型異常,此時可以理解為多態。

異常對象中的常用方法:

  • getMessage():獲取異常的簡單描述信息。
  • printStackTrace():列印異常追蹤的堆棧信息。

4、自定義異常

自定義的異常類需要繼承Exception或者RuntimeException,並且需要定義無參和有參兩個構造方法。

public class MyException extends Exception{
    public MyException{
        
    }
    public MyException(String s){
        super(s);
    }
}

自定義異常中的方法重寫或者覆蓋時需要註意一個語法問題,重寫的方法拋出的異常不能比父類的方法更大或者說更寬泛,只能更小或者說更具體,比如父類異常方法拋出了IOException異常,那麼異常子類中重寫這個方法時就不能拋出Exception異常,但是可以拋出IOException異常或者FileNotFoundException異常。

 

三、泛型

泛型在使用尖括弧“<標識符1,標識符2,...>”來表示,標識符代表的是某種類型。

泛型的作用其實是用它定義了一個模板,定義時並沒有寫死數據的類型,當真正使用的時候可以根據需要傳入自己的數據類型。

自定義泛型:

 /*
   自定一個泛型只需要在類名之後使用<標識符>即可
   註意,此處的標識符是隨意定義,就像變數名一樣
  */
 public class MyGenericTest<T> {
     public static void main(String[] args) {
         // 定義的時候,傳入的類型是什麼,那麼創建的對象使用的泛型類型就是什麼類型
         MyGenericTest<String> mgt = new MyGenericTest<>();
         mgt.func("自定義泛型方法測試!");
     }
 
     /*
       如果想要使用泛型定義的類型,在方法參數中直接使用即可
      */
     public void func(T t){
         System.out.println(t);
     }
 }

 

集合中泛型的應用:

 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
 
 public class GenericTest {
     public static void main(String[] args) {
         // 指定集合中的元素類型為Pet,不能存儲其它類型的元素
         // 使用new的時候可以不用再傳入類型了,可以自動推斷,此時的表達式<>也稱為鑽石表達式
         // 如果不指定泛型,也是可以的,預設就是Object類型
         List<Pet> petList = new ArrayList<>();
         Cat c = new Cat();
         Dog d = new Dog();
 
         petList.add(c);
         petList.add(d);
 
         // 迭代器的聲明也需要加上泛型的定義
         Iterator<Pet> it = petList.iterator();
         while (it.hasNext()) {
             // 原本next方法返回值的類型為Object,使用泛型之後返回的類型直接就是指定
             // 的類型,不需要進行類型轉換了。
             Pet p = it.next();
             p.play();
             // 當然,如果要使用具體的子類對象的方法,還是需要轉型之後才能調用
             if (p instanceof Cat){
                 Cat myCat = (Cat)p;
                 myCat.sleep();
             }
             if (p instanceof Dog){
                 Dog myDog = (Dog)p;
                 myDog.bark();
             }
         }
         /*
         輸出結果:
         寵物在玩耍!
         貓咪在睡覺!
         寵物在玩耍!
         狗子在嚎叫!
         */
     }
 }
 
 
 class Pet {
     public void play() {
         System.out.println("寵物在玩耍!");
     }
 }
 
 
 class Cat extends Pet {
     public void sleep() {
         System.out.println("貓咪在睡覺!");
     }
 }
 
 
 class Dog extends Pet {
     public void bark() {
         System.out.println("狗子在嚎叫!");
     }
 }

 


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

-Advertisement-
Play Games
更多相關文章
  • 第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分散式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ...
  • JVM JVM->Java Virtual Machine:Java虛擬機,是一種用於計算設備的規範,它是一個虛構出來的電腦,是通過在實際的電腦上模擬模擬各種電腦功能來實現的。 基本認知: 1.JVM是用於運行Java代碼的假象電腦,主要有一套位元組碼指令集,一組寄存器,一個棧,一個垃圾回收, ...
  • 從零開始Hibernate實戰篇:(四篇實戰代碼,循序漸進,註意事項和學習內容在代碼註釋裡面,面向有一定基礎的同學使用) 第一篇:基礎篇(搭建) Hibernate開發基本步驟: 1.導入jar包(hibernate-release-5.0.7.Final\lib的文件裡面去找所需要的jar包) 2 ...
  • 很多人接觸Python,都是從爬蟲開始,其實很多語言都可以做爬蟲,只是Python相對其他語言來說,更加簡單而已。但是Python並不止於爬蟲,在人工智慧,科學計算等方面的應用更加廣泛。古人雲:萬丈高樓平地起,要想有長足的發展,打好基礎很重要,本文主要講解Python的面向對象相關知識,僅供學習分享... ...
  • 1、問題描述 安裝在docker容器裡面的storage一直處於退出狀態,導致文件無法存儲。 2、解決方案 查看docker中安裝的容器 docker ps -a 嘗試啟動容器 docker start storage (或者 docker start "容器ID") 若嘗試啟動容器後,容器仍處於退 ...
  • 1 from datetime import * 2 today=datetime.today() 3 now=datetime.now() 4 5 #判斷今天是星期幾 6 today.isoweekday() 7 8 #計算一周以後是星期幾 9 day=timedelta(days=7) 10 t ...
  • 上一節給大家分享了掃雷游戲的源代碼,本篇文章當然也不會讓大家失望,專門針對C語言入門或者學習了部分知識之後的小伙伴來練手的游戲項目——《五子棋大戰》,本期並不是使用的easyX,因為考慮到有些大學的同學沒有接觸到這個,所以本期就是一個“黑漆漆”的控制台界面,這個就希望大家諒解哈!,話不多說,下麵我們 ...
  • 註意:一定要跟著博主的解說再看代碼的中文註釋及其下麵的一行代碼!!! 說到api版本控制,就是我們的前端人員請求的後臺介面可能有多個版本,後臺的介面地址一般是有兩種形式,博主現以這兩種形式逐一解釋api版本控制組件的源碼剖析。 第一種api版本控制的url格式一般是:http://localhost ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...