1. 程式人生 > 實用技巧 >12月6日

12月6日

排序方法

氣泡排序,總共有八大排序

package array;

import java.util.Arrays;

public class Demo4 {
public static void main(String[] args) {
int[]a={5,9,78,8977,7,8,89,13};
int[]sort=sort(a);
System.out.println(Arrays.toString(sort));
}
//氣泡排序:比較陣列中,兩個相鄰的元素,如果第一個數比第二個數大,我們就交換他們的位置
//每一次比較,都會產生一個最大或者最小的數字
//下一輪則可以少一次迴圈
//一次迴圈,知道結束
public static int[] sort(int[] array) {
//外層迴圈,判斷要走多少次;
for (int i = 0; i < array.length-1; i++) {
//內層迴圈,比較判斷兩個數,如果前一個比後一個大,就交換位置
for (int j = 0; j <array.length-i-1 ; j++) {
if (array[j+1]<array[j]){
int temp=0;
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
return array;
}
}

稀疏陣列

是一種資料結構

遍歷二維陣列:

用for,each迴圈

 for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}

增強for迴圈,打array1.for和ints.for就有

把二維陣列的每個陣列元素先給陣列ints,再遍歷ints裡的每個數

 int count=0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j <array1[i].length ; j++) {
if(array1[i][j]!=0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}

在遍歷二維陣列時,注意如果要對每個元素進行判斷,就不能用增強型for迴圈,而是老老實實寫兩層,外層迴圈是以二維陣列的長度為迴圈次數,內層則以每個元素陣列的個數為迴圈次數。

面向物件(00P)

初識面向物件

正確的寫法應該是:以類的方式組織程式碼,以物件的形式封裝資料

方法回顧與加深

方法的呼叫

如果在A類呼叫B類中的方法,就需要判斷B類的這個方法是不是靜態方法,即宣告時有沒有stati修飾,如果有

則可以直接B.fangfa這種形式來呼叫

如果沒有,則需要例項化這個類再呼叫,即設計new

物件型別 物件名 =物件值(new 物件型別)

然後再通過物件名.方法來呼叫

同一個類的方法互相呼叫

public class Demo1{
public static void main(String[] args){}
public static void a(){
b()
}
public void b(){
...
}
}

這種是錯的,ab都是非靜態或者都是靜態是可以的,但是a靜態,b非靜態,a呼叫b方法不行

解釋:static方法是和類一起載入的,而非靜態方法是必須等類例項化(new一個)之後才存在,所以時間順序出錯無法呼叫。

比較靜態方法和非靜態方法的區別

public class Demo1 {
public static void main(String[] args) {
int add = Demo1.add(1, 2);
System.out.println(add);
}
public static int add(int a,int b){
return a+b;
}
}

靜態的不需要例項化,即不不用new一個物件,直接通過類名.方法呼叫即可

public class Demo1 {
public static void main(String[] args) {
Demo1 demo1=new Demo1();
int add = demo1.add(1, 2);
System.out.println(add);
}
public int add(int a,int b){
return a+b;
}
}

非靜態的要先new一個物件,通過這個物件.方法名來呼叫。

值傳遞和引用傳遞

之前說的java一定是值傳遞

值傳遞

public class Demo2 {
public static void main(String[] args) {
int a=1;
Demo2.change(a);
System.out.println(a);
}
public static int change(int a){
return a=10;
}
}

引用傳遞

public class Demp3 {
public static void main(String[] args) {
Person person=new Person();
System.out.println(person.name);
Demp3.change(person);
System.out.println(person.name);
}
public static void change(Person person){
person.name="xyj";
}
}
class Person{
String name; //沒賦值時應該為null
}

這裡小注意:只能有一個public類,但可以定義其他的非public類,注意一定要放在public類的外面定義

注意這裡的區別,第一個經過change方法後並沒有改變a的大小,輸出的仍然是1

第二個經過change後person的屬性name確實改變了,這個後面才能解釋(面向物件和記憶體)

物件的建立分析

類與物件的關係

物件例項化就是用的new

先輸入new student後,還是一樣的alt加回車,自動建立一個student物件

student物件就是一個Student類的具體例項。

構造器

一個類即使什麼都不寫,它也會存在一個方法,開啟class檔案可以看到顯示的就是定義構造器

具體舉例

public class Student {
}

我先構造一個空的類,什麼方法屬性都不寫;

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

然後我在main方法裡建立Student例項,發現程式並沒有問題。

回頭看Student的class檔案

public class Student {
    public Student() {
    }
}

會發現編譯時自動建立了一個public Student()

這個就稱作構造方法/構造器

就像前面說的構造方法必須和類的名字相同,必須沒有返回值,也沒有void

這裡叫做無參構造

注意無參構造可以用於建立例項時初始化值,因為一旦建立例項,就必須走一遍構造器

public class Student {
    String name;
    public Student(){
        this.name="yj";
    }
}

這裡這個this指代的就是這個物件。所以物件一建立name預設是yj。


但是還有有參構造,這裡一定注意,沒有有參構造時,無參構造也可以不寫,因為系統編譯時會預設生成一個無參構造器,但是

一旦有了有參構造,系統就不會生成無參構造器了,就必須自己手動寫(顯示定義),如果一個類只有有參構造就會報錯。

public class Student {
    String name;
    public Student(String name){
        this.name=name;
    }
}

這裡注意this.name指代的是物件的name,而後面的name指形參,也就是傳進來的引數。(this.表示當前類的)

public class Student {
    String name;
    public Student{
    }
    public Student(String name){
        this.name=name;
    }
}

應該這樣寫,無參構造器空著,然後在例項化物件時

Student student = new Student("yj");

就會根據你給的引數跳到有參構造器,這也就是方法的過載!

總結

面向物件的三大特性

封裝

繼承

extends關鍵字

寫了三個程式碼:

package extend.demo1;
import extend.demo2.Person;
import extend.demo3.Student;

public class Application {
public static void main(String[] args) {
Student student = new Student();
student.print();
student.test1();
}
}

package extend.demo3;

import extend.demo2.Person;

public class Student extends Person {
public Student() {
System.out.println("Student無參執行了");
}
private String name = "yj";
public void print(){
System.out.println("student");
}
public void test1(){
print();
this.print();
super.print();
}
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}

這裡test方法呼叫時就會發現,如果先輸出的是給形參的name,再輸出student的name,最後輸出父類的

注意,所有private的東西都是無法繼承的

package extend.demo2;

public class Person {
public Person() {
System.out.println("Person無參執行了");
}
public void print(){
System.out.println("Person");
}
}

其中Person是Student的父類。

可以發現我們用super來呼叫父類的同名的方法,子類的加this或者不加都是直接呼叫子類的

重要:子類和父類的無參構造器同時有語句要執行時,會發現先執行了父類的無參構造器

這裡其實在子類的無參構造器中還省略了一句super()用來呼叫父類的構造器;

如果手動寫出來且放在無參構造器中語句的下面還會報錯,說明確實super()要先執行(所以才會先執行父類的無參構造器)

super()必須在子類構造器的第一行

super詳解

super()這個方法的作用是在子類中呼叫父類的無參構造器,且必須放在子類的構造器的第一行

對比一下this()這個方法,這個可以呼叫子類自己的有參構造器

public Student() {
    this("yj");
    System.out.println(this.name);
}
public Student(String name) {
    super("name");
    System.out.println("Student無參執行了");
}

像這裡一個無參構造,一個有參構造,可以在無參構造中通過this("yj");就是通過給this()一個引數來呼叫相應的有參構造

這裡有個問題,也就是this()也必須在第一行,與super()起衝突,所以構造器中this()與super()只能用一個。

還要注意:super()是預設呼叫的,即使不寫也會呼叫的。但如果用this()來呼叫自己的有參構造器,這裡預設呼叫的super()就不再呼叫了。舉例子

子類:

public class Student extends Person {
    public Student() {
        this("yj");
        System.out.println(this.name);
        System.out.println("Student無參執行了");
    }
    public Student(String name) {
        super("name");
        System.out.println("Student有參執行了");
    }

父類:

public Person() {
    System.out.println("Person無參執行了");
}
public Person(String name) {
    System.out.println("Person有參執行了");
}

main方法中我以無參的形式例項化一個Student物件

Student student = new Student();

則得到的結果為

具體順序為:無參,先呼叫student的無參構造器,然後由於this(“yj”)命令,不再執行super(),即不再呼叫父類的無參

先呼叫自己的有參,自己的有參第一行是super("name");呼叫父類的有參,故第一個輸出Person有參執行了

再輸出Student有參執行了,最後再把student的無參剩下的給走完。

同理,我把this(“yj”)刪掉,則得到:

這樣的結果,雖然沒有寫super(),但它還是預設先呼叫父類的無參構造器。

最後補充一點,如果父類只有有參構造,沒寫無參構造,這按照前面的說法應該是錯誤的。

此時子類的無參寫不寫都會出錯(本身父類就沒無參)

但是如果在子類的無參中呼叫了父類的有參

即super(“yj”);

這樣的話子類是不會報錯,能成功建立物件且先呼叫父類的有參再執行自身的無參

當然,父類沒有無參的話是無法建立父類物件的,只是父類的有參被子類的無參呼叫了就不會影響子類的使用。

總結

抽象類和介面

內部類及OOP實戰

小技巧

demo1.add(1, 2);
int add = demo1.add(1, 2);

輸完第一行後按alt加回車,可以自動把這個值給一個自動建立的變數。

點這個可以把內碼表放右邊進行對比

一個專案只能有一個main方法,一般放在一個叫Application的類中

其餘的每個類中去定義要用的類,注意類只能有一個public類。

如何把class檔案新增到目錄下

先點選專案結構

新增根目錄,把out目錄新增進來即可。

alt加Insert,自動生成構造器

選擇Constructor構造器

選擇就是有參構造器,Select None就是無參構造器

還可以直接生成get和set方法