日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面向对象程序设计_面向对象的程序设计(续)

發布時間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面向对象程序设计_面向对象的程序设计(续) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫在前面:這里是續之前的那篇文章,同樣源于本人的個人博客,在知乎為了一個備份

這里是7-10章

Chapter 7: Arrays 數組 記得在C語言里面,也有提到過數組這個概念 記得RT也說過這玩意會很難結果花了3節課來講這玩意 還好期末考試沒考.... [scode type="green"]Array Basic[/scode] 首先老樣子先來看看語法 int a[] = new int5; //套公式的話就像這樣elementType[] arrayRefVar; //舉個栗子 double [] myList; 數組能被視作一個變量或者是一個數據集合 不過值得一提的是,當一個數組被創建出來之后,其大小就是固定的不會被改變的了 其實數組就像冰塊盒,單行的那種,我們能往盒子里放東西,同樣也能取東西出來 哦對了記得數組是從 0 開始的啊 public static void main(String[] atgs) { int[] array1; double[] array2; char[] array3; } 我們可以聲明一個數組(也就是上面的那個array1)為一個變量,相似于int a; 既然我們已經聲明了一個數組,但是并沒有真正的創建出來 為了創建一個數組,剩下的需要做的事情就是給它賦值了 array1 = new int10; array 2 = new char[100]; 上面的那個就是聲明變量并且創建變量,但是這個過程其實可以在一行代碼中就解決掉 int [] array4 = new int5; 不過我覺得能用兩行還是用兩行比較好 比較到后面檢查來說的話也比較方便嘛 一行就像濃縮咖啡,容易嗆著 關于我們用數組和它的儲值的話可以用一張圖來表示出來

之后,想再次查看數組的長度的話,可以使用 數組名字.length 來查看數組的長度 [collapse status="false" title="關于數組的其他操作"] 當我們輸入數組后加個句號(英文的句號)的時候,就會彈出這樣一個菜單

這個菜單列出的都是關于數組的基本操作 可以選擇一些需要的 [/collapse] 記得之前CC講過一個message.length, 感覺這兩個玩意的性質應該都差不多是一個意思 就是用來計算長度的嘛 那么問題來了,如果說我們需要輸出一個數組里面的數字,咋整? 講道理用一個循環就好了 數組輸出的套路一般都是array[i],其中的i要求就是i++,說白了就是加一加一加一這樣來輸出 用代碼表示的話可以表示為 for ( int i = 0; i < 5 ; i++) { System.out.println("array[i]"); } 這樣子就沒問題了 當我們前面對array數組進行了一系列的賦值操作之后,這里就能一行一行地顯示出來數組里的數字 [scode type="green"]Accessing Array Elements 引用數組元素[/scode] 這里提到的一點就是 當我們去引用我們創建的數組里某一個具體位置的元素的時候,這個數組下標是從 0 開始的 然后最大的數字是一直到 (數組大小 - 1) 的這個位置 比如說我們創建了一個大小為10的數組,那這個數組的下標的最大值就是 9 而不是 10 [scode type="green"]Foreach Loops 關于Foreach 循環[/scode] 這里補充一個小知識點 可以把它叫做數組的便利 就是可以用比較簡潔的方法來將數組里的元素快速地提取出來 首先先來看語法 for (double e: myList) { System.out.println(e); } 就是在for循環中加上 double e: array 就可以了 里面的x可以換成任意的變量,只要不沖突的就行 這句話的意思就是將數組里的數字取出來存放在變量X中,這里我們可以在循環內部加上一個println語句來將其輸出出來 哦對了,我們定義的這個用來存放數據的這個數據類型,一定要和數組里面的數據類型是一致的 比如數組里的是分數的話,那我們定義數組類型的時候就不能定義為int 還是以前那句話,double保平安 [scode type="green"]數組的綜合運用[/scode] 這節課老師用邊上課邊講的方式,喊我們做了個綜合的小練習 這里就po出我的答案啦 package ClassWork; public class ArrayExerise { public static void main(String[] args) { // TODO Auto-generated method stub int[] Jackey; Jackey = new int5; //or you can write like that: //int[] Jackry = new int5 //or int Jackry[] = new int5 //both ok //Initializing arrys with random values 使用隨機數字初始化數組 for (int i = 0; i < Jackey.length ; i++) { Jackey[i] = (int)(Math.random() * 100); //[0,1) //0.555555 -- 5.5555555 -- 55 //() will change the level //加了括號的內容會改變運算的優先級 } //Display arrays 顯示數組內容 for (int i = 0; i < Jackey.length ; i++) { System.out.print(Jackey[i] + " "); } System.out.println(); //Sum all elements int sum = 0; for (int i = 0; i < Jackey.length; i++) { sum += Jackey[i]; } System.out.println("sum :" + sum); //Find the largest element int large = Jackey[0]; for (int i = 1; i < Jackey.length ; i++) { if(Jackey[i] > large) { large = Jackey[i]; } //這里就算去掉上面這個if的花括號也是ok的 } //上面這個for的花括號也可以省略 //因為里面的if是一條語句 //在Java的語法中,只有分號會被視為一條語句 System.out.println("largest : " + large); //Random shuffling 隨機洗牌 for (int i = Jackey.length - 1; i > 0 ; i--) { //generate a random index j //[0 , i] int j = (int)(Math.random() * (i + 1)); int temp = Jackey[i]; Jackey[i] = Jackey[j]; Jackey[j] = temp; } for (int a = 0; a < Jackey.length ; a++) { System.out.print(Jackey[a] + " "); } //Display arrys System.out.println(); //shift elements 移位 int temp = Jackey[0]; for (int i = 1; i < Jackey.length ; i++) { Jackey[i - 1]= Jackey [i]; } Jackey[Jackey.length - 1] = temp; //Display arrays //foreach loop for (int output: Jackey) { System.out.print(output + " "); } } } [scode type="green"]Copying Arrays 數組的復制[/scode] 如果說人類史上最偉大的發明是什么 那我會回答是Ctrl + c and Ctrl + v 當然這種方法也能用在數組上 首先我們先看回到我們以前的賦值方法 在我們賦值數字的時候,一般都是用a = b 來將b的值賦值給a 不過你放心,在數組里的方法肯定不一樣,因為劇本不允許 首先我們要先清楚數組的概念 數組可以將其理解為一個小倉庫和名字,假如我們有兩個小倉庫,名字分別為list1 和 list2

list1 和 list2 都分別有對應的倉庫與其連接,互不干擾 但是當我們執行list2 = list1 這個語句之后,其就會變為

可以看到原本屬于list1的倉庫被貼上了list2的標簽,這也就意味著list1 和 list2都指向同一個倉庫了 結果空巢倉庫list2就沒人管了 這顯然不是我們想要的結果 那么什么是正確操作呢? 為了給數組進行正確的賦值操作,使得兩個數組的值完全一模一樣,我們可以用3種方法

  • 使用循環賦值
  • arraycopy 方法
  • clone方法
  • 首先我們先來看一個一個賦值的基本方法 比如先把數組導入到一個循環里面,然后使用循環將數組里面的數字一個一個的提取出來,并賦值到它應該去的地方 先用一段代碼來表示這個 int[] sourceArray = {2, 3, 4, 5, 10}; int[] targetArray = new int [scourceArray.length]; for (int i = 0; i < sourceArray.length; i++) { targetArray[i] = sourceArray[i]; } 這里就不解釋代碼了,這段代碼比較簡單易懂 我們把重點放在第二種方法上----arraycopy method 數組復制 所謂的arraycopy方法其實就是調用一個存在于系統里的方法,來給指定的數組進行復制 arraycopy(sourceArray, srcPos, targetArray, tarPos, length); 括號內的東西:原數組的名字,原數組的位置,目標數組的名字,目標數組的位置,賦值對少個 所謂原數組的位置的意思就是你想從幾號元素開始復制 最后的賦值多少個的意思就是 按照2345這樣的順序依次復制下去 比如我們最開始希望把源數組的2號位置賦值給目標數組的一號位置,如果我們最后那個數字填的是10,那第一個數字賦值完成后,就會開始把源數組3號位置的值賦值給目標數組的2號位置,并且以此類推 現在有一個問題,已經聲明大小的數組,我們能用相同的語句去改變它的大小嘛 用代碼來表示的話就是 int[] myList; myList = new int10; mylist = new int20; 答案是不行的 因為這樣的代碼并沒有改變數組的大小 原來那個大小為10的數組任然在內存中駐留 而我們的myList指向了另外一個大小為20的數組 因為在內存里面,數組是隨著創建的完成就會被分配出一個空間來儲存它的 當我們輸入myList = new int20的時候,內存就會自動分配一個20空間的地方來存放這個新數組 但是原來那個數組就沒人管了 又成了個空巢數組 [scode type="green"]Passing Array to Methods 把數組在不同方法中傳遞[/scode] 我們可以先自定義一個方法 public static void printArray(int[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i] + " "); } } 然后我們可以在主方法中call它,記得在括號內放上需要的數據 printArray(new int [] {3, 1, 2, 6, 4, 2}) 這樣子就沒問題了 至于使用什么方法傳遞出去的話,可以在call方法前先定義int數組,到時候傳遞的話就是直接把整個數組個發過去了 哦對了,這個和我們之前那個pass by value 有一個很重要的區別 當我們調用一個方法的時候改變的是變量的值而不是變量本身 但是我們把Array傳遞到其他方法的時候,我們可以在傳遞的時候會加上具體的數字,比如 printArray(new int[] {1, 2, 3, 4, 5}); 或者也可以直接使用 printArray (a); 來將數組直接顯示出來 (看起來之前那個有些麻煩) 這樣子就能將數組傳遞到別的方法里,然后數組在方法內部進行了修改,意味著數組本身就被修改了 我們把數組傳遞給方法的時候,可以被描述為 pass by-sharing 即通過分享的方式進行傳遞,意味著array所指代的東西被分享給了調用的方法。哦對了,方法內部的數組和被傳遞過去的被調用的數組是同一個數組 這個和數值在方法之間的傳遞有著根本的區別 所以我們在方法內部改變其內容的時候,數組的內容是真的被改變了的 當我們回到主方法再調用其的時候,其內容是真的被改變了的 [scode type="green"]Heap 堆[/scode] 我們之前講過一個Stack 棧 的概念 這玩意是后進先出,就像往桶子里放東西一樣 如果要拿出來的話都是先拿最上面的,也就是后進來的 但是Heap 堆 這玩意就有點點不同了 這個像個管子,先進來的就會先出去

    [scode type="green"]Return an Array from a Method 把數組作為一個返回值 [/scode] 我們不止可以用一個返回值將結果從一個方法輸出出來,也可以試試看數組 舉個栗子 public static int[] reserse (int[] list) //我們需要在方法頭定義我們需要返回一個數組 { int[] result = new int[list.length]; for (int i = 0, j = result.length - 1; i , list.length; i++, j--) { result[j] = list[i]; } return result; //這里返回一個數組 } 哦對了你知道什么是return 0 嘛 記得在C語言里面,call一個方法是必須要Return的,如果沒啥可返回的話,那就Ruturn 0 但是在Java中,如果沒啥可返回的話,那就在方法頭那里定義為void就可以了 但是在需要返回東西的方法里面,方法頭定義void的話是一定會報錯的 舉個栗子,比如我們需要返回一個一維數組 那我們方法頭就應該寫 int[] [scode type="green"]Searching Arrays 數組的搜尋[/scode] 搜尋和排序是計算機里的非常重要的內容,在未來我們會學習一門磚門的課程來詳細講解 這里我們需要有一個基本的了解 我記得上學期CC在一開學就講過這個東西,還是熟悉的PPT還是熟悉的內容 就是在一堆名字中找到一個指定的名字 首先將名字按照首字母排序完成,然后按照二分搜索 Binary Search 來搜索 [scode type="green"]The Linear Search Approach 線性查找法[/scode] 說白了就是按順序 sequentially 的 依次比較數組中的元素 我們只需要用一個循環去查找就行了就是把數組里的元素一個一個和我們的關鍵字進行對比 然后返回結果 就算沒匹配到也要返回結果 舉個栗子 public class LinearSearch public static int linearSearch(int[] list, int key) { for (int i = 0; i < list.length; i++) { if (key == list[i]) { return i; } return -1; } } 如果能找到的話,就返回指定數字位于數組中的第幾位 然后如果找不到的話,就返回一個指定的數字,當然這個數字我們可以自定義的 然后我們在Main里面只需要call一下這個方法就可以了 比如 int i = linearSearch(list, 4); 其返回值應為 1,意識是找到了,在數組的第二位 哦對了,這里再強調一下,數組是從0開始計算的! [scode type="green"]The Binary Search Approach 二分查找法[/scode] 如果我們想使用二分查找法的話,這個方法會更快一點 所謂的二分法就是 先將現有數據排序 must already be ordered ,然后將數據的中間值和關鍵字做對比 如果在數據中間值之前,那就搜索中間值往上的內容,往下的內容就不考慮了 在中間值往上的內容中,取中點在進行一次運算和取值 這樣子就有點像2的多少次方的感覺 因為都是一半一半地來做 這樣子能夠大大提高搜索的效率 這個方法叫做二分查找法

    package binarySearch; import java.util.Scanner; public class TestBinarySearch { public static void main(String[] args) { int[] list = {2, 4, 7, 10, 11, 45, 50, 59, 60, 66, 69, 70, 79}; Scanner input = new Scanner(http://System.in); int num = input.nextInt(); int i = binarySearch(list, num); if(i >= 0) { System.out.println("Found " + list[i] + ". Its index is " + i); } else { System.out.println("Not found."); } input.close(); } public static int binarySearch(int[] list, int key) { int low = 0; int high = list.length; //取數組最大位數為最大循環數 while(high >= low) //這里是啟用一個循環,循環內部是最大數和最小數 { int mid = (low + high) / 2; //取中位數 if(key < list[mid]) //比較中位數和關鍵字的位置 { high = mid - 1; //縮小取值范圍,將中位數的前一位數設置為最大值 } else if (key == list[mid]) //直到找到與關鍵字相匹配的中位數為止 { return mid; } else { low = mid + 1; } } return -1; } } [scode type="green"]Sorting Arrays 選擇排序[/scode] 真的,當我看到老師放的這個視頻的時候,我就知道已經沒有說太多的必要了 直接點擊視頻就可以看了 一個視頻勝過千言萬語 那么問題來了,如何使用代碼實現這個操作呢? 開整: package selectionSort; public class TestSelectionSort { public static void main(String[] args) { int [] list = {34, 13, 5, 25, 56, 21, 59, 85, 2, 43}; selectionSort(list); for(int i: list) { System.out.println(i + ""); } } public static void selectionSort(int[] list) { for (int i = 0; i < list.length - 1; i++) { int currentMin = list[i]; int currentMinIndex = i; for (int j = i = 1; j < list.length; j++) { if (currentMin > list[j]) { currentMin = list[j]; currentMinIndex = j; } } if (currentMinIndex != i) { list[currentMinIndex] = list[i]; list[i] = currentMin; } } } } 其實說到排序方法的話 還是用一個視頻來講比較好 這樣子可以說簡單明了了 (我感覺最后那個好好玩啊哈哈哈哈哈哈哈) 就有那種嗚啦啦啦啦啦~的感覺 Chapter 8: Multidmensional Arrays 我們之前講過一維數組,關于一維數組的概念這里就不BB啦 實在是記不得里的話可以向上看看 現在我們來講講二維數組 [scode type="green"]Introduction 簡介[/scode] 這個時候可能就有人要來問了,我們為啥要學這玩意列? 其實我也不知道(小聲) 但柿!根據可靠消息,我們可以在以后用這個來處理矩陣 再往深奧一點的意義來講的話 計算機圖形學里面,一張圖片的所有信息能用一個二維矩陣全部裝下去 (我估計可能使用數字表示顏色,用二維矩陣來表示坐標像素點位置) 總之就是非常重要(揚聲器最大聲) 老樣子我們先來看看二位數組的語法 double [] [] sample = { {2, 2}, {2, 2} }; 這里有幾點需要注意的

  • 這里所使用的是兩個 "[]"
  • 記得里面的每行都需要用逗號結束
  • 需要使用兩個"{}"來將數字括起來
  • 雖然和一維數組一樣要以分號結尾但我感覺還是寫出來比較好
  • 一般的,我們使用兩個中括號來表示這個是個二維數組 [scode type="green"]Two-Dimensional Arrays Basics 二維數組的入門到放棄[/scode] 這里首先來講講數組的命名規則 int [] [] matrix;//declare the matrix matrix = new int 5;//fu zhi the matrix 二維數組的創建和一維數組的創建總是有無限的接近 不過后面那兩個中括號可大有講究 第一個中括號表示行 第二個中括號表示列 這個順序是無法被改變的 哦對了,這里有個很坑的地方,就是 emmmmmmm...... 得了我感覺我不懂怎么表達 還是用圖片來說比較好

    你看括號內的是5,但是這個數組最高的就是到4而已 因為數組是從0開始噠! 在看到上面那個圖片的第三個數組 這個就是直接把創建個命名弄到一起去了 不過記得前面提到過的創建數組的幾個點 那么如果我們想知道數組的長度呢? 這里可以使用 x.length 來獲取 不過在二位數組里,我們不止想知道數組有多少行,還想知道數組有多少列呢? 這里可以用 x [0].length 來獲取 簡單的來說,想要多少行就直接用 x.length,想要多少列就直接用 x[0].length 我估計這玩意用在考試里肯定很酸爽 [scode type="green"]Ragged Arrays 鋸齒狀數組[/scode]

    一張圖片解決戰斗 這個是說明如何創建這個數組的 并且這里說明了一個很重要的一點 二位數組的每一行都可以是不一樣的 他們每一行都是一個獨立的一維數組 不過可能有人說,不喜歡上面的這個創建的方法,希望能有更厲害的方法呢? 這里有個可以讓代碼看起來更厲害的方法 int[][] triangeArray = new int5; triangleArray[0] = new int5; triangleArray1 = new int4; triangleArray2 = new int3; triangleArray3 = new int2; triangleArray4 = new int1; 這樣子其實達到的效果和上面那個是一樣的 這里看到上面在定義數組的時候,多少列這里是留空的 也就意味著這玩意可以不寫 我們在后面再去聲明就可以了 我們可以通過一個小程序來簡單的了解數組應該如何正確食用 package multi; import java.util.Scanner; public class TestArray { public static void main(String[] args) { //declare, create, assign //method 1 int[][] matrix; matrix = new int[3][42]; //matrix 2 int [][] matrix2 = new int[3][43]; //method 3 int[][] matrix3 = { {1, 2}, {3, 4}, {5, 6} }; //1. Initializing arrays with input by user Scanner input = new Scanner(System.in); System.out.println("Enter " + matrix.length + " rows and " + matrix[0].length + "colums interger numbers:"); for (int i = 0; i < matrix.length ; i++) { for (int j = 0; j< matrix[0].length; j++) { matrix[i][j] = input.nextInt(); } } //2.Printing arrays for (int i = 0; i < matrix.length ; i++) { for (int j = 0; j< matrix[0].length; j++) { System.out.print(matrix[i][j] + " "); } System.out.println(); } //3. Summing all elements //4. Summing elements by column for (int column = 0; column < matrix[0].length; column++) { int total = 0; for(int row = 0; row < matrix.length; row++) { total = total + matrix[row][column]; } System.out.println("The Sum of this column " + column + " is " + total); } } } [scode type="green"]Processing Two-Dimensional Arrays 把二位數組作為參數傳遞到不同方法中[/scode] emmmm....... 這玩意和一維數組的完全一樣 感覺不想多BB了 直接看前面的把 pass by sharing的概念都是一樣的 Chapter 9: Object and classes 之前咱們講了半天,歸根結底還是一句話 --找不到對象 這句話在現實中也是很實用的 (:з」∠) [scode type="green"]Defining Class for Object 定義[/scode] Object-oriented programming (OOP) 對象編程 一個對象可以表示顯示生活中的實體entity 這些實體都有一些獨特的一些特征,比如狀態之類的 雖然所有的貓都是貓,但是卻不是同樣的實體 比如CC的貓,所有的貓都有不同的貓 因為他們有一些特定的屬性,一些特定的行為 比如最喜歡的是何物,毛發,年齡之類的 這就意味著每一個貓都是獨一無二的對象 但是這些貓都屬于同一個種類,這個就叫類Class

    數據域 data files 數據域用來表示這一個類所有的對象的屬性 方法 Method 表示這一個類的對象的行為,也就是他所做的事情 一個對象擁有非常獨特的特征,比如它會在晚上12點的時候起來去看看家里有沒有老鼠 反正我是沒見過抓老鼠的貓 可能我看的都是假貓 類 Class 記得我們之前說過,所有的貓都可以被定義為“貓”這個類 類是一個藍圖,是一個抽象的概念 它定義了有著相同屬性的對象 而對象是類的一個實例 An object is an instance of a class 那么問題來了,是先有類還是先有對象呢? 答案是先有類 因為找不到對象... 好了言歸正傳,我們把用類轉換為實例的過程稱之為 實例化 Instantiation ,就是通過類來生成這么一些對象的這個過程 下面我們來看一個栗子

    這是個關于幾何圖形的小程序,在未來很多的編程類型中,我們會基于這一個基礎來發展開來 幾何圖形有很多種不同的類型,假如是一個特定的圖形,那他們都會有一個相同的特征 今天我們先來看看圓形 看到上面的object 1、2、3,這3個方法都屬于上面這個circle這個類 然后所有object中不同的區別就是在于圓的半徑 這里圓的半徑Radius叫做這個圓的數據域 data files 假如我們先創建出來一個小圓,當我們把這個圓放大的時候,實際的動作其實是改變這個圓的半徑 假如我們需要計算這個圓的半徑、周長,這里都是用方法來實現的 這里可能有人要問了,如何用代碼來實現這個看起來很不錯的功能呢? class Circle //這里注意,類的首字母需要大寫 { //data fields or data members double radius; //constructors //default constructor Circle() { radius = 1; } //the second constructor Circle(double newRadius) { radius = newRadius; } //methods double getArea() { return radius * radius * Math.PI; } double getPerimeter() { return 2* radius * Math.PI; } double setRadius(double newRadius) { radius = newRadius; } } 這玩意感覺是C語言... 哦對了,有時候我們可能會看到一個玩意,叫UML Unified Modeling Language (UML) 統一建模語言,一般會以縮寫的形式存在 這玩意就是大家遵循這樣的規則來對某個事情進行概括

    哦對了,這里有個玩意叫 Constructors 構造方法 A constructor is invoked to create an object using the new operator 構造方法是用來生成一個用來生成一個屬于這個類的對象 類似于普通的方法一樣,我們可以調用這個構造方法 但是調用構造方法的目的和作用就是生成一個屬于這個類的對象 構造方法有3個特征: [scode type="blue"]

  • 構造方法的名字必須和類的名字一模一樣,甚至連大小寫也要一模一樣
  • 構造方法沒有返回任何東西,甚至連void都不需要
  • 當被其他方法被調用的時候,需要用 **new ** 操作符來進行調用
  • [/scode] 那么可能有人要問了,這個有什么意義呢? 出現了!一意義怪! 其實我也不知道(攤手) 下節課再說唄 哦對了,當我們寫完了程序之后,我們能在電腦中找到這個玩意的源文件 至于文件保存在什么地方的話,就是在創建的時候設置的地方 然后編譯器也會把我們所寫的源文件編寫為.class文件 Java會直接去執行編譯完成的.class文件而不會去執行java源文件 [scode type="green"]Via Reference variables[/scode] 哦對了 不知道你注意到沒有 前面那個代碼,好像沒有main 記得之前Cc說過,所有程序的開頭永遠是從main方法開始的 但是前面這個沒有 那我們就需要再創建一個main方法出來 所以我們在上一個pacage內再創建一個class 取名為TestCircle(再提一次,類的首字母要大寫) 然后這里就可以勾上最喜聞樂見的Main方法了 pacage circle; public class TestCircle { public static void main(String[] args) { //int radius; Circle circle1 = new Circle(); //calling the constructor of Circle Class System.out.print(circle1.radius); System.out.println(circle1.grtAtea()); System.out.println(circle1.getPerimeter()); //get method form class Circle circle1.radius = 100; System.out.println(circle1.getArea()); circle.setRadius(10000); System.out.println(circle1.getArea()); //we can change the value in constructor Circle circle2 = new Circle(20.000); //calling the second construction of Circle Class System.out.print(circle2.radius); System.out.println(circle2.grtAtea()); } } 首先我們先把視線放在 Circle circle1 = new Circle(); 這一行上 先來對比這兩行代碼 int[] array = new int10; Circle circle1 = new Circle(); 可以看到,和創建數組的語句類似,創建和引用構造方法是非常類似的 我們首先需要先聲明這個是個什么類的,當然這個類是我們已經自定義的了 其實Circle circle1 = new Circle();這玩意可以拆分為兩行 Circle circle1; circle1 = new Circle(); 當然這個和數組的也是非常類似 因為數組也能拆分為兩行 int[] array; array = new int10; 然后circle1這個是可以自定義的名字,有個更專業的名字叫 Reference Vriable ,雖然專業名字更讓人看不懂,但是這也不影響我們可以給circle1取什么名字都可以,但是要遵循命名規則 比如iLikeLion 首字母小寫,其后每個單詞首字母都需要大寫 之后的那個new是一個特定的操作符,后面接著的是構造方法,用來生成一個對象 Circle() 表示調用 類 Circle 構造方法 這里有一點值得注意,當我們使用Circle(100)的時候,表示向方法中傳遞數字,這里就不會使用Circle()這個方法,而會使用 Circle(double radius)這個方法 這里我們引入一個概念: instance 實例的 對象是類的實例化 這個概念還是蠻重要的 舉個栗子,instance vaiable實例變量 ,比如我們前面那個小程序中的半徑就是實例變量 instance method 實例方法,比如我們前面的getArea方法,因為這個方法都是由某一個具體的對象所決定的 換句話說,當圓的半徑改變的時候,getArea得出來的值也會隨之改變 [scode type="green"]Call method from another package[/scode] 假如有一天,我們想引入其他package里面的類甚至是類里面的方法,是否有這個操作呢 我們可以使用import 來實現這樣的操作 這個 詞我們之前也曾提到過 就是import java.util.Scanner這個 講道理這兩個東西真的是太相似了 舉個栗子

    在上面這張圖中,假如為我們想在rectange里調用circle里的東西呢 只需要使用 import circle.Circle; 就可以了 import //導入 circle. //來自package circle Circle //package circle 里的 類Circle 但是,當你引用了這個東西,它或許還會報錯 畢竟報錯就是java的靈魂 沒有報錯的java是不完成的java 這個是因為我們之前在寫類Circle的時候,里面的構造方法沒有設定為publie 簡單的來說,如果不加public的話,這個method就是僅限內部員工使用的 當我們給類Circle的構造方法Circle() 加上public 之后,它應該變為這樣 public Circle() { } 這樣就沒問題了 哦對了,雖然說一個Java源文件中能包含多個類,但是public這玩意也不能亂用 [scode type="red"] "one or more classes in one java file. But only one class coule be defined as 'public' "

    • 每個類里面只能有一個public

    "the public class's name should be exactly same as the file name"

    • 有public的類必須和類的名字相同(就是左邊那個列表里出現的類的名字)

    "main() will be put inside a public class , public class is like a string point"

    • main()里的public是不可少的,也就是說在main方法所在的類必須要加public

    " if there is no public class, then your main method coule be put in any one class. but if there is a public class, your main method must be in the public class"

    • 如果一個源文件中沒有public類的話,那main()放在哪個類里面都是ok的。但是程序中有一個public類的話,主方法必須要放在public類里面

    [/scode] 用一張圖來總結類和對象的關系

    [scode type="green"]different between Cariables of Primitive Types and Reference Types[/scode] 這里要撤回去一個概念,我們回到原始數據類型 primitive type 原始數據類型一共有8種,int, double ,float, char, boolean, byte, short, long 對于原始數據類型,我們為其賦值的時候,其實就是用所需要的的值去覆蓋去替換掉原始數值 假設我們寫了一條指令 int i = 1; 這個實際上就是在我們電腦內存中,有這么一個棧,這個棧存放了我們寫這一行代碼的信息 同時,int會被賦值為1,這也就意味著在電腦存放 i 這個位置的地方會被 1 所代表的值所取代 那么現在的類和對象的概念有啥不同呢 記得之前在第七章數組這個概念中,提到過數組的賦值方法是 pass by sharing 也就是箭頭和倉庫(地址)的問題(詳情可以在右邊找Chapter7 ) 雖然數組會被賦值但是原始數組并沒有消失,只是沒有指向這個數組的標志了 其實類的在電腦桌存放的概念和數組非常相似 這玩意叫 Reference Type

    當我們將c2的值賦值給c1的時候,c1將會指向c2所在的那個倉庫(address) 但是實際上c1原來所指代的那個倉庫還是保留在內存中的 我們改變的就是c1所指代的位置 [scode type="green"]Static Variables, Constants, Methods[/scode] static,靜態的 static variables 靜態的變量 static constant 靜態的常量 static method 靜態的方法 那么到底什么是靜態的呢? 我們來舉個例子,假如一群人去吃火鍋,我往里面瞎了眼一份牛肉丸 那么這些肉丸大家都可以吃得到,因為我們是吃的同一個火鍋 static 但是如果是一人一個小鍋,我往我自己的鍋里面下了一份牛肉丸,那么這一份牛肉丸就是我自己獨有的 private 這里就是借助牛肉丸的概念來理解static的意思 static是能被所有對象共享的,所有的方法都可以訪問它

    記得之前在寫圓的面積周長啥的時候,我們有一個圓的半徑,就是 π 這個玩意 π 需要被多個 method 共同使用,但是卻沒有任何東西能改變它的大小 這個時候, π 就是一個靜態的常量 static constant 所以我們可以在代碼的第一行中加入 final static double PI = 3.1415926; 來給定 π 的值 這樣我們在后面的代碼中就不需要使用math.PI了,就可以直接使用PI 接下來我們來看看靜態的變量 static variables 假如我們需要一個變量來記錄這個程序到底執行了多少次 雖然只需要使用count++就能解決的事情 但是這個變量還是有類型的 這個類型就是靜態的變量 比如我們在執行完方法1后,使用count++來記錄方法1執行的次數 這個時候我們去執行方法2,但是也使用count++來記錄方法2的執行次數 在這里方法1和方法2使用的都是同一個count來記錄的 這一個變量它不是僅僅依賴于某一個具體的源變量本身,而是被所有的源對象共享的 我們把這樣的變量叫做 static variables 因為這個變量是被這個類所共享的,所以也能叫類變量 class variable 在創建靜態變量的時候,我們可以使用 static int circleNumber = 0; //如果我們最開始不定義其為0的話,它會默認賦值為int類的初始值,也就是0 說到static method, 感覺也挺簡單的 這玩意創建的方法就是 static int getNumberObjects() { return numberOfObjects; } 沒了 不過值得注意的一點是,我們如果希望在UML中表示出這個方法是靜態的方法的話,需要在其下加一條下劃線 同樣在變量中也是一樣的,加了下劃線的表示靜態的變量 用圖表示的話就像這樣

    那么,對于靜態的方法和實例的方法有什么區別呢? 簡單的來說,實例的方法可以訪問這個類的所有的方法和變量(數據域) 但是靜態的方法被設計為只能訪問靜態的方法和變量(數據域),不能調用實例的方法和實例的變量 我們之前提到過,靜態的變量是屬于這個類的方法都可以訪問的數據域,它的值可以被所有方法更改 而靜態的方法就像是專業為靜態變量而生的,它們會對這些靜態的變量進行一系列的操作來打到目的 比如獲得某個變量的值getNumber 而那些實例的變量來說,它們的值是隨時都可以改變的 舉個栗子,之前的圓的半徑的問題 無論是圓1的半徑還是圓2的半徑,它們的值都是屬于它們自己的,都不是共享的 所以去訪問它的不應該是一個靜態的方法,因為靜態的方法是大家共享的一個方法 靜態方法去訪問一個實例變量的時候,由于實例變量往往是屬于某一個方法的,在訪問的時候可能會出現最喜聞樂見的話 “找不到對象” 那我們還是舉個栗子吧 package classhomework; public class ClassHomework { int i = 5; static int k = 2; public static void main(String[] args) { int j = i; m1(); } public void m1() { i = i + k + m2(i , k); } public static int m2(int i, int j) { return (int)(Math.pow (i, j)); } } 上面這個有沒有問題咧 答案在下面 [collapse status="false" title="答案"] package classhomework; public class ClassHomework { int i = 5; static int k = 2; public static void main(String[] args) { int j = i; //在這個方法前面,有個int i = 5 //這也就意味著i是一個實例變量 //但是這個方法里帶有static字眼,表示這玩意是個靜態方法 //我們之前提到過,靜態方法不能調用實例變量 //所以我們這里是會報錯的 m1(); //你看下面的方法m1中有沒有static字眼 //沒錯我也沒找到 //所以m1方法是個實例方法 //然而這個主方法是個靜態的方法 //所以肯定是不行的 } public void m1() { i = i + k + m2(i , k); //你看這里可是個實例方法哦 //實例方法可調用一切 } public static int m2(int i, int j) { return (int)(Math.pow (i, j)); } } 那么問題來了,如果說我一定要在靜態方法里使用實例方法呢 package classhomework; public class ClassHomework { int i = 5; static int k = 2; public static void main(String[] args) { ClassHomework a = new ClassHomework(); //這里其實就是將靜態的方法指定為一個新的方法,然后再在其中作為新的變量插入 int j = a.i; a.m1(); } public void m1() { i = i + k + m2(i , k); } public static int m2(int i, int j) { return (int)(Math.pow (i, j)); } } 啊,這classhomework打的真是煩死了 下次起個短一點的名字 [/collapse] [collapse status="false" title="前情提要(關鍵詞復習)"] primitive type variables 原始數據類型變量 reference type variables 引用類型變量 static ( variable / constant / method ) 靜態的 變量/常量/方法 static variable = class variable static constant ---> final static datatype name 靜態的方法和實例的方法是互相對比滴 [/collapse] [scode type="green"] access specifier 訪問修飾符 [/scode] 寫在前面:access specifier 訪問修飾符 也可以寫作 visibility modifiers 可見性修飾符 我們之前寫代碼的時候,第一條永遠是 public static void main(String[] args) 但是好像沒人問過這句話到底是啥意思 至少我是沒問過的 因為老師肯定會講嘛(攤手) 其實說起訪問修飾符的話,一共是這4個 public 公共的 default 默認的 private 私有的 provate 被保護的 這四個單詞都是用來表示某一個東西是否是可見的 說白了就是在另外一個地方能不能訪問到它 這四個關鍵詞都是用來修飾一個類的,或者是類內部的變量、方法之類的 當我們在寫代碼的時候,我們可以使用不同的可見性修飾符來定義它 比如我們之前在寫圓這個代碼的時候,我們可以使用不同的修飾符來修飾其中不一樣的方法 一定要注意,這個能夠放在類和方法的前面 首先我們先來看 public public 和 static是不一樣的 雖然說我們把使用static將方法設置為一個靜態的方法 也就是所有對象都能夠訪問它 但是這并不意味著他是一個公開的 這兩個單詞所表示的范疇是完全不一樣的 [scode type="blue"]

    • static 是只能夠修飾方法,不能夠修飾類的
    • static 的作用就是把某一個方法或者變量設定為當前類都能夠訪問,當這個變量的值改變的時候,會對當前類產生影響

    • public 當給一個類設定為公共的之后,對于其他的類而言,這個類是可見的 。舉個栗子,我給圓這個類設定為public之后,當我創建一個長方形類的時候,對于長方形這個類來說,圓這個類是可見的。意味著在長方形類里面可以使用Circle cc = new circle; 去訪問和調用圓類的代碼來創建一個對象
    • public 假如我有一瓶肥宅快樂水,當我將這瓶肥宅快樂水設定為public之后,就意味著是共享肥宅快樂水了

    [/scode] [scode type="blue"]

    • default 當我們沒對類進行詳細定義的時候,也就是說類前面是個光頭的時候,就意味著它會默認地使用default
    • default 并不用可刻意地寫在方法前面,當我們沒有這3個字的時候,它就會默認為default
    • default 當一個類被設定為default的時候,其會被默認為 package-private包內訪問,也就意味著能夠在一個包內互相訪問。換句話說 ,隔壁包就無法被訪問了

    [/scode] [scode type="blue"]

    • private 這玩意用來修飾類內部的變量或者方法,并不會修飾一個類
    • private 因為把類設定為私有的話好像就沒啥意義了
    • private 可能就是用來保護啥東西了的

    [/scode] private 這里就不多BB了 感覺以后肯定是超級麻煩的茬 能咸魚一天算一天 [scode type="green"]Private and public in UML[/scode] 那么,在UML中又該怎么表示呢? 讓我猜猜,肯定有人忘了UML是啥 [collapse status="false" title="UML答案--點開了自覺抄10遍"] Unified Modeling Language 統一建模語言 [/collapse] 其實也挺簡單的 如果是private 的話就在方法前加個減號,就像 - 這樣 反過來如果是public 的話就在方法前加個加號,就像 + 這樣 整體來看的話就像這樣

    [scode type="green"]Data Field Encapsulation 數據域封裝[/scode] 這里說到了蟲子(BUG)攻擊 據說電腦BUG之所以叫BUG是因為最原始的電腦真的會被一直蟲子搞的BUG出來 不過今天的可不像以前那樣了 今天我們講究安全性 當我們在寫程序的時候,一般都要有一種意識,就是別人不能隨隨便便改我的程序 就算我留有接口給別人調用都好,但是本應該屬于程序的變量時不會改變的 所以這里就涉及到一個東西,叫 Encapsulation 封裝 說白了就是組裝好了的機械,能夠正常的去運行,但是你并不知道機械內部到底是什么歌情況,也不允許查看其中的東西 當我們在命名一些方法的時候,一般可以用 getter 和 setter 來對其進行命名 getter 就是當我們想獲得一些私人的變量的值的時候,需要寫的一個特定的方法來獲得這個變量的值 setter 也是針對私有的數據域或者改變它的值,才會被稱為setter [scode type="green"]Passing Objects To Methods [/scode] 其實我們可以通過一個小栗子來簡單地理解 package circle; public class TestPassCircle { public static void main(String[] args) { Circle cc = new Circle(10); int n = 5; printAreas(n , cc); System.out.println ("After calling method:"); System.out.println("Radius is " + cc.getRadius()); System.out.println("n is " + n); } public static void printAreas (int times, Circle c) //先看到這里的這個Circle C //我們需要在這個方法中接受一個來自類 Ciecle 的對象(c 變量為屬于類Circle ) //這里感覺就像是拿了一個Circle的變量來用,還是原封不動的那種 { System.out.println("Radius tArea"); while(times >= 1) { System.out.println(c.getRadius() + "t" + c.getArea()); c.setRadius(c.getRadius() + 1); times--; } System.out.println("Radius is " + c.getRadius() + "n"); } } 這玩意輸出結果雖然有蠻多的,但是真正重要的就三行 balabalabala Radius is 15.0 After calling method: Radius is 15.0 n is 5 這里可真正體現了 pass-by-value 的精髓了 你看變量n 最開始我們傳遞過去的時候,它的值是5 這個在傳遞的時候,是把變量的值,也就是10傳遞了過去,而不是傳遞變量本身 變量本身的值還是不會改變的 在方法內部n的值因為循環的原因每一次都在改變 但是無論n的值如何改變,主方法里n的值永遠不會改變,也就是不會影響到主方法里的 這里得和數組在方法之間的傳遞區分開來 我這里就不寫出來了不然看著也亂 數組就是pass-by-Sharing 具體是啥就回到數組哪兒去看看吧 [scode type="green"]array of object[/scode] 記得在之前的時候,我們講過如何創建一個int類型的數組 int[] arrayName = new int[ 10 ]; 那么你可能猜到了,為啥要在講對象的時候提到這個數組列 當然是因為我們有了這個對象數組啦 和int類型的數組一樣,這個也能被簡單地創建出來 Circle[] circleArray = new Circle10; 對比一下之前的那個,是不是非常的相似? 當這個語句運行完成之后,系統就會自動分出一個 Heap 堆 來存放這個玩意 只不過這個里面還是空的,也就是空值 因為在這個時候數組確實是用來存放Circle類的對象,但是這個時候還沒被創建出來 所以這個時候我們需要使用一個循環來生成它們 這里要注意是生成生成,不是像之前那樣的直接賦值 舉個栗子 for(int i = 0; i < circleArray.length; i++) { circleArray[i] = new Circle(5); } 那么為啥之前交生成它們呢? 因為這個數組我們在做的其實是單純的付給它一個 reference variables 就是給它了一個小倉庫的地址 這樣子數組就能夠在每個位置指向屬于它自己的倉庫了

    [scode type="green"]The Scope of Variable 變量的作用域[/scode] 我們之前確實講過變量的作用域 這里之所以再講一次是因為 一個類的代碼包含兩大部分,一個是這個類的數據成員 data fileds (或者可以叫類的變量 class's variables) 第二個部分是類的行為,就是類的對象的行為 不過值得一提的是,當在類里面使用變量的時候,就算先用后聲明也是ok的 這些數據域的成員可以放在整個類的任何一個地方 可以是最開始也可以是最后面都是ok的 舉個栗子 public class Circle { public double findArea() { return radius * radius * Math.PI; } private double radius = 1; } 你看在上面這個例子中,方法findArea位于類Circle中 但是我們是先用再聲明 這樣也不會報錯的 但是有個問題要注意一下 我們來看這樣一個例子 public class F { private int i; private int j = i + 1; } 如果是這樣的話它就會報錯 因為j的值是基于i的值的 所以在這種情況之下就不能交換它們之間的位置 在這里老師引入了一個很有趣的小栗子 這個栗子可以充分幫助我們理解變量的作用域的問題 public class Test { private static int i = 0; private static int j = 0; public static void main(String[] args) { // TODO Auto-generated method stub int i = 2; int k = 3; { int j = 3; System.out.println("i + j is " + i + j); } k = i + j; System.out.println("k is " + k); System.out.println("j is " + j); } } [collapse status="false" title="小栗子答案"] 首先先來說說答案 i + j is 23 k is 2 j is 0 如果能正確地說出答案的話那就沒必要看解析啦 當然為此一次就是沒做對滴 很絕望 那個 i + j 根本不按套路出牌 過分了過分了 public class Test { private static int i = 0; private static int j = 0; //這里的叫做類的變量class's variables //上面講過,這句話無論放在這個類的前面和后面效果都一樣的 public static void main(String[] args) { int i = 2; int j = 3; //這里的就是考點了 //這里的兩個變量,如果在eclipse里面輸入的話,會發現它兩的顏色和上面的類變量不一樣 //因為他們兩個的作用域不同 //這兩個的作用域就是僅僅限于這個block 塊的 //我們可以看到,優先級還是以方法內的優先 //就算外面有個類變量,方法內的變量還是被優先考慮的 { int j = 3; //老師說過,變量的作用域表示的就是它所在的這個塊 block //然而區分每個塊的標志就是花括號 //這里會優先以 j = 3 來計算 System.out.println("i + j is " + i + j); } k = i + j; //在上面的 j = 3 的作用域已經完成,這里就不屬于它的作用域了 //所以我們往上找找,剩下的就只是類變量里的 j = 0了 //所以在這里j的值應該為0 System.out.println("k is " + k); System.out.println("j is " + j); } } [/collapse] [scode type="green"]The this reference [/scode] 接下來我們來講一個關鍵字,這個 就是這個 “這個” this this表示的就是某個變量 其實我們平時在寫代碼的時候都沒寫 this 這個關鍵字,是因為Java自動幫我們加上去了 因為每個變量都得寫這玩意的話看著都煩 當然寫上才是正確的姿勢 那么這個時候可能有人會問了,有什么意義呢 還真有些時候必須要自己寫上 private double radius; public void setRadius (double radius) { radius = radius; } 你看這里就是個小栗子 雖然這樣子確實是不會報錯 但是會有一個警告 因為Java根本不知道到底左邊的是啥右邊的是啥 這個時候就需要加個this了 我們將賦值語句改為 this.radius = radius; 用來表示左邊的這個是我們類的變量半徑,右邊的是接收到的 哦對了this還有個很高端的操作 因為它在類里面可以指代這個類本身 比如我們需要調用這個類的構造方法的時候,我們就會使用 Circle(10); 但是用this來表示的話,可以寫成這樣 this(10); 表示的效果都是一樣的 Chapter 10: Object-Oriented Thinking Class absraction 類的抽象 class encapsulation 類的封裝 我們在用很多方法的時候,很多時候我們都不知道這玩意到底該怎么用的 就是只知道怎么使用就行了 其實在Java世界里,所有的對象所有的方法都是會被寫在類里面的 我們在寫代碼的時候往往都會先定義一個類出來 然后我們再在類里面去寫代碼 所以我們之前討論到的方法的抽象和封裝實際上就是類的抽象和封裝 結束語 在這里感謝抽出寶貴時間幫我檢查筆記的CC Teacher~ 感謝網頁沒有在我碼字到一半的時候崩潰 感謝我的小博客 感謝自己高中買的咖啡豆還能喝還沒過期 還要感謝小獅子!!! 小獅子天下第一!!!!

    • ----to be continue

    總結

    以上是生活随笔為你收集整理的面向对象程序设计_面向对象的程序设计(续)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。